Source code for drresult.function_decorators

# Copyright 2024 Ole Kliemann
# SPDX-License-Identifier: MIT

from types import TracebackType
from typing import Any, Callable, NoReturn, Type, List
import traceback

from drresult.result import Result, Err, format_exception, format_traceback, Panic

"""
This module provides decorators for functions to handle expected and unexpected exceptions.

Decorators:
    - noexcept: Marks a function as not expecting any exceptions.
    - returns_result: Wraps exceptions in a `Result` type based on expected exceptions.

Constants:
    - LanguageLevelExceptions: Exceptions considered language-level errors.
    - SystemLevelExceptions: Exceptions considered system-level errors.
    - expects_default: Default list of expected exceptions.
    - not_expects_default: Default list of unexpected exceptions.
"""


[docs] def noexcept[T](func: Callable[..., T]) -> Callable[..., T]: """Decorator to mark a function as not expecting any exceptions. Args: func (Callable[..., T]): The function to decorate. Returns: Callable[..., T]: The wrapped function. Raises: Panic: If an unexpected exception occurs. """ def wrapper(*args: Any, **kwargs: Any) -> T: try: return func(*args, **kwargs) except Panic: raise except BaseException as e: raise Panic(e) from None return wrapper
# Exception lists for internal use LanguageLevelExceptions: List[Type[BaseException]] = [ AssertionError, AttributeError, ImportError, NameError, SyntaxError, TypeError, ] SystemLevelExceptions: List[Type[BaseException]] = [ MemoryError, SystemError, ] expects_default: List[Type[BaseException]] = [Exception] not_expects_default: List[Type[BaseException]] = LanguageLevelExceptions + SystemLevelExceptions def make_drresult_returns_result_decorator[ T ]( expects: List[Type[BaseException]] = expects_default, not_expects: List[Type[BaseException]] = not_expects_default, ) -> Callable[[Callable[..., Result[T]]], Callable[..., Result[T]]]: """Creates a decorator to wrap exceptions in a `Result` type. Args: expects (List[Type[BaseException]]): List of expected exceptions. not_expects (List[Type[BaseException]]): List of unexpected exceptions. Returns: Callable: A decorator for functions returning `Result[T]`. """ expects_tuple = tuple(expects) not_expects_tuple = tuple(not_expects) def make_drresult_returns_result_wrapper( func: Callable[..., Result[T]] ) -> Callable[..., Result[T]]: def drresult_returns_result_wrapper(*args: Any, **kwargs: Any) -> Result[T]: try: return func(*args, **kwargs) except Panic: raise except not_expects_tuple as e: raise Panic(e) from None except expects_tuple as e: return Err(e) except BaseException as e: raise Panic(e) from None return drresult_returns_result_wrapper return make_drresult_returns_result_wrapper
[docs] def returns_result[ T ](*decorator_args: Any, **decorator_kwargs: Any) -> ( Callable[..., Result[T]] | Callable[[Callable[..., Result[T]]], Callable[..., Result[T]]] ): """Decorator to wrap expected exceptions in an `Err`, and unexpected ones in a `Panic`. Can be used with or without arguments. Usage: @returns_result def func(...): ... @returns_result(expects=[ValueError]) def func(...): ... Args: *decorator_args (Any): Positional arguments. **decorator_kwargs (Any): Keyword arguments. Returns: Callable: The decorator or wrapped function. """ if len(decorator_args) == 1 and callable(decorator_args[0]) and not decorator_kwargs: return make_drresult_returns_result_decorator(expects_default, not_expects_default)( decorator_args[0] ) else: return make_drresult_returns_result_decorator(**decorator_kwargs)