Skip to content

wg_utilities.decorators

Custom decorators for the wg_utilities package.

process_exception

Custom decorator for processing a thrown exception.

process_exception(exceptions=Exception, /, logger=None, *, callback=None, raise_after_processing=True, default_return_value=None)

Allow simple cover-all exception processing/logging, with optional suppression.

Parameters:

Name Type Description Default
exceptions type[Exception] | tuple[type[Exception], ...]

the exception(s) to catch

Exception
logger Logger

optional logger for logging the exception

None
callback Callable

callback function to process the exception

None
raise_after_processing bool

raise the exception after the processing is complete

True
default_return_value Any

optional default return value for the decorated function

None

Returns:

Name Type Description
Callable Callable[[Any], Any]

the actual decorator

Source code in wg_utilities/decorators/process_exception.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def process_exception(
    exceptions: type[Exception] | tuple[type[Exception], ...] = Exception,
    /,
    logger: Logger | None = None,
    *,
    callback: Callable[[Exception], Any] | None = None,
    raise_after_processing: bool = True,
    default_return_value: Any | None = None,
) -> Callable[[Any], Any]:
    """Allow simple cover-all exception processing/logging, with optional suppression.

    Args:
        exceptions (type[Exception] | tuple[type[Exception], ...]): the exception(s) to catch
        logger (Logger): optional logger for logging the exception
        callback (Callable): callback function to process the exception
        raise_after_processing (bool): raise the exception after the processing is
            complete
        default_return_value (Any): optional default return value for the decorated
            function

    Returns:
        Callable: the actual decorator
    """

    if default_return_value is not None and raise_after_processing:
        raise ValueError(
            "The `default_return_value` parameter can only be set when"
            " `raise_after_processing` is False.",
        )

    def _decorator(func: Callable[[Any], Any]) -> Callable[[Any, Any], Any]:
        @wraps(func)
        def worker(*args: Any, **kwargs: Any) -> Any:
            """Try to run the decorated function and calls the callback function.

            Args:
                *args (Any): any args passed to the inner func
                **kwargs (Any): any kwargs passed to the inner func

            Returns:
                Any: the result of the wrapped function

            Raises:
                Exception: any exception from the decorated function
            """

            try:
                return func(*args, **kwargs)
            except exceptions as exc:
                if logger is not None:
                    logger.exception(
                        "%s %s in %s.%s: %s",
                        type(exc).__name__,
                        "thrown" if raise_after_processing else "caught",
                        func.__module__,
                        func.__qualname__,
                        str(exc),  # noqa: TRY401
                    )

                if callback is not None:
                    callback(exc)

                if raise_after_processing:
                    raise

                return default_return_value

        return worker

    return _decorator