Created
February 10, 2009 17:55
-
-
Save zvoase/61496 to your computer and use it in GitHub Desktop.
This file contains 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
class CallSuper(Exception): pass | |
def callsuper(method): | |
""" | |
Decorator for calling the super method automagically. | |
In the submethod, if a ``CallSuper`` exception is raised at any point, then | |
the wrapper will look up the class's MRO (method resolution order) for a | |
method of the same name. If none is found, the exception is allowed to | |
permeate. If one is found, it too is wrapped with the ``callsuper`` | |
decorator and called with the arguments passed to ``CallSuper.__init__()``. | |
""" | |
def callsuper_wrapper(self, *args): | |
try: | |
return method(self, *args) | |
except CallSuper, exc: | |
supermethod, name = None, method.__name__ | |
for base in self.__class__.mro()[1:]: | |
if (hasattr(base, name) and | |
hasattr(getattr(base, name), '__call__')): | |
supermethod = callsuper(getattr(base, name)) | |
break | |
if not supermethod: | |
raise | |
return supermethod(self, *exc.args) | |
callsuper_wrapper.__name__ = method.__name__ | |
callsuper_wrapper.__doc__ = method.__doc__ | |
return callsuper_wrapper | |
# Test it out | |
global COUNTER | |
COUNTER = 0 | |
class SuperClass(object): | |
def method(self): | |
global COUNTER | |
COUNTER += 1 # Increment counter. | |
class SubClass(SuperClass): | |
@callsuper | |
def method(self): | |
global COUNTER | |
COUNTER += 1 # Increment counter. | |
raise CallSuper | |
SubClass().method() | |
assert COUNTER == 2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment