Optional keywords in python decorators

…so the challenge is to create a dectorator that accepts either no parameters, or accepts any number of keyword parameters. That is

@zing
def woo() :
pass

@zing(off=’on’)
def pop() :
pass

The problem is, for woo, the decorator is going to get called once with zing(woo), and the result should be a function with the signature of the target function.

For pop, it’s more complicated:

+ first, call with zing(**kwargs), expect build(function) back
+ call build(pop), expect a function with the same signature as the original
+ call that function

So I took a hint from the web, and based the logic on the type of the first parameter, if there is one. Then I switched it around to take advantage of the fact that there will either be one argument (the target function), or else there will be keyword arguments. But not both.

If there are keywords, the code resolves them and bakes them into a closure. Which is itself inside a closure.

def woop(*args,**kwargs):
    if len(args) and callable(args[0]) :
        return _wrap(args[0],'simple')
    else :
        extra = kwargs.get('extra','nope')
        def build(target):
            return _wrap(target,extra)
        return build
        
def _wrap(target,extra):
    def woop_woop(that,a):
        return 'woop:' + target(that,a) + '.' + extra + ':woop'
    return woop_woop
    
class Ping(object):
    @woop
    def zong(self,a):
        return a
    
    @woop(extra='zzz')
    def zing(self,a):
        return a
    
    @woop(sleep='woo')
    def nope(self,a):
        return a

p = Ping()
print p.zong('aaa')
print p.zing('bbb')
print p.nope('ccc')
Advertisements

Leave a comment

Filed under utility

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s