diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d22bba..0337367 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # Changelog +## Pedantic 2.1.10 +- added type check support for `functools.partial` +- update dependencies + ## Pedantic 2.1.9 - added Python 3.13 to CI diff --git a/docs/pedantic/constants.html b/docs/pedantic/constants.html index 183b9a3..34974f3 100644 --- a/docs/pedantic/constants.html +++ b/docs/pedantic/constants.html @@ -2,18 +2,32 @@ - - + + pedantic.constants API documentation - - - - - - + + + + + + - - + +
@@ -22,25 +36,6 @@

Module pedantic.constants

-
- -Expand source code - -
from typing import TypeVar as Tv, Callable
-
-
-TYPE_VAR_METHOD_NAME = '__pedantic_m42__'
-TYPE_VAR_ATTR_NAME = '__pedantic_a42__'
-TYPE_VAR_SELF = Tv('__pedantic_t42__')
-ATTR_NAME_GENERIC_INSTANCE_ALREADY_CHECKED = '__pedantic_g42__'
-
-TypeVar = Tv
-ReturnType = TypeVar('ReturnType')
-F = Callable[..., ReturnType]
-C = TypeVar('C')
-K = TypeVar('K')
-V = TypeVar('V')
-
@@ -52,7 +47,6 @@

Module pedantic.constants

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/class_decorators.html b/docs/pedantic/decorators/class_decorators.html index 14b6874..8c36034 100644 --- a/docs/pedantic/decorators/class_decorators.html +++ b/docs/pedantic/decorators/class_decorators.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.class_decorators API documentation - - - - - - + + + + + + - - + +
@@ -22,104 +36,6 @@

Module pedantic.decorators.class_decorators

-
- -Expand source code - -
import enum
-import types
-from dataclasses import is_dataclass
-from typing import Callable, Optional, Dict, Type
-
-from pedantic.constants import TYPE_VAR_ATTR_NAME, TYPE_VAR_METHOD_NAME, F, C, TYPE_VAR_SELF
-from pedantic.decorators import timer, trace
-from pedantic.decorators.fn_deco_pedantic import pedantic, pedantic_require_docstring
-from pedantic.env_var_logic import is_enabled
-from pedantic.exceptions import PedanticTypeCheckException
-from pedantic.type_checking_logic.check_generic_classes import check_instance_of_generic_class_and_get_type_vars, \
-    is_instance_of_generic_class
-
-
-def for_all_methods(decorator: F) -> Callable[[Type[C]], Type[C]]:
-    """
-        Applies a decorator to all methods of a class.
-
-        Example:
-
-        >>> @for_all_methods(pedantic)
-        ... class MyClass(object):
-        ...     def m1(self): pass
-        ...     def m2(self, x): pass
-    """
-    def decorate(cls: C) -> C:
-        if not is_enabled():
-            return cls
-
-        if issubclass(cls, enum.Enum):
-            raise PedanticTypeCheckException(f'Enum "{cls}" cannot be decorated with "@pedantic_class". '
-                                             f'Enums are not supported yet.')
-
-        if is_dataclass(obj=cls):
-            raise PedanticTypeCheckException(f'Dataclass "{cls}" cannot be decorated with "@pedantic_class". '
-                                             f'Try to write "@dataclass" over "@pedantic_class".')
-
-        for attr in cls.__dict__:
-            attr_value = getattr(cls, attr)
-
-            if isinstance(attr_value, (types.FunctionType, types.MethodType)):
-                setattr(cls, attr, decorator(attr_value))
-            elif isinstance(attr_value, property):
-                prop = attr_value
-                wrapped_getter = _get_wrapped(prop=prop.fget, decorator=decorator)
-                wrapped_setter = _get_wrapped(prop=prop.fset, decorator=decorator)
-                wrapped_deleter = _get_wrapped(prop=prop.fdel, decorator=decorator)
-                new_prop = property(fget=wrapped_getter, fset=wrapped_setter, fdel=wrapped_deleter)
-                setattr(cls, attr, new_prop)
-
-        _add_type_var_attr_and_method_to_class(cls=cls)
-        return cls
-    return decorate
-
-
-def pedantic_class(cls: C) -> C:
-    """ Shortcut for @for_all_methods(pedantic) """
-    return for_all_methods(decorator=pedantic)(cls=cls)
-
-
-def pedantic_class_require_docstring(cls: C) -> C:
-    """ Shortcut for @for_all_methods(pedantic_require_docstring) """
-    return for_all_methods(decorator=pedantic_require_docstring)(cls=cls)
-
-
-def trace_class(cls: C) -> C:
-    """ Shortcut for @for_all_methods(trace) """
-    return for_all_methods(decorator=trace)(cls=cls)
-
-
-def timer_class(cls: C) -> C:
-    """ Shortcut for @for_all_methods(timer) """
-    return for_all_methods(decorator=timer)(cls=cls)
-
-
-def _get_wrapped(prop: Optional[F], decorator: F) -> Optional[F]:
-    return decorator(prop) if prop is not None else None
-
-
-def _add_type_var_attr_and_method_to_class(cls: C) -> None:
-    def type_vars(self) -> Dict:
-        t_vars = {TYPE_VAR_SELF: cls}
-
-        if is_instance_of_generic_class(instance=self):
-            type_vars_fifo = getattr(self, TYPE_VAR_ATTR_NAME, dict())
-            type_vars_generics = check_instance_of_generic_class_and_get_type_vars(instance=self)
-            setattr(self, TYPE_VAR_ATTR_NAME, {**type_vars_fifo, **type_vars_generics, **t_vars})
-        else:
-            setattr(self, TYPE_VAR_ATTR_NAME, t_vars)
-
-        return getattr(self, TYPE_VAR_ATTR_NAME)
-
-    setattr(cls, TYPE_VAR_METHOD_NAME, type_vars)
-
@@ -132,13 +48,6 @@

Functions

def for_all_methods(decorator: Callable[..., ~ReturnType]) ‑> Callable[[Type[~C]], Type[~C]]
-

Applies a decorator to all methods of a class.

-

Example:

-
>>> @for_all_methods(pedantic)
-... class MyClass(object):
-...     def m1(self): pass
-...     def m2(self, x): pass
-
Expand source code @@ -183,12 +92,18 @@

Functions

return cls return decorate
+

Applies a decorator to all methods of a class.

+

Example:

+
>>> @for_all_methods(pedantic)
+... class MyClass(object):
+...     def m1(self): pass
+...     def m2(self, x): pass
+
def pedantic_class(cls: ~C) ‑> ~C
-

Shortcut for @for_all_methods(pedantic)

Expand source code @@ -197,12 +112,12 @@

Functions

""" Shortcut for @for_all_methods(pedantic) """ return for_all_methods(decorator=pedantic)(cls=cls)
+

Shortcut for @for_all_methods(pedantic)

def pedantic_class_require_docstring(cls: ~C) ‑> ~C
-

Shortcut for @for_all_methods(pedantic_require_docstring)

Expand source code @@ -211,12 +126,12 @@

Functions

""" Shortcut for @for_all_methods(pedantic_require_docstring) """ return for_all_methods(decorator=pedantic_require_docstring)(cls=cls)
+

Shortcut for @for_all_methods(pedantic_require_docstring)

def timer_class(cls: ~C) ‑> ~C
-

Shortcut for @for_all_methods(timer)

Expand source code @@ -225,12 +140,12 @@

Functions

""" Shortcut for @for_all_methods(timer) """ return for_all_methods(decorator=timer)(cls=cls)
+

Shortcut for @for_all_methods(timer)

def trace_class(cls: ~C) ‑> ~C
-

Shortcut for @for_all_methods(trace)

Expand source code @@ -239,6 +154,7 @@

Functions

""" Shortcut for @for_all_methods(trace) """ return for_all_methods(decorator=trace)(cls=cls)
+

Shortcut for @for_all_methods(trace)

@@ -246,7 +162,6 @@

Functions

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/cls_deco_frozen_dataclass.html b/docs/pedantic/decorators/cls_deco_frozen_dataclass.html index 1803aad..da6d516 100644 --- a/docs/pedantic/decorators/cls_deco_frozen_dataclass.html +++ b/docs/pedantic/decorators/cls_deco_frozen_dataclass.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.cls_deco_frozen_dataclass API documentation - - - - - - + + + + + + - - + +
@@ -22,27 +36,23 @@

Module pedantic.decorators.cls_deco_frozen_dataclass

+
+
+
+
+
+
+

Functions

+
+
+def frozen_dataclass(cls: Type[~T] = None,
type_safe: bool = False,
order: bool = False,
kw_only: bool = True,
slots: bool = False) ‑> Type[~T] | Callable[[Type[~T]], Type[~T]]
+
+
Expand source code -
from copy import deepcopy
-from dataclasses import dataclass, fields, replace
-from typing import Type, TypeVar, Any, Union, Callable, Dict
-
-from pedantic.get_context import get_context
-from pedantic.type_checking_logic.check_types import assert_value_matches_type
-
-T = TypeVar('T')
-
-
-def frozen_type_safe_dataclass(cls: Type[T]) -> Type[T]:
-    """ Shortcut for @frozen_dataclass(type_safe=True) """
-
-    return frozen_dataclass(type_safe=True)(cls)
-
-
-def frozen_dataclass(
+
def frozen_dataclass(
         cls: Type[T] = None,
         type_safe: bool = False,
         order: bool = False,
@@ -169,25 +179,8 @@ 

Module pedantic.decorators.cls_deco_frozen_dataclass

+ return decorator(cls_=cls)
-
-
-
-
-
-
-

Functions

-
-
-def frozen_dataclass(cls: Type[~T] = None, type_safe: bool = False, order: bool = False, kw_only: bool = True, slots: bool = False) ‑> Union[Type[~T], Callable[[Type[~T]], Type[~T]]] -
-

Makes the decorated class immutable and a dataclass by adding the [@dataclass(frozen=True)] decorator. Also adds useful copy_with() and validate_types() instance methods to this class (see below).

If [type_safe] is True, a type check is performed for each field after the post_init method was called @@ -231,145 +224,11 @@

Functions

>>> print(foo.copy_with(a=676676, b='new', c=False)) Foo(a=676676, b='new', c=False)
-
- -Expand source code - -
def frozen_dataclass(
-        cls: Type[T] = None,
-        type_safe: bool = False,
-        order: bool = False,
-        kw_only: bool = True,
-        slots: bool = False,
-) -> Union[Type[T], Callable[[Type[T]], Type[T]]]:
-    """
-        Makes the decorated class immutable and a dataclass by adding the [@dataclass(frozen=True)]
-        decorator. Also adds useful copy_with() and validate_types() instance methods to this class (see below).
-
-        If [type_safe] is True, a type check is performed for each field after the __post_init__ method was called
-        which itself s directly called after the __init__ constructor.
-        Note this have a negative impact on the performance. It's recommend to use this for debugging and testing only.
-
-        In a nutshell, the followings methods will be added to the decorated class automatically:
-        - __init__() gives you a simple constructor like "Foo(a=6, b='hi', c=True)"
-        - __eq__() lets you compare objects easily with "a == b"
-        - __hash__() is also needed for instance comparison
-        - __repr__() gives you a nice output when you call "print(foo)"
-        - copy_with() allows you to quickly create new similar frozen instances. Use this instead of setters.
-        - deep_copy_with() allows you to create deep copies and modify them.
-        - validate_types() allows you to validate the types of the dataclass.
-                           This is called automatically when [type_safe] is True.
-
-        If the [order] parameter is True (default is False), the following comparison methods
-        will be added additionally:
-        - __lt__() lets you compare instance like "a < b"
-        - __le__() lets you compare instance like "a <= b"
-        - __gt__() lets you compare instance like "a > b"
-        - __ge__() lets you compare instance like "a >= b"
-
-        These compare the class as if it were a tuple of its fields, in order.
-        Both instances in the comparison must be of the identical type.
-
-        The parameters slots and kw_only are only applied if the Python version is greater or equal to 3.10.
-
-        Example:
-
-        >>> @frozen_dataclass
-        ... class Foo:
-        ...     a: int
-        ...     b: str
-        ...     c: bool
-        >>> foo = Foo(a=6, b='hi', c=True)
-        >>> print(foo)
-        Foo(a=6, b='hi', c=True)
-        >>> print(foo.copy_with())
-        Foo(a=6, b='hi', c=True)
-        >>> print(foo.copy_with(a=42))
-        Foo(a=42, b='hi', c=True)
-        >>> print(foo.copy_with(b='Hello'))
-        Foo(a=6, b='Hello', c=True)
-        >>> print(foo.copy_with(c=False))
-        Foo(a=6, b='hi', c=False)
-        >>> print(foo.copy_with(a=676676, b='new', c=False))
-        Foo(a=676676, b='new', c=False)
-    """
-
-    def decorator(cls_: Type[T]) -> Type[T]:
-        args = {'frozen': True, 'order': order, 'kw_only': kw_only, 'slots': slots}
-
-        if type_safe:
-            old_post_init = getattr(cls_, '__post_init__', lambda _: None)
-
-            def new_post_init(self) -> None:
-                old_post_init(self)
-                context = get_context(depth=3, increase_depth_if_name_matches=[
-                    copy_with.__name__,
-                    deep_copy_with.__name__,
-                ])
-                self.validate_types(_context=context)
-
-            setattr(cls_, '__post_init__', new_post_init)  # must be done before applying dataclass()
-
-        new_class = dataclass(**args)(cls_)  # slots = True will create a new class!
-
-        def copy_with(self, **kwargs: Any) -> T:
-            """
-                Creates a new immutable instance that by copying all fields of this instance replaced by the new values.
-                Keep in mind that this is a shallow copy!
-            """
-
-            return replace(self, **kwargs)
-
-        def deep_copy_with(self, **kwargs: Any) -> T:
-            """
-                Creates a new immutable instance that by deep copying all fields of
-                this instance replaced by the new values.
-            """
-
-            current_values = {field.name: deepcopy(getattr(self, field.name)) for field in fields(self)}
-            return new_class(**{**current_values, **kwargs})
-
-        def validate_types(self, *, _context: Dict[str, Type] = None) -> None:
-            """
-                Checks that all instance variable have the correct type.
-                Raises a [PedanticTypeCheckException] if at least one type is incorrect.
-            """
-
-            props = fields(new_class)
-
-            if _context is None:
-                # method was called by user
-                _context = get_context(depth=2)
-
-            _context = {**_context, **self.__init__.__globals__, self.__class__.__name__: self.__class__}
-
-            for field in props:
-                assert_value_matches_type(
-                    value=getattr(self, field.name),
-                    type_=field.type,
-                    err=f'In dataclass "{cls_.__name__}" in field "{field.name}": ',
-                    type_vars={},
-                    context=_context,
-                )
-
-        methods_to_add = [copy_with, deep_copy_with, validate_types]
-
-        for method in methods_to_add:
-            setattr(new_class, method.__name__, method)
-
-        return new_class
-
-    if cls is None:
-        return decorator
-
-    return decorator(cls_=cls)
-
def frozen_type_safe_dataclass(cls: Type[~T]) ‑> Type[~T]
-

Shortcut for @frozen_dataclass(type_safe=True)

Expand source code @@ -379,6 +238,7 @@

Functions

return frozen_dataclass(type_safe=True)(cls)
+

Shortcut for @frozen_dataclass(type_safe=True)

@@ -386,7 +246,6 @@

Functions

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/fn_deco_context_manager.html b/docs/pedantic/decorators/fn_deco_context_manager.html index 51264c6..e6b1817 100644 --- a/docs/pedantic/decorators/fn_deco_context_manager.html +++ b/docs/pedantic/decorators/fn_deco_context_manager.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.fn_deco_context_manager API documentation - - - - - - + + + + + + - - + +
@@ -22,76 +36,23 @@

Module pedantic.decorators.fn_deco_context_manager

+
+
+
+
+
+
+

Functions

+
+
+def safe_async_contextmanager(f: Callable[..., AsyncIterator[~T]]) ‑> Callable[..., AsyncContextManager[~T, bool | None]] +
+
Expand source code -
from contextlib import contextmanager, asynccontextmanager
-from functools import wraps
-from inspect import isasyncgenfunction, isgeneratorfunction
-from typing import Callable, TypeVar, Iterator, ContextManager, AsyncContextManager, AsyncIterator
-
-T = TypeVar('T')
-
-
-def safe_contextmanager(f: Callable[..., Iterator[T]]) -> Callable[..., ContextManager[T]]:
-    """
-    @safe_contextmanager decorator.
-
-    Typical usage:
-
-        @safe_contextmanager
-        def some_generator(<arguments>):
-            <setup>
-            yield <value>
-            <cleanup>
-
-    equivalent to this:
-
-        @contextmanager
-        def some_generator(<arguments>):
-            <setup>
-            try:
-                yield <value>
-            finally:
-                <cleanup>
-
-    This makes this:
-
-        with some_generator(<arguments>) as <variable>:
-            <body>
-
-    equivalent to this:
-
-        <setup>
-        try:
-            <variable> = <value>
-            <body>
-        finally:
-            <cleanup>
-    """
-
-    if isasyncgenfunction(f):
-        raise AssertionError(f'{f.__name__} is async. So you need to use "safe_async_contextmanager" instead.')
-    if not isgeneratorfunction(f):
-        raise AssertionError(f'{f.__name__} is not a generator.')
-
-    @wraps(f)
-    def wrapper(*args, **kwargs) -> Iterator[T]:
-        iterator = f(*args, **kwargs)
-
-        try:
-            yield next(iterator)
-        finally:
-            try:
-                next(iterator)
-            except StopIteration:
-                pass  # this is intended
-
-    return contextmanager(wrapper)  # type: ignore
-
-
-def safe_async_contextmanager(f: Callable[..., AsyncIterator[T]]) -> Callable[..., AsyncContextManager[T]]:
+
def safe_async_contextmanager(f: Callable[..., AsyncIterator[T]]) -> Callable[..., AsyncContextManager[T]]:
     """
     @safe_async_contextmanager decorator.
 
@@ -151,18 +112,6 @@ 

Module pedantic.decorators.fn_deco_context_manager

-
-
-
-
-
-
-

Functions

-
-
-def safe_async_contextmanager(f: Callable[..., AsyncIterator[~T]]) ‑> Callable[..., AsyncContextManager[~T]] -
-

@safe_async_contextmanager decorator.

Note: You need Python 3.10 or newer for this.

 Typical usage:
@@ -197,104 +146,11 @@ 

Functions

finally: <cleanup>
-
- -Expand source code - -
def safe_async_contextmanager(f: Callable[..., AsyncIterator[T]]) -> Callable[..., AsyncContextManager[T]]:
-    """
-    @safe_async_contextmanager decorator.
-
-    Note: You need Python 3.10 or newer for this.
-
-         Typical usage:
-
-            @safe_async_contextmanager
-            async def some_async_generator(<arguments>):
-                <setup>
-                yield <value>
-                <cleanup>
-
-        equivalent to this:
-
-            @asynccontextmanager
-            async def some_async_generator(<arguments>):
-                <setup>
-                try:
-                    yield <value>
-                finally:
-                    <cleanup>
-
-        This makes this:
-
-            async with some_async_generator(<arguments>) as <variable>:
-                <body>
-
-        equivalent to this:
-
-            <setup>
-            try:
-                <variable> = <value>
-                <body>
-            finally:
-                <cleanup>
-        """
-
-    if not isasyncgenfunction(f):
-        if not isgeneratorfunction(f):
-            raise AssertionError(f'{f.__name__} is not a generator.')
-
-        raise AssertionError(f'{f.__name__} is not an async generator. '
-                             f'So you need to use "safe_contextmanager" instead.')
-
-    @wraps(f)
-    async def wrapper(*args, **kwargs) -> Iterator[T]:
-        iterator = f(*args, **kwargs)
-
-        try:
-            yield await anext(iterator)
-        finally:
-            try:
-                await anext(iterator)
-            except StopAsyncIteration:
-                pass  # this is intended
-
-    return asynccontextmanager(wrapper)  # type: ignore
-
-def safe_contextmanager(f: Callable[..., Iterator[~T]]) ‑> Callable[..., ContextManager[~T]] +def safe_contextmanager(f: Callable[..., Iterator[~T]]) ‑> Callable[..., ContextManager[~T, bool | None]]
-

@safe_contextmanager decorator.

-

Typical usage:

-
@safe_contextmanager
-def some_generator(<arguments>):
-    <setup>
-    yield <value>
-    <cleanup>
-
-

equivalent to this:

-
@contextmanager
-def some_generator(<arguments>):
-    <setup>
-    try:
-        yield <value>
-    finally:
-        <cleanup>
-
-

This makes this:

-
with some_generator(<arguments>) as <variable>:
-    <body>
-
-

equivalent to this:

-
<setup>
-try:
-    <variable> = <value>
-    <body>
-finally:
-    <cleanup>
-
Expand source code @@ -355,6 +211,35 @@

Functions

return contextmanager(wrapper) # type: ignore
+

@safe_contextmanager decorator.

+

Typical usage:

+
@safe_contextmanager
+def some_generator(<arguments>):
+    <setup>
+    yield <value>
+    <cleanup>
+
+

equivalent to this:

+
@contextmanager
+def some_generator(<arguments>):
+    <setup>
+    try:
+        yield <value>
+    finally:
+        <cleanup>
+
+

This makes this:

+
with some_generator(<arguments>) as <variable>:
+    <body>
+
+

equivalent to this:

+
<setup>
+try:
+    <variable> = <value>
+    <body>
+finally:
+    <cleanup>
+
@@ -362,7 +247,6 @@

Functions

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/fn_deco_count_calls.html b/docs/pedantic/decorators/fn_deco_count_calls.html index af63426..6ad3b2a 100644 --- a/docs/pedantic/decorators/fn_deco_count_calls.html +++ b/docs/pedantic/decorators/fn_deco_count_calls.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.fn_deco_count_calls API documentation - - - - - - + + + + + + - - + +
@@ -22,48 +36,6 @@

Module pedantic.decorators.fn_deco_count_calls

-
- -Expand source code - -
from datetime import datetime
-from functools import wraps
-from typing import Any
-
-from pedantic.constants import F, ReturnType
-
-
-def count_calls(func: F) -> F:
-    """
-        Prints how often the method is called during program execution.
-
-        Example:
-
-        >>> @count_calls
-        ... def often_used_method():
-        ...    return 42
-        >>> often_used_method()
-        Count Calls: Call 1 of function 'often_used_method' at ...
-        >>> often_used_method()
-        Count Calls: Call 2 of function 'often_used_method' at ...
-        >>> often_used_method()
-        Count Calls: Call 3 of function 'often_used_method' at ...
-    """
-
-    @wraps(func)
-    def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
-        wrapper.num_calls += 1
-        print(f"Count Calls: Call {wrapper.num_calls} of function {func.__name__!r} at {datetime.now()}.")
-        return func(*args, **kwargs)
-
-    wrapper.num_calls = 0
-    return wrapper
-
-
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
-
@@ -76,18 +48,6 @@

Functions

def count_calls(func: Callable[..., ~ReturnType]) ‑> Callable[..., ~ReturnType]
-

Prints how often the method is called during program execution.

-

Example:

-
>>> @count_calls
-... def often_used_method():
-...    return 42
->>> often_used_method()
-Count Calls: Call 1 of function 'often_used_method' at ...
->>> often_used_method()
-Count Calls: Call 2 of function 'often_used_method' at ...
->>> often_used_method()
-Count Calls: Call 3 of function 'often_used_method' at ...
-
Expand source code @@ -118,6 +78,18 @@

Functions

wrapper.num_calls = 0 return wrapper
+

Prints how often the method is called during program execution.

+

Example:

+
>>> @count_calls
+... def often_used_method():
+...    return 42
+>>> often_used_method()
+Count Calls: Call 1 of function 'often_used_method' at ...
+>>> often_used_method()
+Count Calls: Call 2 of function 'often_used_method' at ...
+>>> often_used_method()
+Count Calls: Call 3 of function 'often_used_method' at ...
+
@@ -125,7 +97,6 @@

Functions

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/fn_deco_deprecated.html b/docs/pedantic/decorators/fn_deco_deprecated.html index f2dc0d2..7e3dab1 100644 --- a/docs/pedantic/decorators/fn_deco_deprecated.html +++ b/docs/pedantic/decorators/fn_deco_deprecated.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.fn_deco_deprecated API documentation - - - - - - + + + + + + - - + +
@@ -22,40 +36,6 @@

Module pedantic.decorators.fn_deco_deprecated

-
- -Expand source code - -
from functools import wraps
-from typing import Any
-
-from pedantic.constants import F, ReturnType
-from pedantic.helper_methods import _raise_warning
-
-
-def deprecated(func: F) -> F:
-    """
-        Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.
-
-        Example:
-
-        >>> @deprecated
-        ... def my_function(a, b, c):
-        ...     pass
-        >>> my_function(5, 4, 3)
-    """
-
-    @wraps(func)
-    def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
-        _raise_warning(msg=f'Call to deprecated function {func.__qualname__}.', category=DeprecationWarning)
-        return func(*args, **kwargs)
-    return wrapper
-
-
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
-
@@ -68,13 +48,6 @@

Functions

def deprecated(func: Callable[..., ~ReturnType]) ‑> Callable[..., ~ReturnType]
-

Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.

-

Example:

-
>>> @deprecated
-... def my_function(a, b, c):
-...     pass
->>> my_function(5, 4, 3)
-
Expand source code @@ -97,6 +70,13 @@

Functions

return func(*args, **kwargs) return wrapper
+

Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.

+

Example:

+
>>> @deprecated
+... def my_function(a, b, c):
+...     pass
+>>> my_function(5, 4, 3)
+
@@ -104,7 +84,6 @@

Functions

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/fn_deco_does_same_as_function.html b/docs/pedantic/decorators/fn_deco_does_same_as_function.html index 71ebc42..9292832 100644 --- a/docs/pedantic/decorators/fn_deco_does_same_as_function.html +++ b/docs/pedantic/decorators/fn_deco_does_same_as_function.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.fn_deco_does_same_as_function API documentation - - - - - - + + + + + + - - + +
@@ -22,70 +36,6 @@

Module pedantic.decorators.fn_deco_does_same_as_function

-
- -Expand source code - -
import inspect
-from functools import wraps
-from typing import Any
-
-from pedantic.constants import F, ReturnType
-
-
-def does_same_as_function(other_func: F) -> F:
-    """
-        Each time the decorated function is executed, the function other_func is also executed and the results
-        are compared. An AssertionError is raised if the results are not equal.
-
-        Example:
-
-        >>> def other_calculation(a, b, c):
-        ...     return c + b + a
-        >>> @does_same_as_function(other_calculation)
-        ... def some_calculation(a, b, c):
-        ...     return a + b + c
-        >>> some_calculation(1, 2, 3)
-        6
-    """
-
-    def decorator(decorated_func: F) -> F:
-        @wraps(decorated_func)
-        def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
-            result = decorated_func(*args, **kwargs)
-            other = other_func(*args, **kwargs)
-
-            if other != result:
-                raise AssertionError(f'Different outputs: Function "{decorated_func.__name__}" returns {result} and '
-                                     f'function "{other_func.__name__}" returns {other} for parameters {args} {kwargs}')
-            return result
-
-        @wraps(decorated_func)
-        async def async_wrapper(*args: Any, **kwargs: Any) -> ReturnType:
-            result = await decorated_func(*args, **kwargs)
-
-            if inspect.iscoroutinefunction(other_func):
-                other = await other_func(*args, **kwargs)
-            else:
-                other = other_func(*args, **kwargs)
-
-            if other != result:
-                raise AssertionError(f'Different outputs: Function "{decorated_func.__name__}" returns {result} and '
-                                     f'function "{other_func.__name__}" returns {other} for parameters {args} {kwargs}')
-            return result
-
-        if inspect.iscoroutinefunction(decorated_func):
-            return async_wrapper
-        else:
-            return wrapper
-
-    return decorator
-
-
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
-
@@ -98,17 +48,6 @@

Functions

def does_same_as_function(other_func: Callable[..., ~ReturnType]) ‑> Callable[..., ~ReturnType]
-

Each time the decorated function is executed, the function other_func is also executed and the results -are compared. An AssertionError is raised if the results are not equal.

-

Example:

-
>>> def other_calculation(a, b, c):
-...     return c + b + a
->>> @does_same_as_function(other_calculation)
-... def some_calculation(a, b, c):
-...     return a + b + c
->>> some_calculation(1, 2, 3)
-6
-
Expand source code @@ -161,6 +100,17 @@

Functions

return decorator
+

Each time the decorated function is executed, the function other_func is also executed and the results +are compared. An AssertionError is raised if the results are not equal.

+

Example:

+
>>> def other_calculation(a, b, c):
+...     return c + b + a
+>>> @does_same_as_function(other_calculation)
+... def some_calculation(a, b, c):
+...     return a + b + c
+>>> some_calculation(1, 2, 3)
+6
+
@@ -168,7 +118,6 @@

Functions

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/fn_deco_in_subprocess.html b/docs/pedantic/decorators/fn_deco_in_subprocess.html index 593cf0f..d152fb0 100644 --- a/docs/pedantic/decorators/fn_deco_in_subprocess.html +++ b/docs/pedantic/decorators/fn_deco_in_subprocess.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.fn_deco_in_subprocess API documentation - - - - - - + + + + + + - - + +
@@ -22,61 +36,23 @@

Module pedantic.decorators.fn_deco_in_subprocess

+
+
+
+
+
+
+

Functions

+
+
+async def calculate_in_subprocess(func: Callable[..., ~T | Awaitable[~T]], *args: Any, **kwargs: Any) ‑> ~T +
+
Expand source code -
import asyncio
-import inspect
-from functools import wraps
-from typing import Callable, TypeVar, Any, Awaitable, Optional, Type, Union
-
-try:
-    from multiprocess import Process, Pipe
-    from multiprocess.connection import Connection
-except ImportError:
-    Process: Optional[Type] = None
-    Pipe: Optional[Type] = None
-    Connection: Optional[Type] = None
-
-T = TypeVar('T')
-
-
-class SubprocessError:
-    """ Is returned by the subprocess if an error occurs in the subprocess. """
-
-    def __init__(self, ex: Exception) -> None:
-        self.exception = ex
-
-
-def in_subprocess(func: Callable[..., Union[T, Awaitable[T]]]) -> Callable[..., Awaitable[T]]:
-    """
-        Executes the decorated function in a subprocess and returns the return value of it.
-        Note that the decorated function will be replaced with an async function which returns
-        a coroutine that needs to be awaited.
-        This purpose of this is doing long-taking calculations without blocking the main thread
-        of your application synchronously. That ensures that other asyncio.Tasks can work without any problem
-        at the same time.
-
-        Example:
-            >>> import time
-            >>> import asyncio
-            >>> @in_subprocess
-            ... def f(value: int) -> int:
-            ...     time.sleep(0.1)  # a long taking synchronous blocking calculation
-            ...     return 2 * value
-            >>> asyncio.run(f(value=42))
-            84
-    """
-
-    @wraps(func)
-    async def wrapper(*args: Any, **kwargs: Any) -> T:
-        return await calculate_in_subprocess(func, *args, **kwargs)
-
-    return wrapper
-
-
-async def calculate_in_subprocess(func: Callable[..., Union[T, Awaitable[T]]], *args: Any, **kwargs: Any) -> T:
+
async def calculate_in_subprocess(func: Callable[..., Union[T, Awaitable[T]]], *args: Any, **kwargs: Any) -> T:
     """
         Calculates the result of a synchronous function in subprocess without blocking the current thread.
 
@@ -128,45 +104,8 @@ 

Module pedantic.decorators.fn_deco_in_subprocess< if isinstance(result, SubprocessError): raise result.exception - return result - - -def _inner(tx: Connection, fun: Callable[..., Union[T, Awaitable[T]]], *a, **kw_args) -> None: - """ This runs in another process. """ - - event_loop = None - if inspect.iscoroutinefunction(fun): - event_loop = asyncio.new_event_loop() - asyncio.set_event_loop(event_loop) - - try: - if event_loop is not None: - res = event_loop.run_until_complete(fun(*a, **kw_args)) - else: - res = fun(*a, **kw_args) - except Exception as ex: - tx.send(SubprocessError(ex=ex)) - else: - tx.send(res) - - -if __name__ == '__main__': - import doctest - - doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)

+ return result
-
-
-
-
-
-
-

Functions

-
-
-async def calculate_in_subprocess(func: Callable[..., Union[~T, Awaitable[~T]]], *args: Any, **kwargs: Any) ‑> ~T -
-

Calculates the result of a synchronous function in subprocess without blocking the current thread.

Arguments

func: The function that will be called in a subprocess. @@ -186,85 +125,11 @@

Example

>>> asyncio.run(calculate_in_subprocess(func=f, value=42)) 84
-
- -Expand source code - -
async def calculate_in_subprocess(func: Callable[..., Union[T, Awaitable[T]]], *args: Any, **kwargs: Any) -> T:
-    """
-        Calculates the result of a synchronous function in subprocess without blocking the current thread.
-
-        Arguments:
-            func: The function that will be called in a subprocess.
-            args: Positional arguments that will be passed to the function.
-            kwargs: Keyword arguments that will be passed to the function.
-
-        Returns:
-             The calculated result of the function "func".
-
-        Raises:
-            Any Exception that is raised inside [func].
-
-        Further reading: https://medium.com/devopss-hole/python-multiprocessing-pickle-issue-e2d35ccf96a9
-
-        Example:
-            >>> import time
-            >>> import asyncio
-            >>> def f(value: int) -> int:
-            ...     time.sleep(0.1)  # a long taking synchronous blocking calculation
-            ...     return 2 * value
-            >>> asyncio.run(calculate_in_subprocess(func=f, value=42))
-            84
-    """
-
-    if Pipe is None:
-        raise ImportError('You need to install the multiprocess package to use this: pip install multiprocess')
-
-    rx, tx = Pipe(duplex=False)  # receiver & transmitter ; Pipe is one-way only
-    process = Process(target=_inner, args=(tx, func, *args), kwargs=kwargs)
-    process.start()
-
-    event = asyncio.Event()
-    loop = asyncio.get_event_loop()
-    loop.add_reader(fd=rx.fileno(), callback=event.set)
-
-    if not rx.poll():  # do not use process.is_alive() as condition here
-        await event.wait()
-
-    loop.remove_reader(fd=rx.fileno())
-    event.clear()
-
-    result = rx.recv()
-    process.join()  # this blocks synchronously! make sure that process is terminated before you call join()
-    rx.close()
-    tx.close()
-
-    if isinstance(result, SubprocessError):
-        raise result.exception
-
-    return result
-
-def in_subprocess(func: Callable[..., Union[~T, Awaitable[~T]]]) ‑> Callable[..., Awaitable[~T]] +def in_subprocess(func: Callable[..., ~T | Awaitable[~T]]) ‑> Callable[..., Awaitable[~T]]
-

Executes the decorated function in a subprocess and returns the return value of it. -Note that the decorated function will be replaced with an async function which returns -a coroutine that needs to be awaited. -This purpose of this is doing long-taking calculations without blocking the main thread -of your application synchronously. That ensures that other asyncio.Tasks can work without any problem -at the same time.

-

Example

-
>>> import time
->>> import asyncio
->>> @in_subprocess
-... def f(value: int) -> int:
-...     time.sleep(0.1)  # a long taking synchronous blocking calculation
-...     return 2 * value
->>> asyncio.run(f(value=42))
-84
-
Expand source code @@ -295,6 +160,22 @@

Example

return wrapper
+

Executes the decorated function in a subprocess and returns the return value of it. +Note that the decorated function will be replaced with an async function which returns +a coroutine that needs to be awaited. +This purpose of this is doing long-taking calculations without blocking the main thread +of your application synchronously. That ensures that other asyncio.Tasks can work without any problem +at the same time.

+

Example

+
>>> import time
+>>> import asyncio
+>>> @in_subprocess
+... def f(value: int) -> int:
+...     time.sleep(0.1)  # a long taking synchronous blocking calculation
+...     return 2 * value
+>>> asyncio.run(f(value=42))
+84
+
@@ -306,7 +187,6 @@

Classes

(ex: Exception)
-

Is returned by the subprocess if an error occurs in the subprocess.

Expand source code @@ -317,12 +197,12 @@

Classes

def __init__(self, ex: Exception) -> None: self.exception = ex
+

Is returned by the subprocess if an error occurs in the subprocess.

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/fn_deco_mock.html b/docs/pedantic/decorators/fn_deco_mock.html index 1137b01..d7f46ca 100644 --- a/docs/pedantic/decorators/fn_deco_mock.html +++ b/docs/pedantic/decorators/fn_deco_mock.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.fn_deco_mock API documentation - - - - - - + + + + + + - - + +
@@ -22,54 +36,6 @@

Module pedantic.decorators.fn_deco_mock

-
- -Expand source code - -
import inspect
-from functools import wraps
-from typing import Any
-
-from pedantic.constants import ReturnType, F
-
-
-def mock(return_value: ReturnType) -> F:
-    """
-        Skip the execution of the function and simply return the given return value instead.
-        This can be useful you want to check quickly if the behavior of the function causes a specific problem.
-        Without this decorator you actually need to change the implementation of the function temporarily.
-
-        Example:
-
-        >>> @mock(return_value=42)
-        ... def my_function(a, b, c):
-        ...     return a + b + c
-        >>> my_function(1, 2, 3)
-        42
-        >>> my_function(1000, 88, 204)
-        42
-    """
-
-    def decorator(func: F) -> F:
-        @wraps(func)
-        def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
-            return return_value
-
-        @wraps(func)
-        async def async_wrapper(*args: Any, **kwargs: Any) -> ReturnType:
-            return return_value
-
-        if inspect.iscoroutinefunction(func):
-            return async_wrapper
-        else:
-            return wrapper
-    return decorator
-
-
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
-
@@ -82,18 +48,6 @@

Functions

def mock(return_value: ~ReturnType) ‑> Callable[..., ~ReturnType]
-

Skip the execution of the function and simply return the given return value instead. -This can be useful you want to check quickly if the behavior of the function causes a specific problem. -Without this decorator you actually need to change the implementation of the function temporarily.

-

Example:

-
>>> @mock(return_value=42)
-... def my_function(a, b, c):
-...     return a + b + c
->>> my_function(1, 2, 3)
-42
->>> my_function(1000, 88, 204)
-42
-
Expand source code @@ -130,6 +84,18 @@

Functions

return wrapper return decorator
+

Skip the execution of the function and simply return the given return value instead. +This can be useful you want to check quickly if the behavior of the function causes a specific problem. +Without this decorator you actually need to change the implementation of the function temporarily.

+

Example:

+
>>> @mock(return_value=42)
+... def my_function(a, b, c):
+...     return a + b + c
+>>> my_function(1, 2, 3)
+42
+>>> my_function(1000, 88, 204)
+42
+
@@ -137,7 +103,6 @@

Functions

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/fn_deco_overrides.html b/docs/pedantic/decorators/fn_deco_overrides.html index 5fbd251..148924b 100644 --- a/docs/pedantic/decorators/fn_deco_overrides.html +++ b/docs/pedantic/decorators/fn_deco_overrides.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.fn_deco_overrides API documentation - - - - - - + + + + + + - - + +
@@ -22,47 +36,6 @@

Module pedantic.decorators.fn_deco_overrides

-
- -Expand source code - -
from typing import Type
-
-from pedantic.constants import F
-from pedantic.exceptions import PedanticOverrideException
-
-
-def overrides(base_class: Type) -> F:
-    """
-        This is used for marking methods that overrides methods of the base class which makes the code more readable.
-        This decorator raises an Exception if the decorated method is not a method in the parent class.
-
-        Example:
-
-        >>> class Parent:
-        ...     def my_instance_method(self):
-        ...         pass
-        >>> class Child(Parent):
-        ...     @overrides(Parent)
-        ...     def my_instance_method(self):
-        ...         print('hello world')
-    """
-
-    def decorator(func: F) -> F:
-        name = func.__name__
-
-        if name not in dir(base_class):
-            raise PedanticOverrideException(
-                f'In function {func.__qualname__}:\n '
-                f'Base class "{base_class.__name__}" does not have such a method "{name}".')
-        return func
-    return decorator
-
-
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
-
@@ -75,17 +48,6 @@

Functions

def overrides(base_class: Type) ‑> Callable[..., ~ReturnType]
-

This is used for marking methods that overrides methods of the base class which makes the code more readable. -This decorator raises an Exception if the decorated method is not a method in the parent class.

-

Example:

-
>>> class Parent:
-...     def my_instance_method(self):
-...         pass
->>> class Child(Parent):
-...     @overrides(Parent)
-...     def my_instance_method(self):
-...         print('hello world')
-
Expand source code @@ -116,6 +78,17 @@

Functions

return func return decorator
+

This is used for marking methods that overrides methods of the base class which makes the code more readable. +This decorator raises an Exception if the decorated method is not a method in the parent class.

+

Example:

+
>>> class Parent:
+...     def my_instance_method(self):
+...         pass
+>>> class Child(Parent):
+...     @overrides(Parent)
+...     def my_instance_method(self):
+...         print('hello world')
+
@@ -123,7 +96,6 @@

Functions

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/fn_deco_pedantic.html b/docs/pedantic/decorators/fn_deco_pedantic.html index 8c869ff..609a08a 100644 --- a/docs/pedantic/decorators/fn_deco_pedantic.html +++ b/docs/pedantic/decorators/fn_deco_pedantic.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.fn_deco_pedantic API documentation - - - - - - + + + + + + - - + +
@@ -22,22 +36,23 @@

Module pedantic.decorators.fn_deco_pedantic

+
+
+
+
+
+
+

Functions

+
+
+def pedantic(func: Callable[..., ~ReturnType] | None = None,
require_docstring: bool = False) ‑> Callable[..., ~ReturnType]
+
+
Expand source code -
from functools import wraps
-from typing import Any, Optional
-
-from pedantic.get_context import get_context
-from pedantic.type_checking_logic.check_docstring import _check_docstring
-from pedantic.constants import ReturnType, F
-from pedantic.models.decorated_function import DecoratedFunction
-from pedantic.models.function_call import FunctionCall
-from pedantic.env_var_logic import is_enabled
-
-
-def pedantic(func: Optional[F] = None, require_docstring: bool = False) -> F:
+
def pedantic(func: Optional[F] = None, require_docstring: bool = False) -> F:
     """
         A PedanticException is raised if one of the following happened:
         - The decorated function is called with positional arguments.
@@ -99,30 +114,8 @@ 

Module pedantic.decorators.fn_deco_pedantic

else: return wrapper - return decorator if func is None else decorator(f=func) - - -def pedantic_require_docstring(func: Optional[F] = None) -> F: - """Shortcut for @pedantic(require_docstring=True) """ - return pedantic(func=func, require_docstring=True) - - -if __name__ == "__main__": - import doctest - doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
+ return decorator if func is None else decorator(f=func)
-
-
-
-
-
-
-

Functions

-
-
-def pedantic(func: Optional[Callable[..., ~ReturnType]] = None, require_docstring: bool = False) ‑> Callable[..., ~ReturnType] -
-

A PedanticException is raised if one of the following happened: - The decorated function is called with positional arguments. - The function has no type annotation for their return type or one or more parameters do not have type @@ -155,80 +148,11 @@

Functions

pedantic.exceptions.PedanticCallWithArgsException: In function my_function: Use kwargs when you call function my_function. Args: (5, 4.0, 'hi')
-
- -Expand source code - -
def pedantic(func: Optional[F] = None, require_docstring: bool = False) -> F:
-    """
-        A PedanticException is raised if one of the following happened:
-        - The decorated function is called with positional arguments.
-        - The function has no type annotation for their return type or one or more parameters do not have type
-            annotations.
-        - A type annotation is incorrect.
-        - A type annotation misses type arguments, e.g. typing.List instead of typing.List[int].
-        - The documented arguments do not match the argument list or their type annotations.
-
-       Example:
-
-       >>> @pedantic
-       ... def my_function(a: int, b: float, c: str) -> bool:
-       ...     return float(a) == b and str(b) == c
-       >>> my_function(a=42.0, b=14.0, c='hi')
-       Traceback (most recent call last):
-       ...
-       pedantic.exceptions.PedanticTypeCheckException: In function my_function:
-       Type hint is incorrect: Argument a=42.0 of type <class 'float'> does not match expected type <class 'int'>.
-       >>> my_function(a=42, b=None, c='hi')
-       Traceback (most recent call last):
-       ...
-       pedantic.exceptions.PedanticTypeCheckException: In function my_function:
-       Type hint is incorrect: Argument b=None of type <class 'NoneType'> does not match expected type <class 'float'>.
-       >>> my_function(a=42, b=42, c='hi')
-       Traceback (most recent call last):
-       ...
-       pedantic.exceptions.PedanticTypeCheckException: In function my_function:
-       Type hint is incorrect: Argument b=42 of type <class 'int'> does not match expected type <class 'float'>.
-       >>> my_function(5, 4.0, 'hi')
-       Traceback (most recent call last):
-       ...
-       pedantic.exceptions.PedanticCallWithArgsException: In function my_function:
-       Use kwargs when you call function my_function. Args: (5, 4.0, 'hi')
-   """
-
-    def decorator(f: F) -> F:
-        if not is_enabled():
-            return f
-
-        decorated_func = DecoratedFunction(func=f)
-
-        if decorated_func.docstring is not None and (require_docstring or len(decorated_func.docstring.params)) > 0:
-            _check_docstring(decorated_func=decorated_func)
-
-        @wraps(f)
-        def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
-            call = FunctionCall(func=decorated_func, args=args, kwargs=kwargs, context=get_context(2))
-            call.assert_uses_kwargs()
-            return call.check_types()
-
-        async def async_wrapper(*args: Any, **kwargs: Any) -> ReturnType:
-            call = FunctionCall(func=decorated_func, args=args, kwargs=kwargs, context=get_context(2))
-            call.assert_uses_kwargs()
-            return await call.async_check_types()
-
-        if decorated_func.is_coroutine:
-            return async_wrapper
-        else:
-            return wrapper
-
-    return decorator if func is None else decorator(f=func)
-
-def pedantic_require_docstring(func: Optional[Callable[..., ~ReturnType]] = None) ‑> Callable[..., ~ReturnType] +def pedantic_require_docstring(func: Callable[..., ~ReturnType] | None = None) ‑> Callable[..., ~ReturnType]
-

Shortcut for @pedantic(require_docstring=True)

Expand source code @@ -237,6 +161,7 @@

Functions

"""Shortcut for @pedantic(require_docstring=True) """ return pedantic(func=func, require_docstring=True)
+

Shortcut for @pedantic(require_docstring=True)

@@ -244,7 +169,6 @@

Functions

- \ No newline at end of file + diff --git a/docs/pedantic/decorators/fn_deco_rename_kwargs.html b/docs/pedantic/decorators/fn_deco_rename_kwargs.html index d16db62..8f126b8 100644 --- a/docs/pedantic/decorators/fn_deco_rename_kwargs.html +++ b/docs/pedantic/decorators/fn_deco_rename_kwargs.html @@ -2,18 +2,32 @@ - - + + pedantic.decorators.fn_deco_rename_kwargs API documentation - - - - - - + + + + + + - - + +
@@ -22,63 +36,6 @@

Module pedantic.decorators.fn_deco_rename_kwargs

-
- -Expand source code - -
from functools import wraps
-from typing import Callable
-
-from pedantic.constants import F, ReturnType
-
-
-class Rename:
-    def __init__(self, from_: str, to: str) -> None:
-        self.from_ = from_
-        self.to = to
-
-
-def rename_kwargs(*params: Rename) -> Callable[[F], F]:
-    """
-        Renames the keyword arguments based on the given "Rename" rules when the decorated function is called.
-        You can also use this to define aliases for keyword arguments.
-
-        Example:
-
-        >>> @rename_kwargs(
-        ...     Rename(from_='firstname', to='a'),
-        ...     Rename(from_='lastname', to='b'),
-        ... )
-        ... def my_function(a, b):
-        ...     return a + ' ' + b
-        >>> my_function(a='egon', b='olsen')  # the normal way
-        'egon olsen'
-        >>> my_function(firstname='egon', lastname='olsen')  # using new defined keyword arguments
-        'egon olsen'
-    """
-
-    param_dict = {p.from_: p.to for p in params}
-
-    def decorator(func: F) -> F:
-        @wraps(func)
-        def wrapper(*args, **kwargs) -> ReturnType:
-            result_kwargs = {}
-
-            for k, v in kwargs.items():
-                if k in param_dict:
-                    result_kwargs[param_dict[k]] = kwargs[k]
-                else:
-                    result_kwargs[k] = kwargs[k]
-
-            return func(*args, **result_kwargs)
-        return wrapper
-    return decorator
-
-
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
-
@@ -91,20 +48,6 @@

Functions

def rename_kwargs(*params: Rename) ‑> Callable[[Callable[..., ~ReturnType]], Callable[..., ~ReturnType]]
-

Renames the keyword arguments based on the given "Rename" rules when the decorated function is called. -You can also use this to define aliases for keyword arguments.

-

Example:

-
>>> @rename_kwargs(
-...     Rename(from_='firstname', to='a'),
-...     Rename(from_='lastname', to='b'),
-... )
-... def my_function(a, b):
-...     return a + ' ' + b
->>> my_function(a='egon', b='olsen')  # the normal way
-'egon olsen'
->>> my_function(firstname='egon', lastname='olsen')  # using new defined keyword arguments
-'egon olsen'
-
Expand source code @@ -145,6 +88,20 @@

Functions

return wrapper return decorator
+

Renames the keyword arguments based on the given "Rename" rules when the decorated function is called. +You can also use this to define aliases for keyword arguments.

+

Example:

+
>>> @rename_kwargs(
+...     Rename(from_='firstname', to='a'),
+...     Rename(from_='lastname', to='b'),
+... )
+... def my_function(a, b):
+...     return a + ' ' + b
+>>> my_function(a='egon', b='olsen')  # the normal way
+'egon olsen'
+>>> my_function(firstname='egon', lastname='olsen')  # using new defined keyword arguments
+'egon olsen'
+
@@ -156,7 +113,6 @@

Classes

(from_: str, to: str)
-
Expand source code @@ -166,12 +122,12 @@

Classes

self.from_ = from_ self.to = to
+