Skip to content

Instantly share code, notes, and snippets.

@dropwhile
Created September 22, 2011 08:52
Show Gist options
  • Save dropwhile/1234373 to your computer and use it in GitHub Desktop.
Save dropwhile/1234373 to your computer and use it in GitHub Desktop.
decorator soup
import functools
def _decorate_method(f, name):
@functools.wraps(f)
def __wrapper(self, *args, **kwds):
print 'wrapped a method', f, name
return f(self, *args, **kwds)
return __wrapper
def _decorate_class(cls, name):
original_init = cls.__init__
def __init_wrapper(self, *args, **kwds):
print 'wrapped a class __init__', cls, name
return original_init(self, *args, **kwds)
cls.__init__ = __init_wrapper
return cls
def _make_decorator(name, f):
if isinstance(f, type):
print 'decorating class', f, name
return _decorate_class(f, name)
else:
print 'decorating method', f, name
return _decorate_method(f, name)
def my_decorator(arg='some-default'):
"""
decorator generator logic engine wrapper
determines if the thing to be wrapped is a method or a class, then
calls the appropriate decorator generator
"""
if isinstance(arg, str):
# requires partial application, because the return must be a
# function that takes a function as its argument
return functools.partial(_make_decorator, arg)
else:
return _make_decorator('some-default', arg)
## examples
@my_decorator
@my_decorator()
@my_decorator('not-bar')
class Foo(object):
@my_decorator
def something_a(self):
pass
@my_decorator()
def something_b(self):
pass
@my_decorator('not-foo')
def something_c(self):
pass
print 'instantiation here'
f = Foo()
print 'calling methods'
f.something_a()
f.something_b()
f.something_c()
## output
# decorating method <function something_a at 0x10f4a1320> some-default
# decorating method <function something_b at 0x10f4a1410> some-default
# decorating method <function something_c at 0x10f4a1500> not-foo
# decorating class <class '__main__.Foo'> not-bar
# decorating class <class '__main__.Foo'> some-default
# decorating class <class '__main__.Foo'> some-default
# instantiation here
# wrapped a class __init__ <class '__main__.Foo'> some-default
# wrapped a class __init__ <class '__main__.Foo'> some-default
# wrapped a class __init__ <class '__main__.Foo'> not-bar
# calling methods
# wrapped a method <function something_a at 0x10f4a1320> some-default
# wrapped a method <function something_b at 0x10f4a1410> some-default
# wrapped a method <function something_c at 0x10f4a1500> not-foo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment