Skip to content

Instantly share code, notes, and snippets.

@zvoase
Created February 10, 2009 17:55
Show Gist options
  • Save zvoase/61496 to your computer and use it in GitHub Desktop.
Save zvoase/61496 to your computer and use it in GitHub Desktop.
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