Created
September 22, 2011 08:52
decorator soup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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