diff --git a/src/snakia/utils/__init__.py b/src/snakia/utils/__init__.py index 7fee463..cc6694a 100644 --- a/src/snakia/utils/__init__.py +++ b/src/snakia/utils/__init__.py @@ -1,13 +1,16 @@ -from .attr import get_attrs, get_or_set_attr -from .frame import frame +from .attrs import get_attrs, get_or_set_attr +from .calls import call, caller +from .exceptions import catch, throw +from .frames import frame from .inherit import inherit from .nolock import nolock from .side import side, side_func from .this import this -from .throw import throw from .to_async import to_async __all__ = [ + "call", + "caller", "get_or_set_attr", "get_attrs", "frame", @@ -17,5 +20,6 @@ __all__ = [ "side_func", "this", "throw", + "catch", "to_async", ] diff --git a/src/snakia/utils/attr.py b/src/snakia/utils/attrs.py similarity index 100% rename from src/snakia/utils/attr.py rename to src/snakia/utils/attrs.py diff --git a/src/snakia/utils/calls.py b/src/snakia/utils/calls.py new file mode 100644 index 0000000..eeabd5f --- /dev/null +++ b/src/snakia/utils/calls.py @@ -0,0 +1,12 @@ +from typing import Callable, ParamSpec, TypeVar + +P = ParamSpec("P") +T = TypeVar("T") + + +def call(f: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T: + return f(*args, **kwargs) + + +def caller(f: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> Callable[..., T]: + return lambda *_, **__: f(*args, **kwargs) diff --git a/src/snakia/utils/exceptions.py b/src/snakia/utils/exceptions.py new file mode 100644 index 0000000..5c1599e --- /dev/null +++ b/src/snakia/utils/exceptions.py @@ -0,0 +1,62 @@ +import contextlib +from typing import Any, Callable, NoReturn, TypeVar, overload + +from exceptiongroup import ExceptionGroup + +from snakia.types.unset import Unset + +E = TypeVar("E", bound=Exception) +T = TypeVar("T") +D = TypeVar("D") + + +@overload +def throw( + *exceptions: E, # pyright: ignore[reportInvalidTypeVarUse] + from_: Unset | BaseException = Unset(), +) -> NoReturn: ... + + +@overload +def throw( + exception: BaseException, from_: Unset | BaseException = Unset(), / +) -> NoReturn: ... + + +def throw(*exceptions: Any, from_: Unset | BaseException = Unset()) -> NoReturn: + """Throw an exception.""" + if isinstance(from_, Unset): + if len(exceptions) == 1: + raise exceptions[0] + raise ExceptionGroup("", exceptions) + if len(exceptions) == 1: + raise exceptions[0] from from_ + raise ExceptionGroup("", exceptions) from from_ + + +contextlib.suppress() + + +@overload +def catch( + func: Callable[[], T], + *exceptions: type[Exception] | type[BaseException], + default: None = None, +) -> T | None: ... +@overload +def catch( + func: Callable[[], T], + *exceptions: type[Exception] | type[BaseException], + default: D, +) -> T | D: ... +def catch( + func: Callable[[], T], + *exceptions: type[Exception] | type[BaseException], + default: Any = None, +) -> T | Any: + try: + return func() + except BaseException as e: + if any(isinstance(e, exc) for exc in exceptions): + return default + raise diff --git a/src/snakia/utils/frame.py b/src/snakia/utils/frames.py similarity index 100% rename from src/snakia/utils/frame.py rename to src/snakia/utils/frames.py diff --git a/src/snakia/utils/this.py b/src/snakia/utils/this.py index d5dd37b..35339e3 100644 --- a/src/snakia/utils/this.py +++ b/src/snakia/utils/this.py @@ -2,7 +2,7 @@ import gc from types import FunctionType, MethodType from typing import Any -from .frame import frame +from .frames import frame def this() -> Any: diff --git a/src/snakia/utils/throw.py b/src/snakia/utils/throw.py deleted file mode 100644 index b1a6d4c..0000000 --- a/src/snakia/utils/throw.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Any, NoReturn, TypeVar, overload - -from exceptiongroup import ExceptionGroup - -from snakia.types.unset import Unset - -T = TypeVar("T", bound=Exception) - - -@overload -def throw( - *exceptions: T, # pyright: ignore[reportInvalidTypeVarUse] - from_: Unset | BaseException = Unset(), -) -> NoReturn: ... - - -@overload -def throw( - exception: BaseException, from_: Unset | BaseException = Unset(), / -) -> NoReturn: ... - - -def throw( - *exceptions: Any, from_: Unset | BaseException = Unset() -) -> NoReturn: - """Throw an exception.""" - if isinstance(from_, Unset): - if len(exceptions) == 1: - raise exceptions[0] - raise ExceptionGroup("", exceptions) - if len(exceptions) == 1: - raise exceptions[0] from from_ - raise ExceptionGroup("", exceptions) from from_