Skip to content

compclass (class decorator)

compclass(_cls=None, delegates=None, verbose=True, log_func=logger.info)

Decorator that adds class attributes/methods from delegates to _cls object as class properties.

Parameters:

Name Type Description Default
_cls Union[Type[T], None]

Class to which attributes/methods should be forwarded to.

None
delegates Union[Dict[str, Union[Iterable[str], delegatee]], None]

Key-value pair of delegates.

  • key: Name of the class/instance attribute to which the delegate instance is assigned to.
  • value: Must be either a sequence/iterable of method names or a delegatee instance. They represent the attributes/methods to forward.
None
verbose bool

Defines the level of verbosity when setting those forwarded methods.

True
log_func Callable[[str], None]

Function to use for logging, if verbose is set to True.

logger.info

Raises:

Type Description
ValueError

delegates param cannot be None.

Returns:

Type Description
Union[Type[T], Callable[[Type[T], Dict[str, Union[Iterable[str], delegatee]]], Type[T]]]

Class with added methods from delegates.

Usage:

The function can be used as a class decorator:

class Foo:
    a = 1

    def __len__(self) -> int:
        # custom len method
        return 42

@compclass(delegates={"_foo": ("a", "__len__")})
class Bar:
    def __init__(self, foo: Foo):
        self._foo = foo

foo = Foo()
bar = Bar(foo)

bar.a  # -> 1 (instead of bar._foo.a)
len(bar)  # -> 42 (instead of len(bar._foo))
Source code in compclasses/_decorator.py
def compclass(
    _cls: Union[Type[T], None] = None,
    delegates: Union[Dict[str, Union[Iterable[str], delegatee]], None] = None,
    verbose: bool = True,
    log_func: Callable[[str], None] = logger.info,
) -> Union[Type[T], Callable[[Type[T], Dict[str, Union[Iterable[str], delegatee]]], Type[T]]]:
    """Decorator that adds class attributes/methods from `delegates` to `_cls` object as class properties.

    Arguments:
        _cls: Class to which attributes/methods should be forwarded to.
        delegates: Key-value pair of delegates.

            - key: Name of the class/instance attribute to which the delegate instance is assigned to.
            - value: Must be either a sequence/iterable of method names or a `delegatee` instance.
                They represent the attributes/methods to forward.

        verbose: Defines the level of verbosity when setting those forwarded methods.
        log_func: Function to use for logging, if verbose is set to True.

    Raises:
        ValueError: `delegates` param cannot be `None`.

    Returns:
        Class with added methods from delegates.

    Usage:

    The function can be used as a class decorator:

    ```python
    class Foo:
        a = 1

        def __len__(self) -> int:
            # custom len method
            return 42

    @compclass(delegates={"_foo": ("a", "__len__")})
    class Bar:
        def __init__(self, foo: Foo):
            self._foo = foo

    foo = Foo()
    bar = Bar(foo)

    bar.a  # -> 1 (instead of bar._foo.a)
    len(bar)  # -> 42 (instead of len(bar._foo))
    ```
    """
    if delegates is None:
        raise ValueError("`delegates` param cannot be `None`")

    def wrap(
        _cls: Type[T],
        delegates: Dict[str, Union[Iterable[str], delegatee]] = delegates,  # type: ignore
    ) -> Type[T]:
        for _name, _to_inject in generate_properties(delegates, verbose, log_func):
            setattr(_cls, _name, _to_inject)

        return _cls

    if _cls is None:
        # Called with parens: @compclass(delegates=...)
        return wrap

    # Called directly on class C = compclass(C, delegates)
    return wrap(_cls)