descriptors2_classmethod0.py (Source)

"""Descriptors & Decorators
Example 1: class methods
"""
from functools import wraps


class decorator:
    def __init__(self, func):
        self.func = func
        wraps(func)(self)

    def __call__(self, *args, **kwargs):
        result = self.func(*args, **kwargs)
        return f"decorated {result}"


class decorator2(decorator):
    def __get__(self, instance, owner):
        mapped = self.func.__get__(instance, owner)
        return self.__class__(mapped)


@decorator
def function():
    """
    >>> function()
    'decorated function'
    """
    return 'function'


class Object:
    """
    >>> Object.class_method()
    Traceback (most recent call last):
    ...
    TypeError: 'classmethod' object is not callable


    >>> Object.class_method2()
    'decorated second class method'

    >>> Object.base_class_method()
    Traceback (most recent call last):
    ...
    TypeError: 'classmethod' object is not callable

    >>> Object.correct()
    'decorated this works'
    """
    @decorator
    @classmethod
    def class_method(cls):
        return 'class method'

    @decorator2
    @classmethod
    def class_method2(cls):
        return 'second class method'


    @classmethod
    def base_class_method(cls):
        return 'base class method'

    base_class_method = decorator(base_class_method)

    @classmethod
    @decorator
    def correct(cls):
        return 'this works'


if __name__ == '__main__':
    import doctest
    doctest.testmod(verbose=True)