Functools.wraps equivalent for class decor

When we decorate a function, we use functools.wraps to make the decorated function look original.

Is there any wat to do the same when we want to decorate a 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)

Conclusion:

class Wrapper(MainClass)
 |  Some Wrapper not important doc.
 |  
 |  Method resolution order:
 |      Wrapper
 |      MainClass
 |      builtins.object
 |  
 # ... no MainClass important doc below.

I tried to write a shell equivalent for the class decorator based on the source code functools.wraps, but my implementation does not work correctly:

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)

Conclusion:

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 any way to completely replace the issued MainClass help release with the broken MainClass help output?

+4
source share
2 answers

, , , some_class_decorator. help pydoc.Helper, pydoc.text.docclass, :

# List the mro, if non-trivial.
mro = deque(inspect.getmro(object))
if len(mro) > 2:
    push("Method resolution order:")
    for base in mro:
        push('    ' + makename(base))
    push('')

, MRO. . MRO, , "", . , . MRO, , . - , - ( ?), , .

, , , , MRO - DecoratorWrapper_of_MainClass . , Wrapper, .

+1

, , , .

"" .

workng:

class Wrapper(object):
    """Some Wrapper not important doc."""
    def another_method(self):
        """Another method."""
        print 'Another method'


def some_class_decorator(cls_to_decorate):
    return type(cls_to_decorate.__name__, cls_to_decorate.__bases__, dict
        (cls_to_decorate.__dict__, another_method=Wrapper.__dict__['another_method']))


class MainClass(object):
    """MainClass important doc."""
    def method(self):
        """A method."""
        print "A method"


help(MainClass)
_MainClass = some_class_decorator(MainClass)
help(_MainClass)
_MainClass().another_method()
MainClass().another_method()

, .

, , .

+1

All Articles