I am writing a generic class decorator which needs to apply a decorator to each method. My first approach is something like this:
def class_decorator(cls):
for name, member in vars(cls).items():
# Ignore anything that is not a method
if not isinstance(member, (types.FunctionType, types.BuiltinFunctionType, classmethod, staticmethod)):
continue
setattr(cls, name, method_decorator(member))
return cls
The decorator itself is not very important. Looks something like this:
def method_decorator(fn):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
# do something
return fn(*args, **kwargs):
return wrapper
Once I tested it, I ran into the problem that this does not work with static or class methods, and the following error is raised from functools.wraps
:
AttributeError: 'classmethod' object has no attribute '__module__'
Yeah, classmethod
or staticmethods
are not normal functions, not even callables. Generally if you need to decorate a classmethod
, you first apply your decorator and then the classmethod
decorator, but since this is a class decorator, I cannot influence the order of the decorators.
Any good solution for this?