Re: [Pyobjc-dev] Crafting wrapped API?
Brought to you by:
ronaldoussoren
From: Jonathan L. <pan...@sk...> - 2005-10-04 17:09:17
|
> The sort of things that we have done, with success, is add cover > API implemented through lambdas or def'd functions that essentially > rename auto-wrapped API. > > For example, if PyObjC exposes: > > FooBar.setRadius_() > FooBar.setReferenceAssetPath_componentPath_() > > We might have this extra goop in our __init__.py for the module: > > FooBar.setRadius = lambda self, val: self.setRadius_(val) > FooBar.setReference = lambda self, assetPath, componentPath: > self.setReferenceAssetPath_componentPath_(assetPath, componentPath) > > This allows python callers to use setRadius() and setReference() > instead of the other names. > > The issue with this is for subclassers. Subclassers cannot > override the new names and have that work back in Obj-C land. They > must override the original names. > > I have had similar frustrations with the way that PyObjC does its selector mapping. Its dirt simple, and easy to understand, but my code ends up looking kind of ugly. I have had great success in using metaclasses to do some of the mapping things that you are wanting to do to make my code a bit more palatable. I find all the insane underscores in my PyObjC code to make it difficult to read, so I implemented a simple metaclass and a decorator to allow me to name my methods whatever I want, and then map (or "export") them with a more Obj-C like name. I don't have the current code on me, so I whipped up an example of what it sort of looks like (this requires Python 2.4+): import types # the metaclass class ObjcMeta(type): def __init__(cls, name, bases, dict): items = (item for item in dict.values() if type(item) is types.FunctionType and hasattr(item, 'selector')) for item in items: newname = item.selector.replace(':', '_') setattr(cls, newname, item) # the decorator def export(selector): def export_proxy(method): method.selector = selector return method return export_proxy # a test class class Test(object): __metaclass__ = ObjcMeta @export('updatePerson:withName:') def updatePersonWithName(self, person, name): print 'updating person:', person, 'with name:', name if __name__ == '__main__': t = Test() t.updatePerson_withName_('Jon', 'Jonathan') t.updatePersonWithName('Jon', 'Jonathan') I am not sure if this will help, but it allows you do expose your methods the way that you would like. Granted, its a very simplistic approach, but I think it makes my PyObjC code look a heck of a lot more readable. If I were trying to do what you are doing, I would use this approach, along with Bob's suggested facades to get the desired result. I hope this helps, at least a little bit. -- Jonathan |