hbutils.design.decorator

Decorator utilities for flexible decorator usage.

This module provides a utility function that simplifies the creation of decorators which can be used both with and without parameters. It focuses on the common pattern where a decorator accepts optional keyword arguments and wraps a target function accordingly.

The module contains the following main components:

  • decolize() - A decorator for decorators that enables optional arguments.

Example:

>>> from functools import wraps
>>> from hbutils.design.decorator import decolize
>>>
>>> @decolize
... def deco(func, a=1, b=2):
...     @wraps(func)
...     def _new_func(*args, **kwargs):
...         return func(*args, **kwargs) * a + b
...     return _new_func
>>>
>>> @deco
... def f1(x):
...     return x
>>>
>>> @deco(a=2)
... def f2(x):
...     return x
>>>
>>> f1(3)
5
>>> f2(3)
8

Note

Only keyword arguments are supported for parameterized decorator usage.

__all__

hbutils.design.decorator.__all__ = ['decolize']

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

decolize

hbutils.design.decorator.decolize(deco: Callable[[...], Callable]) Callable[source]

Decorator for decorator, make a decorator function with keyword-arguments usable as the real python decorator.

This utility allows decorators with parameters to be used both as simple decorators (without parentheses) and as parameterized decorators (with parentheses and arguments).

Parameters:

deco (Callable[..., Callable]) – Decorator function to be decorated. The first parameter should be the function to be decorated, followed by optional keyword arguments.

Returns:

A new decorator that can be used with or without parameters.

Return type:

Callable

Tip

This decorator can be useful when building a decorator with parameters.

Note

In the decorated decorator, only keyword arguments are supported. So make sure the original decorator function’s parameters (except func) are all keyword supported, and do not try to use positional arguments when using it to decorate another function.

Examples:

>>> from functools import wraps
>>> @decolize  # decorate the decorator
... def deco(func, a=1, b=2):
...     @wraps(func)
...     def _new_func(*args, **kwargs):
...         return func(*args, **kwargs) * a + b
...
...     return _new_func
>>> @deco  # used as simple decorator, same as deco(_func_1)
... def _func_1(a, b, c):
...     return (a + b * 2) * c
>>> @deco(a=2)  # used as parameterized decorator, same as deco(_func_2, a=2)
... def _func_2(a, b, c):
...     return (a + b * 2) * c
>>> _func_1(1, 2, 3)
17
>>> _func_2(1, 2, 3)
32