When we decorate function, we use functools.wraps to make decorated function look like original.
Is there any wat to do same, when we want to decorate class?
def some_class_decorator(cls_to_decorate): class Wrapper(cls_to_decorate): """Some Wrapper not important doc.""" pass return Wrapper @some_class_decorator class MainClass: """MainClass important doc.""" pass help(MainClass) Output:
class Wrapper(MainClass) | Some Wrapper not important doc. | | Method resolution order: | Wrapper | MainClass | builtins.object | # ... no MainClass important doc below. I tried to write wraps equivalent for class decorator based on functools.wraps source code, but my implementation doesn't work correct:
import functools def wraps_cls(original_cls): def wrapper(wrapper_cls): """Update wrapper_cls to look like original_cls.""" for attr in functools.WRAPPER_ASSIGNMENTS: try: value = getattr(original_cls, attr) except AttributeError: pass else: setattr(wrapper_cls, attr, value) return wrapper_cls return wrapper def some_class_decorator(cls_to_decorate): @wraps_cls(cls_to_decorate) class Wrapper(cls_to_decorate): """Some Wrapper not important doc.""" pass return Wrapper @some_class_decorator class MainClass: """MainClass important doc.""" pass help(MainClass) Output:
class MainClass(MainClass) | MainClass important doc. | | Method resolution order: | MainClass | MainClass | builtins.object | # ... MainClass doc is here but "Method resolution order" is broken. Is there anyway to completely replace decorated MainClass help output with not decorated MainClass help output?
@functools.wraps(cls, updated=())would have saved you from writing your own wrapper. It suffers from the same problem though.