Thread: [Pyobjc-dev] PyObjcC class method swizzling
Brought to you by:
ronaldoussoren
From: Lukas P. | D. V. <lu...@dr...> - 2009-09-19 12:02:57
|
Hi everyone! I've just recently started to explore the power of PyObjC by rewriting the GPGMail plugin and I'm more than impressed. A big compliment to the developers! Unfortunately at the moment I'm stuck with class method swizzling. I've found a very nice decorator which can be used to swizzle instance methods: def swizzle(*args): cls, SEL = args def decorator(func): oldIMP = cls.instanceMethodForSelector_(SEL) def wrapper(self, *args, **kwargs): return func(self, oldIMP, *args, **kwargs) newMethod = objc.selector(wrapper, selector = oldIMP.selector, signature = oldIMP.signature) objc.classAddMethod(cls, SEL, newMethod) return wrapper return decorator My poor attempt to convert this into a decorator which swizzles class methods looks like the one below, but unfortunately doesn't work. def swizzleClassMethod(*args): cls, SEL = args def decorator(func): oldIMP = cls.methodForSelector_(SEL) def wrapper(klass, *args, **kwargs): return func(klass, oldIMP, *args, **kwargs) newMethod = objc.selector(wrapper, selector = oldIMP.selector, signature = oldIMP.signature) objc.classAddMethod(cls, SEL, newMethod) return wrapper return decorator I'd really appreciate it, if someone could help me to find out how to do this. What I wanna do with that is replacing the + sharedPreferences class method of the NSPreferences class with my own implementation and call the original method from within there. Please anyone point me into the right direction, so I can finally finish the GPGMail plugin. Thanks in advance Lukas |
From: Aahz <aa...@py...> - 2009-09-20 14:38:23
|
On Sat, Sep 19, 2009, Lukas Pitschl | Dressy Vagabonds wrote: > > Unfortunately at the moment I'm stuck with class method swizzling. > I've found a very nice decorator which can be used to swizzle instance > methods: Could you please explain what "swizzling" is? I've never heard the term before, and I haven't, it's likely other people haven't, either -- more efficient for you to explain than force everyone to JFGI. -- Aahz (aa...@py...) <*> http://www.pythoncraft.com/ "I won't accept a model of the universe in which free will, omniscient gods, and atheism are simultaneously true." --M |
From: Lukas P. | D. V. <lu...@dr...> - 2009-09-20 16:45:47
|
Oh, right, that's a good idea. Instance method or class method swizzling is basically the idea of replacing an existing class/instance method implementation with your own implementation, however differently from using categories, since the original implementation should be preserved to later use it in your own implementation of the mehtod. This allows you to add additional functionality to the original method implementation, in my case for example to add a preferences pane to Mail.app which is otherwise not possible. I hope this explains a little better what i'm looking for. Thx for in advance for any help Lukas Am 20.09.2009 um 16:38 schrieb Aahz: > On Sat, Sep 19, 2009, Lukas Pitschl | Dressy Vagabonds wrote: >> >> Unfortunately at the moment I'm stuck with class method swizzling. >> I've found a very nice decorator which can be used to swizzle >> instance >> methods: > > Could you please explain what "swizzling" is? I've never heard the > term > before, and I haven't, it's likely other people haven't, either -- > more > efficient for you to explain than force everyone to JFGI. > -- > Aahz (aa...@py...) <*> http://www.pythoncraft.com/ > > "I won't accept a model of the universe in which free will, omniscient > gods, and atheism are simultaneously true." --M > > ------------------------------------------------------------------------------ > Come build with us! The BlackBerry® Developer Conference in SF, CA > is the only developer event you need to attend this year. Jumpstart > your > developing skills, take BlackBerry mobile applications to market and > stay > ahead of the curve. Join us from November 9-12, 2009. Register > now! > http://p.sf.net/sfu/devconf > _______________________________________________ > Pyobjc-dev mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyobjc-dev |
From: James R E. <Jam...@lr...> - 2009-09-20 17:11:25
Attachments:
smime.p7s
|
Hi Lukas, Here's a copy of the method i use. I haven't tried swizzling any classmethods, so it may or may not work for your purposes. One problem I've had in particular with PyObjC decorators is that Objective-C and consequently PyObjC don't like *args and **kwargs- style parameters very well. My workaround is to inspect the decorated method and return the appropriate version from a lookup table. This works in most reasonable cases, but it not as clean as I'd like (If anyone else has a better suggestion, I'd love to hear it!). Anyways, here's my swizzle decorator : # Replacement wrapper lambdas depending on the number of parameters required. Support up to 8 # parameters, including self. This is necessary to suppress a PyObjC DeprecationWarning about # Not all Objective-C arguments being present in the Python argument list (collapsed as *args). __swizzleIMPMap = {0: lambda f: lambda: f(), 1: lambda f: lambda self: f(self), 2: lambda f: lambda self, a: f(self, a), 3: lambda f: lambda self, a, b: f(self, a, b), 4: lambda f: lambda self, a, b, c: f(self, a, b, c), 5: lambda f: lambda self, a, b, c, d: f(self, a, b, c, d), 6: lambda f: lambda self, a, b, c, d, e: f(self, a, b, c, d, e), 7: lambda f: lambda self, a, b, c, d, e, g: f (self, a, b, c, d, e, g), 8: lambda f: lambda self, a, b, c, d, e, g, h: f (self, a, b, c, d, e, g, h), } def swizzleMethod(old): def swizzleWithNewMethod_(f): cls = old.definingClass oldSelectorName = old.__name__.replace("_", ":") oldIMP = cls.instanceMethodForSelector_(oldSelectorName) newSelectorName = f.__name__.replace("_", ":") argc = len(inspect.getargspec(f)[0]) newSEL = objc.selector(f, selector=newSelectorName, signature=old.signature) #oldSEL = objc.selector(lambda self, *args: oldIMP(self, *args), selector=newSelectorName, signature=old.signature) oldSEL = objc.selector(__swizzleIMPMap[argc](oldIMP), selector=newSelectorName, signature=old.signature) # Swap the two methods objc.classAddMethod(cls, newSelectorName, oldSEL) objc.classAddMethod(cls, oldSelectorName, newSEL) #NSLog(u"Swizzled %s.%s <-> %s" % (cls.__name__, oldSelectorName, newSelectorName)) return f return swizzleWithNewMethod_ Use it like this: @swizzle(NSPreferences.sharedPreferences) # Note: this hasn't been tested with classmethods! def sharedPreferences(self): # ... self.sharedPreferences() # Calls the original method # ... Cheers! James Le 19 sept. 2009 à 14:02, Lukas Pitschl | Dressy Vagabonds a écrit : > Hi everyone! > > I've just recently started to explore the power of PyObjC by rewriting > the GPGMail plugin and I'm more than impressed. > A big compliment to the developers! > > Unfortunately at the moment I'm stuck with class method swizzling. > I've found a very nice decorator which can be used > to swizzle instance methods: > > def swizzle(*args): > cls, SEL = args > def decorator(func): > oldIMP = cls.instanceMethodForSelector_(SEL) > def wrapper(self, *args, **kwargs): > return func(self, oldIMP, *args, **kwargs) > newMethod = objc.selector(wrapper, > selector = oldIMP.selector, > signature = oldIMP.signature) > objc.classAddMethod(cls, SEL, newMethod) > return wrapper > return decorator > > My poor attempt to convert this into a decorator which swizzles class > methods looks like the one below, but unfortunately doesn't > work. > > def swizzleClassMethod(*args): > cls, SEL = args > def decorator(func): > oldIMP = cls.methodForSelector_(SEL) > def wrapper(klass, *args, **kwargs): > return func(klass, oldIMP, *args, **kwargs) > newMethod = objc.selector(wrapper, > selector = oldIMP.selector, > signature = oldIMP.signature) > objc.classAddMethod(cls, SEL, newMethod) > return wrapper > return decorator > > I'd really appreciate it, if someone could help me to find out how to > do this. > What I wanna do with that is replacing the + sharedPreferences class > method of the NSPreferences class > with my own implementation and call the original method from within > there. > > Please anyone point me into the right direction, so I can finally > finish the GPGMail plugin. > > Thanks in advance > > Lukas > > ------------------------------------------------------------------------------ > Come build with us! The BlackBerry® Developer Conference in SF, CA > is the only developer event you need to attend this year. Jumpstart > your > developing skills, take BlackBerry mobile applications to market and > stay > ahead of the curve. Join us from November 9-12, 2009. Register > now! > http://p.sf.net/sfu/devconf > _______________________________________________ > Pyobjc-dev mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyobjc-dev |
From: Aahz <aa...@py...> - 2009-09-20 17:14:25
|
On Sun, Sep 20, 2009, Lukas Pitschl | Dressy Vagabonds wrote: > > Instance method or class method swizzling is basically the idea of > replacing an existing class/instance method implementation with your > own implementation, however differently from using categories, since > the original implementation should be preserved to later use it in > your own implementation of the mehtod. How is this different from proxying or monkey-patching? -- Aahz (aa...@py...) <*> http://www.pythoncraft.com/ "I won't accept a model of the universe in which free will, omniscient gods, and atheism are simultaneously true." --M |
From: Lukas P. | D. V. <lu...@dr...> - 2009-09-20 23:46:22
|
That might be same, don't really know those terms. The important thing is that they do the same thing being, replacing the original implementation with a custom one and preserve the original one to call it in the custom one. Any idea Aahz on how to do that? @ James: Thanks, I'll try that immediately! Lukas Am 20.09.2009 um 19:14 schrieb Aahz: > On Sun, Sep 20, 2009, Lukas Pitschl | Dressy Vagabonds wrote: >> >> Instance method or class method swizzling is basically the idea of >> replacing an existing class/instance method implementation with your >> own implementation, however differently from using categories, since >> the original implementation should be preserved to later use it in >> your own implementation of the mehtod. > > How is this different from proxying or monkey-patching? > -- > Aahz (aa...@py...) <*> http://www.pythoncraft.com/ > > "I won't accept a model of the universe in which free will, omniscient > gods, and atheism are simultaneously true." --M > > ------------------------------------------------------------------------------ > Come build with us! The BlackBerry® Developer Conference in SF, CA > is the only developer event you need to attend this year. Jumpstart > your > developing skills, take BlackBerry mobile applications to market and > stay > ahead of the curve. Join us from November 9-12, 2009. Register > now! > http://p.sf.net/sfu/devconf > _______________________________________________ > Pyobjc-dev mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyobjc-dev |
From: Aahz <aa...@py...> - 2009-09-20 23:57:27
|
On Mon, Sep 21, 2009, Lukas Pitschl | Dressy Vagabonds wrote: > > That might be same, don't really know those terms. The important > thing is that they do the same thing being, replacing the original > implementation with a custom one and preserve the original one to call > it in the custom one. > > Any idea Aahz on how to do that? That's basically what decorators do, here are a couple of hits from Googling "python decorator tutorial": http://www.artima.com/weblogs/viewpost.jsp?thread=240808 http://uswaretech.com/blog/2009/06/understanding-decorators/ -- Aahz (aa...@py...) <*> http://www.pythoncraft.com/ "I won't accept a model of the universe in which free will, omniscient gods, and atheism are simultaneously true." --M |
From: Lukas P. | D. V. <lu...@dr...> - 2009-09-21 00:49:18
|
Of course you'd use a decorator, the problem is that PyObjC doesn't like it if you combine @classmethod and @swizzle (dealing with the swizzle). I still haven't found out why that is, but it simply won't work Am 21.09.2009 um 01:57 schrieb Aahz: > On Mon, Sep 21, 2009, Lukas Pitschl | Dressy Vagabonds wrote: >> >> That might be same, don't really know those terms. The important >> thing is that they do the same thing being, replacing the original >> implementation with a custom one and preserve the original one to >> call >> it in the custom one. >> >> Any idea Aahz on how to do that? > > That's basically what decorators do, here are a couple of hits from > Googling "python decorator tutorial": > > http://www.artima.com/weblogs/viewpost.jsp?thread=240808 > http://uswaretech.com/blog/2009/06/understanding-decorators/ > -- > Aahz (aa...@py...) <*> http://www.pythoncraft.com/ > > "I won't accept a model of the universe in which free will, omniscient > gods, and atheism are simultaneously true." --M > > ------------------------------------------------------------------------------ > Come build with us! The BlackBerry® Developer Conference in SF, CA > is the only developer event you need to attend this year. Jumpstart > your > developing skills, take BlackBerry mobile applications to market and > stay > ahead of the curve. Join us from November 9-12, 2009. Register > now! > http://p.sf.net/sfu/devconf > _______________________________________________ > Pyobjc-dev mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyobjc-dev |
From: Lukas P. | D. V. <lu...@dr...> - 2009-09-21 10:49:40
|
Just for information: I've now decided to change strategy and implement the class method swizzling in Objective-C. That works like a charm. I'm still interested though in any solutions to this problems, since I don't want to load many objective-c frameworks into my plugin. Thx for the help everyone Lukas Am 21.09.2009 um 02:20 schrieb Lukas Pitschl | Dressy Vagabonds: > Of course you'd use a decorator, the problem is that PyObjC doesn't > like it if you combine @classmethod and @swizzle (dealing with the > swizzle). > I still haven't found out why that is, but it simply won't work > > > Am 21.09.2009 um 01:57 schrieb Aahz: > >> On Mon, Sep 21, 2009, Lukas Pitschl | Dressy Vagabonds wrote: >>> >>> That might be same, don't really know those terms. The important >>> thing is that they do the same thing being, replacing the original >>> implementation with a custom one and preserve the original one to >>> call >>> it in the custom one. >>> >>> Any idea Aahz on how to do that? >> >> That's basically what decorators do, here are a couple of hits from >> Googling "python decorator tutorial": >> >> http://www.artima.com/weblogs/viewpost.jsp?thread=240808 >> http://uswaretech.com/blog/2009/06/understanding-decorators/ >> -- >> Aahz (aa...@py...) <*> http://www.pythoncraft.com/ >> >> "I won't accept a model of the universe in which free will, >> omniscient >> gods, and atheism are simultaneously true." --M >> >> ------------------------------------------------------------------------------ >> Come build with us! The BlackBerry® Developer Conference in SF, >> CA >> is the only developer event you need to attend this year. Jumpstart >> your >> developing skills, take BlackBerry mobile applications to market and >> stay >> ahead of the curve. Join us from November 9-12, 2009. Register >> now! >> http://p.sf.net/sfu/devconf >> _______________________________________________ >> Pyobjc-dev mailing list >> Pyo...@li... >> https://lists.sourceforge.net/lists/listinfo/pyobjc-dev > > > ------------------------------------------------------------------------------ > Come build with us! The BlackBerry® Developer Conference in SF, CA > is the only developer event you need to attend this year. Jumpstart > your > developing skills, take BlackBerry mobile applications to market and > stay > ahead of the curve. Join us from November 9-12, 2009. Register > now! > http://p.sf.net/sfu/devconf > _______________________________________________ > Pyobjc-dev mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyobjc-dev |
From: Ronald O. <ron...@ma...> - 2009-09-29 20:41:25
Attachments:
smime.p7s
|
On 19 Sep, 2009, at 14:02, Lukas Pitschl | Dressy Vagabonds wrote: > Hi everyone! > > I've just recently started to explore the power of PyObjC by rewriting > the GPGMail plugin and I'm more than impressed. > A big compliment to the developers! > > Unfortunately at the moment I'm stuck with class method swizzling. > I've found a very nice decorator which can be used > to swizzle instance methods: > > def swizzle(*args): > cls, SEL = args > def decorator(func): > oldIMP = cls.instanceMethodForSelector_(SEL) > def wrapper(self, *args, **kwargs): > return func(self, oldIMP, *args, **kwargs) > newMethod = objc.selector(wrapper, > selector = oldIMP.selector, > signature = oldIMP.signature) > objc.classAddMethod(cls, SEL, newMethod) > return wrapper > return decorator > > My poor attempt to convert this into a decorator which swizzles class > methods looks like the one below, but unfortunately doesn't > work. > > def swizzleClassMethod(*args): > cls, SEL = args > def decorator(func): > oldIMP = cls.methodForSelector_(SEL) > def wrapper(klass, *args, **kwargs): > return func(klass, oldIMP, *args, **kwargs) > newMethod = objc.selector(wrapper, > selector = oldIMP.selector, > signature = oldIMP.signature) > objc.classAddMethod(cls, SEL, newMethod) > return wrapper > return decorator Have you tried adding "isClassMethod=True" to the argument list of objc.selector? Your current code creates an instance method. Ronald |