From 3f34b562f4f4c3c10d9d23dc206f458fea105f79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 15:12:34 +0000 Subject: [PATCH 1/2] Bump ruff from 0.15.16 to 0.15.17 Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.16 to 0.15.17. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.15.16...0.15.17) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.15.17 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 27a41053..1f6a0573 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ dev = [ "pytest-cov==7.1.0", "Flask[async]==3.1.3", "multiprocess==0.70.19", - "ruff==0.15.16", + "ruff==0.15.17", ] [tool.deptry.per_rule_ignores] From fe29bb8b098a47fc6daa0a82eaf6941af3611aa1 Mon Sep 17 00:00:00 2001 From: Willi Sontopski <32729196+LostInDarkMath@users.noreply.github.com> Date: Fri, 12 Jun 2026 20:43:51 +0200 Subject: [PATCH 2/2] fix CI and links to docs --- .github/workflows/main.yml | 9 +- README.md | 44 +- docs/pedantic.html | 617 ++++++++++++++++++++------- docs/search.js | 2 +- pedantic/__init__.py | 6 + pedantic/decorators/__init__.py | 2 + pedantic/decorators/in_subprocess.py | 30 +- poetry.lock | 40 +- 8 files changed, 524 insertions(+), 226 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f77b1081..6889d549 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,8 +2,6 @@ name: Python Tests on: push: - branches: - - '*' permissions: contents: read @@ -53,6 +51,12 @@ jobs: task lint test: + if: | + always() && + ( + github.ref == 'refs/heads/master' || + needs.feature-branch-checks.result == 'success' + ) needs: feature-branch-checks runs-on: ubuntu-latest strategy: @@ -61,7 +65,6 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: diff --git a/README.md b/README.md index 69a20938..09fd52a0 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A collection of useful decorators in mixins for Python development. -## [GenericMixin](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/mixins/generic_mixin.html) +## [GenericMixin](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#GenericMixin) Do you need a way to figure out to which type a type variable is bound? With `GenericMixin` you can do exactly this: ```python @@ -17,7 +17,7 @@ f = Foo[str, int]() print(f.type_vars) # {T: , U: } ``` -## [@frozen_dataclass](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/frozen_dataclass.html) +## [@frozen_dataclass](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#frozen_dataclass) With `@frozen_dataclass` you can create immutable data classes with provides a `copy_with()` instance method. So you can write ```python @@ -42,9 +42,9 @@ class Foo: foo = Foo(a=6, b='hi') bar = replace(foo, a=42) ``` -You also can enfore run-time type checks for you dataclasses with `@frozen_dataclass(type_safe=True)`. +You also can enforce run-time type checks for you dataclasses with `@frozen_dataclass(type_safe=True)`. -## [@in_subprocess](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/in_subprocess.html) +## [@in_subprocess](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#in_subprocess) If you have an asynchronous service, that should perform some long-running calculation without blocking the event loop to keep the service responsive, you can use `@in_subprocess` to run the calculation in a separate process. ```python import time @@ -58,7 +58,7 @@ def f() -> int: await f() == 42 # calculation is done in a separate process => event loop is not blocked ``` -## [WithDecoratedMethods](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/mixins/with_decorated_methods.html) +## [WithDecoratedMethods](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#WithDecoratedMethods) You want to register instance methods of a class as callbacks with a decorator? Easy! ```python from pedantic import DecoratorType, create_decorator, WithDecoratedMethods @@ -82,7 +82,7 @@ class MyClass(WithDecoratedMethods[Decorators]): self.message_broker_client.subscribe(subject=subject, on_new_message=callback) ``` -## [@pedantic](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/pedantic_decorator.html) +## [@pedantic](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#pedantic) The `@pedantic` decorator enforces type annotations and check that passed arguments and returned values match those type annotations. ```python @@ -101,7 +101,7 @@ m.calc(s=45.0) # raises PedanticTypeCheckException Since this is type checking at runtime, it might be slow. So it is recommended to use it only in development mode. This is also **not** compatible with compiled source code (e.g., with [Nuitka](https://github.com/Nuitka/Nuitka)). -## [@validate](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/validate/validate.html) +## [@validate](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#validate) This is an alternative to the [flask-request-validator](https://github.com/d-ganchar/flask_request_validator) that allows you to make parsing arguments from requests and validate them easy. ```python from flask import Flask, Response, jsonify @@ -197,25 +197,25 @@ And it is not only for `flask`! The implementation is fully generic. ## Content of the package ### Decorators -- [@deprecated](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/deprecated.html) -- [@frozen_dataclass](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/frozen_dataclass.html#pedantic.decorators.frozen_dataclass.frozen_dataclass) -- [@frozen_type_safe_dataclass](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/frozen_dataclass.html#pedantic.decorators.frozen_dataclass.frozen_type_safe_dataclass) -- [@in_subprocess](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/in_subprocess.html) -- [@overrides](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/overrides.html) -- [@pedantic](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/pedantic_decorator.html) -- [@retry](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/retry.html) -- [@safe_async_contextmanager](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/safe_context_manager.html#pedantic.decorators.safe_context_manager.safe_async_contextmanager) -- [@safe_contextmanager](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/safe_context_manager.html#pedantic.decorators.safe_context_manager.safe_contextmanager) -- [@trace](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/trace.html) -- [@validate](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/decorators/validate/validate.html) +- [@deprecated](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#deprecated) +- [@frozen_dataclass](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#frozen_dataclass) +- [@frozen_type_safe_dataclass](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#frozen_type_safe_dataclass) +- [@in_subprocess](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#in_subprocess) +- [@overrides](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#overrides) +- [@pedantic](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#pedantic) +- [@retry](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#retry) +- [@safe_async_contextmanager](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#safe_async_contextmanager) +- [@safe_contextmanager](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#safe_contextmanager) +- [@trace](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#trace) +- [@validate](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#validate) ### Mixins -- [GenericMixin](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/mixins/generic_mixin.html) -- [WithDecoratedMethods](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic/mixins/with_decorated_methods.html) +- [GenericMixin](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#GenericMixin) +- [WithDecoratedMethods](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#WithDecoratedMethods) ### Helper Functions -- [decorate_class()]() -- [run_doctest_of_single_function()]() +- [decorate_class()](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#decorate_class) +- [run_doctest_of_single_function()](https://lostindarkmath.github.io/pedantic-python-decorators/pedantic.html#run_doctest_of_single_function) ## Contributing This project is based on [poetry](https://python-poetry.org/) and [taskfile](https://taskfile.dev). diff --git a/docs/pedantic.html b/docs/pedantic.html index 84639e76..8495be2e 100644 --- a/docs/pedantic.html +++ b/docs/pedantic.html @@ -389,6 +389,9 @@

API Documentation

  • create_decorator
  • +
  • + decorate_class +
  • deprecated
  • @@ -416,6 +419,12 @@

    API Documentation

  • run_doctest_of_single_function
  • +
  • + safe_async_contextmanager +
  • +
  • + safe_contextmanager +
  • trace
  • @@ -523,129 +532,135 @@

      1from pedantic.decorators import (
       2    calculate_in_subprocess,
    -  3    deprecated,
    -  4    frozen_dataclass,
    -  5    frozen_type_safe_dataclass,
    -  6    in_subprocess,
    -  7    overrides,
    -  8    pedantic,
    -  9    retry,
    - 10    trace,
    - 11)
    - 12from pedantic.decorators.validate.exceptions import (
    - 13    ConversionError,
    - 14    ExceptionDictKey,
    - 15    InvalidHeader,
    - 16    ParameterException,
    - 17    TooManyArguments,
    - 18    ValidateException,
    - 19    ValidatorException,
    - 20)
    - 21from pedantic.decorators.validate.parameters import (
    - 22    Deserializable,
    - 23    EnvironmentVariableParameter,
    - 24    ExternalParameter,
    - 25    Parameter,
    - 26)
    - 27from pedantic.decorators.validate.validate import (
    - 28    ReturnAs,
    - 29    validate,
    - 30)
    - 31from pedantic.decorators.validate.validators import (
    - 32    DatetimeIsoFormat,
    - 33    DateTimeUnixTimestamp,
    - 34    Email,
    - 35    ForEach,
    - 36    IsEnum,
    - 37    IsUuid,
    - 38    MatchPattern,
    - 39    Max,
    - 40    MaxLength,
    - 41    Min,
    - 42    MinLength,
    - 43    NotEmpty,
    - 44    Validator,
    - 45)
    - 46from pedantic.helper_fn import run_doctest_of_single_function
    - 47from pedantic.mixins import (
    - 48    DecoratorType,
    - 49    GenericMixin,
    - 50    WithDecoratedMethods,
    - 51    create_decorator,
    - 52)
    - 53from pedantic.type_checking_logic import (
    - 54    assert_value_matches_type,
    - 55    resolve_forward_ref,
    - 56)
    - 57
    - 58__all__ = [
    - 59    'ConversionError',
    - 60    'DateTimeUnixTimestamp',
    - 61    'DatetimeIsoFormat',
    - 62    'DecoratorType',
    - 63    'Deserializable',
    - 64    'Email',
    - 65    'EnvironmentVariableParameter',
    - 66    'ExceptionDictKey',
    - 67    'ExternalParameter',
    - 68    'ExternalParameter',
    - 69    'ForEach',
    - 70    'GenericMixin',
    - 71    'InvalidHeader',
    - 72    'IsEnum',
    - 73    'IsUuid',
    - 74    'MatchPattern',
    - 75    'Max',
    - 76    'MaxLength',
    - 77    'Min',
    - 78    'MinLength',
    - 79    'NotEmpty',
    - 80    'Parameter',
    - 81    'ParameterException',
    - 82    'ReturnAs',
    - 83    'TooManyArguments',
    - 84    'ValidateException',
    - 85    'Validator',
    - 86    'ValidatorException',
    - 87    'WithDecoratedMethods',
    - 88    'assert_value_matches_type',
    - 89    'calculate_in_subprocess',
    - 90    'create_decorator',
    - 91    'deprecated',
    - 92    'frozen_dataclass',
    - 93    'frozen_type_safe_dataclass',
    - 94    'in_subprocess',
    - 95    'overrides',
    - 96    'pedantic',
    - 97    'resolve_forward_ref',
    - 98    'retry',
    - 99    'run_doctest_of_single_function',
    -100    'trace',
    -101    'validate',
    -102]
    -103
    -104try:
    -105    from pedantic.decorators.validate.parameters import (
    -106        FlaskFormParameter,
    -107        FlaskGetParameter,
    -108        FlaskHeaderParameter,
    -109        FlaskJsonParameter,
    -110        FlaskParameter,
    -111        FlaskPathParameter,
    -112        GenericFlaskDeserializer,
    -113    )
    -114
    -115    __all__ +=[
    -116        'FlaskFormParameter',
    -117        'FlaskGetParameter',
    -118        'FlaskHeaderParameter',
    -119        'FlaskJsonParameter',
    -120        'FlaskParameter',
    -121        'FlaskPathParameter',
    -122        'GenericFlaskDeserializer',
    -123    ]
    -124except ImportError:
    -125    pass  # no Flask installed
    +  3    decorate_class,
    +  4    deprecated,
    +  5    frozen_dataclass,
    +  6    frozen_type_safe_dataclass,
    +  7    in_subprocess,
    +  8    overrides,
    +  9    pedantic,
    + 10    retry,
    + 11    safe_async_contextmanager,
    + 12    safe_contextmanager,
    + 13    trace,
    + 14)
    + 15from pedantic.decorators.validate.exceptions import (
    + 16    ConversionError,
    + 17    ExceptionDictKey,
    + 18    InvalidHeader,
    + 19    ParameterException,
    + 20    TooManyArguments,
    + 21    ValidateException,
    + 22    ValidatorException,
    + 23)
    + 24from pedantic.decorators.validate.parameters import (
    + 25    Deserializable,
    + 26    EnvironmentVariableParameter,
    + 27    ExternalParameter,
    + 28    Parameter,
    + 29)
    + 30from pedantic.decorators.validate.validate import (
    + 31    ReturnAs,
    + 32    validate,
    + 33)
    + 34from pedantic.decorators.validate.validators import (
    + 35    DatetimeIsoFormat,
    + 36    DateTimeUnixTimestamp,
    + 37    Email,
    + 38    ForEach,
    + 39    IsEnum,
    + 40    IsUuid,
    + 41    MatchPattern,
    + 42    Max,
    + 43    MaxLength,
    + 44    Min,
    + 45    MinLength,
    + 46    NotEmpty,
    + 47    Validator,
    + 48)
    + 49from pedantic.helper_fn import run_doctest_of_single_function
    + 50from pedantic.mixins import (
    + 51    DecoratorType,
    + 52    GenericMixin,
    + 53    WithDecoratedMethods,
    + 54    create_decorator,
    + 55)
    + 56from pedantic.type_checking_logic import (
    + 57    assert_value_matches_type,
    + 58    resolve_forward_ref,
    + 59)
    + 60
    + 61__all__ = [
    + 62    'ConversionError',
    + 63    'DateTimeUnixTimestamp',
    + 64    'DatetimeIsoFormat',
    + 65    'DecoratorType',
    + 66    'Deserializable',
    + 67    'Email',
    + 68    'EnvironmentVariableParameter',
    + 69    'ExceptionDictKey',
    + 70    'ExternalParameter',
    + 71    'ExternalParameter',
    + 72    'ForEach',
    + 73    'GenericMixin',
    + 74    'InvalidHeader',
    + 75    'IsEnum',
    + 76    'IsUuid',
    + 77    'MatchPattern',
    + 78    'Max',
    + 79    'MaxLength',
    + 80    'Min',
    + 81    'MinLength',
    + 82    'NotEmpty',
    + 83    'Parameter',
    + 84    'ParameterException',
    + 85    'ReturnAs',
    + 86    'TooManyArguments',
    + 87    'ValidateException',
    + 88    'Validator',
    + 89    'ValidatorException',
    + 90    'WithDecoratedMethods',
    + 91    'assert_value_matches_type',
    + 92    'calculate_in_subprocess',
    + 93    'create_decorator',
    + 94    'decorate_class',
    + 95    'deprecated',
    + 96    'frozen_dataclass',
    + 97    'frozen_type_safe_dataclass',
    + 98    'in_subprocess',
    + 99    'overrides',
    +100    'pedantic',
    +101    'resolve_forward_ref',
    +102    'retry',
    +103    'run_doctest_of_single_function',
    +104    'safe_async_contextmanager',
    +105    'safe_contextmanager',
    +106    'trace',
    +107    'validate',
    +108]
    +109
    +110try:
    +111    from pedantic.decorators.validate.parameters import (
    +112        FlaskFormParameter,
    +113        FlaskGetParameter,
    +114        FlaskHeaderParameter,
    +115        FlaskJsonParameter,
    +116        FlaskParameter,
    +117        FlaskPathParameter,
    +118        GenericFlaskDeserializer,
    +119    )
    +120
    +121    __all__ +=[
    +122        'FlaskFormParameter',
    +123        'FlaskGetParameter',
    +124        'FlaskHeaderParameter',
    +125        'FlaskJsonParameter',
    +126        'FlaskParameter',
    +127        'FlaskPathParameter',
    +128        'GenericFlaskDeserializer',
    +129    ]
    +130except ImportError:
    +131    pass  # no Flask installed
     
    @@ -3310,13 +3325,13 @@

    69 Further reading: https://medium.com/devopss-hole/python-multiprocessing-pickle-issue-e2d35ccf96a9 70 71 Example: - 72 >>> import time - 73 >>> import asyncio - 74 >>> def f(value: int) -> int: - 75 ... time.sleep(0.1) # a long taking synchronous blocking calculation - 76 ... return 2 * value - 77 >>> asyncio.run(calculate_in_subprocess(func=f, value=42)) - 78 84 + 72 >>> import time + 73 >>> import asyncio + 74 >>> def f(value: int) -> int: + 75 ... time.sleep(0.1) # a long taking synchronous blocking calculation + 76 ... return 2 * value + 77 >>> asyncio.run(calculate_in_subprocess(func=f, value=42)) + 78 84 79 """ 80 81 if Pipe is None: @@ -3365,19 +3380,16 @@

    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

    -
    -
    -
    +
    +
    >>> 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
    +
    +
    @@ -3424,6 +3436,65 @@

    + +
    + +
    + + def + decorate_class( cls: ~T, decorate_callable: Callable[[Callable, ...], Callable], *args: Any, allowed_dunder_methods: list[str] | None = None) -> ~T: + + + +
    + +
    17def decorate_class(
    +18    cls: T,
    +19    decorate_callable: Callable[[Callable, ...], Callable],
    +20    *args: Any,
    +21    allowed_dunder_methods: list[str] | None = None,
    +22) -> T:
    +23    """Applies a decorator with optional arguments to each method of a class."""
    +24
    +25    if allowed_dunder_methods is None:
    +26        allowed_dunder_methods = []
    +27
    +28    for attr_name, attr_value in vars(cls).items():
    +29        if attr_name.startswith('__') and attr_name.endswith('__') and attr_name not in allowed_dunder_methods:
    +30            continue
    +31
    +32        if inspect.isfunction(attr_value) or inspect.ismethod(attr_value):
    +33            setattr(cls, attr_name, decorate_callable(attr_value, *args))
    +34        elif isinstance(attr_value, staticmethod):
    +35            wrapped = decorate_callable(attr_value.__func__, *args)
    +36            setattr(cls, attr_name, staticmethod(wrapped))
    +37        elif isinstance(attr_value, classmethod):
    +38            wrapped = decorate_callable(attr_value.__func__, *args)
    +39            setattr(cls, attr_name, classmethod(wrapped))
    +40        elif isinstance(attr_value, property):
    +41            fget = decorate_callable(attr_value.fget, *args) if attr_value.fget is not None else None
    +42            fset = decorate_callable(attr_value.fset, *args) if attr_value.fset is not None else None
    +43            fdel = decorate_callable(attr_value.fdel, *args) if attr_value.fdel is not None else None
    +44
    +45            setattr(
    +46                cls,
    +47                attr_name,
    +48                property(
    +49                    fget=fget,
    +50                    fset=fset,
    +51                    fdel=fdel,
    +52                    doc=attr_value.__doc__,
    +53                ),
    +54            )
    +55
    +56    return cls
    +
    + + +

    Applies a decorator with optional arguments to each method of a class.

    +
    + +
    @@ -3778,14 +3849,14 @@

    34 at the same time. 35 36 Example: -37 >>> import time -38 >>> import asyncio -39 >>> @in_subprocess -40 ... def f(value: int) -> int: -41 ... time.sleep(0.1) # a long taking synchronous blocking calculation -42 ... return 2 * value -43 >>> asyncio.run(f(value=42)) -44 84 +37 >>> import time +38 >>> import asyncio +39 >>> @in_subprocess +40 ... def f(value: int) -> int: +41 ... time.sleep(0.1) # a long taking synchronous blocking calculation +42 ... return 2 * value +43 >>> asyncio.run(f(value=42)) +44 84 45 """ 46 47 @wraps(func) @@ -3805,20 +3876,17 @@

    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

    -
    -
    -
    +
    +
    >>> 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
    +
    +
    @@ -4159,6 +4227,225 @@

    +

    +
    + +
    + + def + safe_async_contextmanager( f: Callable[..., AsyncIterator[~T]]) -> Callable[..., contextlib.AbstractAsyncContextManager[~T]]: + + + +
    + +
     68def safe_async_contextmanager(f: Callable[..., AsyncIterator[T]]) -> Callable[..., AbstractAsyncContextManager[T]]:
    + 69    """
    + 70    @safe_async_contextmanager decorator.
    + 71
    + 72         Typical usage:
    + 73
    + 74            @safe_async_contextmanager
    + 75            async def some_async_generator(<arguments>):
    + 76                <setup>
    + 77                yield <value>
    + 78                <cleanup>
    + 79
    + 80        equivalent to this:
    + 81
    + 82            @asynccontextmanager
    + 83            async def some_async_generator(<arguments>):
    + 84                <setup>
    + 85                try:
    + 86                    yield <value>
    + 87                finally:
    + 88                    <cleanup>
    + 89
    + 90        This makes this:
    + 91
    + 92            async with some_async_generator(<arguments>) as <variable>:
    + 93                <body>
    + 94
    + 95        equivalent to this:
    + 96
    + 97            <setup>
    + 98            try:
    + 99                <variable> = <value>
    +100                <body>
    +101            finally:
    +102                <cleanup>
    +103    """
    +104
    +105    if not isasyncgenfunction(f):
    +106        if not isgeneratorfunction(f):
    +107            raise AssertionError(f'{f.__name__} is not a generator.')
    +108
    +109        raise AssertionError(f'{f.__name__} is not an async generator. '
    +110                             f'So you need to use "safe_contextmanager" instead.')
    +111
    +112    @wraps(f)
    +113    async def wrapper(*args: Any, **kwargs: Any) -> Iterator[T]:
    +114        iterator = f(*args, **kwargs)
    +115
    +116        try:
    +117            yield await anext(iterator)
    +118        finally:
    +119            try:  # noqa: SIM105
    +120                await anext(iterator)
    +121            except StopAsyncIteration:
    +122                pass
    +123
    +124    return asynccontextmanager(wrapper)
    +
    + + +

    @safe_async_contextmanager decorator.

    + +
     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>
    +
    +
    + + +
    +
    + +
    + + def + safe_contextmanager( f: Callable[..., Iterator[~T]]) -> Callable[..., contextlib.AbstractContextManager[~T]]: + + + +
    + +
    11def safe_contextmanager(f: Callable[..., Iterator[T]]) -> Callable[..., AbstractContextManager[T]]:
    +12    """
    +13    @safe_contextmanager decorator.
    +14
    +15    Typical usage:
    +16
    +17        @safe_contextmanager
    +18        def some_generator(<arguments>):
    +19            <setup>
    +20            yield <value>
    +21            <cleanup>
    +22
    +23    equivalent to this:
    +24
    +25        @contextmanager
    +26        def some_generator(<arguments>):
    +27            <setup>
    +28            try:
    +29                yield <value>
    +30            finally:
    +31                <cleanup>
    +32
    +33    This makes this:
    +34
    +35        with some_generator(<arguments>) as <variable>:
    +36            <body>
    +37
    +38    equivalent to this:
    +39
    +40        <setup>
    +41        try:
    +42            <variable> = <value>
    +43            <body>
    +44        finally:
    +45            <cleanup>
    +46    """
    +47
    +48    if isasyncgenfunction(f):
    +49        raise AssertionError(f'{f.__name__} is async. So you need to use "safe_async_contextmanager" instead.')
    +50    if not isgeneratorfunction(f):
    +51        raise AssertionError(f'{f.__name__} is not a generator.')
    +52
    +53    @wraps(f)
    +54    def wrapper(*args: Any, **kwargs: Any) -> Iterator[T]:
    +55        iterator = f(*args, **kwargs)
    +56
    +57        try:
    +58            yield next(iterator)
    +59        finally:
    +60            try:  # noqa: SIM105
    +61                next(iterator)
    +62            except StopIteration:
    +63                pass  # this is intended
    +64
    +65    return contextmanager(wrapper)
    +
    + + +

    @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>
    +
    +
    + +
    diff --git a/docs/search.js b/docs/search.js index a0f9d1d9..025f1f2e 100644 --- a/docs/search.js +++ b/docs/search.js @@ -1,6 +1,6 @@ window.pdocSearch = (function(){ /** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o

    \n"}, {"fullname": "pedantic.ConversionError", "modulename": "pedantic", "qualname": "ConversionError", "kind": "class", "doc": "

    Is raised if a type cast failed.

    \n", "bases": "pedantic.decorators.validate.exceptions.ValidateException"}, {"fullname": "pedantic.DateTimeUnixTimestamp", "modulename": "pedantic", "qualname": "DateTimeUnixTimestamp", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.DateTimeUnixTimestamp.validate", "modulename": "pedantic", "qualname": "DateTimeUnixTimestamp.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: float | str) -> datetime.datetime:", "funcdef": "def"}, {"fullname": "pedantic.DatetimeIsoFormat", "modulename": "pedantic", "qualname": "DatetimeIsoFormat", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.DatetimeIsoFormat.validate", "modulename": "pedantic", "qualname": "DatetimeIsoFormat.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: str) -> datetime.datetime:", "funcdef": "def"}, {"fullname": "pedantic.DecoratorType", "modulename": "pedantic", "qualname": "DecoratorType", "kind": "class", "doc": "

    The interface that defines all possible decorators types.

    \n\n

    The values of this enum are used as property names and the properties are added to the decorated functions.\nSo I would recommend naming them with a leading underscore to keep them private and also write it lowercase.

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    class Decorators(DecoratorType):\n ... FOO = '_foo'

    \n
    \n
    \n
    \n", "bases": "enum.StrEnum"}, {"fullname": "pedantic.Deserializable", "modulename": "pedantic", "qualname": "Deserializable", "kind": "class", "doc": "

    A tiny interface which has a static from_json() method which acts like a named constructor.

    \n", "bases": "abc.ABC"}, {"fullname": "pedantic.Deserializable.from_json", "modulename": "pedantic", "qualname": "Deserializable.from_json", "kind": "function", "doc": "

    A named constructor which creates an object from JSON.

    \n", "signature": "(\tdata: dict[str, typing.Any]) -> pedantic.decorators.validate.parameters.deserializable.Deserializable:", "funcdef": "def"}, {"fullname": "pedantic.Email", "modulename": "pedantic", "qualname": "Email", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.Email.__init__", "modulename": "pedantic", "qualname": "Email.__init__", "kind": "function", "doc": "

    \n", "signature": "(\temail_pattern: str = '[^@\\\\s]+@[^@\\\\s]+\\\\.[a-zA-Z0-9]+$',\tpost_processor: Callable[[str], str] = <function Email.<lambda>>)"}, {"fullname": "pedantic.Email.validate", "modulename": "pedantic", "qualname": "Email.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: str) -> str:", "funcdef": "def"}, {"fullname": "pedantic.EnvironmentVariableParameter", "modulename": "pedantic", "qualname": "EnvironmentVariableParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_external_parameter.ExternalParameter"}, {"fullname": "pedantic.EnvironmentVariableParameter.__init__", "modulename": "pedantic", "qualname": "EnvironmentVariableParameter.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tname: str,\tenv_var_name: str | None = None,\tvalue_type: type[str | bool | int | float] = <class 'str'>,\tvalidators: Iterable[pedantic.decorators.validate.validators.abstract_validator.Validator] | None = None,\trequired: bool = True,\tdefault: Any = <class 'pedantic.decorators.validate.parameters.abstract_parameter.NoValue'>)"}, {"fullname": "pedantic.EnvironmentVariableParameter.has_value", "modulename": "pedantic", "qualname": "EnvironmentVariableParameter.has_value", "kind": "function", "doc": "

    Returns True if the value can be fetched.

    \n", "signature": "(self) -> bool:", "funcdef": "def"}, {"fullname": "pedantic.EnvironmentVariableParameter.load_value", "modulename": "pedantic", "qualname": "EnvironmentVariableParameter.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.ExceptionDictKey", "modulename": "pedantic", "qualname": "ExceptionDictKey", "kind": "class", "doc": "

    \n"}, {"fullname": "pedantic.ExceptionDictKey.VALUE", "modulename": "pedantic", "qualname": "ExceptionDictKey.VALUE", "kind": "variable", "doc": "

    \n", "default_value": "'VALUE'"}, {"fullname": "pedantic.ExceptionDictKey.MESSAGE", "modulename": "pedantic", "qualname": "ExceptionDictKey.MESSAGE", "kind": "variable", "doc": "

    \n", "default_value": "'MESSAGE'"}, {"fullname": "pedantic.ExceptionDictKey.PARAMETER", "modulename": "pedantic", "qualname": "ExceptionDictKey.PARAMETER", "kind": "variable", "doc": "

    \n", "default_value": "'PARAMETER'"}, {"fullname": "pedantic.ExceptionDictKey.VALIDATOR", "modulename": "pedantic", "qualname": "ExceptionDictKey.VALIDATOR", "kind": "variable", "doc": "

    \n", "default_value": "'VALIDATOR'"}, {"fullname": "pedantic.ExternalParameter", "modulename": "pedantic", "qualname": "ExternalParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_parameter.Parameter, abc.ABC"}, {"fullname": "pedantic.ExternalParameter.has_value", "modulename": "pedantic", "qualname": "ExternalParameter.has_value", "kind": "function", "doc": "

    Returns True if the value can be fetched.

    \n", "signature": "(self) -> bool:", "funcdef": "def"}, {"fullname": "pedantic.ExternalParameter.load_value", "modulename": "pedantic", "qualname": "ExternalParameter.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.ForEach", "modulename": "pedantic", "qualname": "ForEach", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.ForEach.__init__", "modulename": "pedantic", "qualname": "ForEach.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tvalidators: pedantic.decorators.validate.validators.abstract_validator.Validator | Iterable[pedantic.decorators.validate.validators.abstract_validator.Validator])"}, {"fullname": "pedantic.ForEach.validate", "modulename": "pedantic", "qualname": "ForEach.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Iterable[typing.Any]) -> list[typing.Any]:", "funcdef": "def"}, {"fullname": "pedantic.GenericMixin", "modulename": "pedantic", "qualname": "GenericMixin", "kind": "class", "doc": "

    A mixin that provides easy access to given type variables.

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    from typing import Generic, TypeVar\n T = TypeVar('T')\n U = TypeVar('U')\n class Foo(Generic[T, U], GenericMixin):\n ... values: list[T]\n ... value: U\n f = Foostr, int\n f.type_vars\n {~T: , ~U: }

    \n
    \n
    \n
    \n"}, {"fullname": "pedantic.GenericMixin.type_vars", "modulename": "pedantic", "qualname": "GenericMixin.type_vars", "kind": "variable", "doc": "

    Returns the mapping of type variables to types.

    \n\n

    DO NOT call this inside __init__()!

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    from typing import Generic, TypeVar\n T = TypeVar('T')\n U = TypeVar('U')\n class Foo(Generic[T, U], GenericMixin):\n ... values: list[T]\n ... value: U\n f = Foostr, int\n f.type_vars\n {~T: , ~U: }

    \n
    \n
    \n
    \n", "annotation": ": dict[typing.TypeVar, type]"}, {"fullname": "pedantic.InvalidHeader", "modulename": "pedantic", "qualname": "InvalidHeader", "kind": "class", "doc": "

    Is raised if there is a validation error in a FlaskHeaderParameter.

    \n", "bases": "pedantic.decorators.validate.exceptions.ParameterException"}, {"fullname": "pedantic.IsEnum", "modulename": "pedantic", "qualname": "IsEnum", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.IsEnum.__init__", "modulename": "pedantic", "qualname": "IsEnum.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tenum: enum.EnumType,\tconvert: bool = True,\tto_upper_case: bool = True)"}, {"fullname": "pedantic.IsEnum.validate", "modulename": "pedantic", "qualname": "IsEnum.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Any) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.IsUuid", "modulename": "pedantic", "qualname": "IsUuid", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.IsUuid.__init__", "modulename": "pedantic", "qualname": "IsUuid.__init__", "kind": "function", "doc": "

    \n", "signature": "(convert: bool = False)"}, {"fullname": "pedantic.IsUuid.validate", "modulename": "pedantic", "qualname": "IsUuid.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: str) -> str:", "funcdef": "def"}, {"fullname": "pedantic.MatchPattern", "modulename": "pedantic", "qualname": "MatchPattern", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.MatchPattern.__init__", "modulename": "pedantic", "qualname": "MatchPattern.__init__", "kind": "function", "doc": "

    \n", "signature": "(pattern: str)"}, {"fullname": "pedantic.MatchPattern.validate", "modulename": "pedantic", "qualname": "MatchPattern.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: str) -> str:", "funcdef": "def"}, {"fullname": "pedantic.Max", "modulename": "pedantic", "qualname": "Max", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.Max.__init__", "modulename": "pedantic", "qualname": "Max.__init__", "kind": "function", "doc": "
    \n
    >>> Max(7, True).validate(7)\n7\n>>> Max(7, False).validate(7)  # doctest: +IGNORE_EXCEPTION_DETAIL\nTraceback (most recent call last):\nValidatorException: ...\n>>> Max(7, False).validate(6.999)\n6.999\n
    \n
    \n", "signature": "(value: float, include_boundary: bool = True)"}, {"fullname": "pedantic.Max.validate", "modulename": "pedantic", "qualname": "Max.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: float) -> int | float:", "funcdef": "def"}, {"fullname": "pedantic.MaxLength", "modulename": "pedantic", "qualname": "MaxLength", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.MaxLength.__init__", "modulename": "pedantic", "qualname": "MaxLength.__init__", "kind": "function", "doc": "

    \n", "signature": "(length: int)"}, {"fullname": "pedantic.MaxLength.validate", "modulename": "pedantic", "qualname": "MaxLength.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Sized) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.Min", "modulename": "pedantic", "qualname": "Min", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.Min.__init__", "modulename": "pedantic", "qualname": "Min.__init__", "kind": "function", "doc": "
    \n
    >>> Min(7, True).validate(7)\n7\n>>> Min(7, False).validate(7)  # doctest: +IGNORE_EXCEPTION_DETAIL\nTraceback (most recent call last):\nValidatorException: ...\n>>> Min(7, False).validate(7.001)\n7.001\n
    \n
    \n", "signature": "(value: float, include_boundary: bool = True)"}, {"fullname": "pedantic.Min.validate", "modulename": "pedantic", "qualname": "Min.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: float) -> int | float:", "funcdef": "def"}, {"fullname": "pedantic.MinLength", "modulename": "pedantic", "qualname": "MinLength", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.MinLength.__init__", "modulename": "pedantic", "qualname": "MinLength.__init__", "kind": "function", "doc": "

    \n", "signature": "(length: int)"}, {"fullname": "pedantic.MinLength.validate", "modulename": "pedantic", "qualname": "MinLength.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Sized) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.NotEmpty", "modulename": "pedantic", "qualname": "NotEmpty", "kind": "class", "doc": "

    Validates that the given value is not empty.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.NotEmpty.__init__", "modulename": "pedantic", "qualname": "NotEmpty.__init__", "kind": "function", "doc": "

    If strip is True, the leading and trailing whitespace will be removed.

    \n", "signature": "(strip: bool = True)"}, {"fullname": "pedantic.NotEmpty.strip", "modulename": "pedantic", "qualname": "NotEmpty.strip", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.NotEmpty.validate", "modulename": "pedantic", "qualname": "NotEmpty.validate", "kind": "function", "doc": "

    Throws a ValidationError if the sequence is empty.\nIf the sequence is a string, it removes all leading and trailing whitespace.

    \n", "signature": "(self, value: Sequence) -> Sequence:", "funcdef": "def"}, {"fullname": "pedantic.Parameter", "modulename": "pedantic", "qualname": "Parameter", "kind": "class", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.__init__", "modulename": "pedantic", "qualname": "Parameter.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tname: str,\tvalue_type: type[bool | int | float | str | dict | list] | None = None,\tvalidators: Iterable[pedantic.decorators.validate.validators.abstract_validator.Validator] | None = None,\tdefault: Any = <class 'pedantic.decorators.validate.parameters.abstract_parameter.NoValue'>,\trequired: bool = True)"}, {"fullname": "pedantic.Parameter.exception_type", "modulename": "pedantic", "qualname": "Parameter.exception_type", "kind": "variable", "doc": "

    \n", "annotation": ": type[pedantic.decorators.validate.exceptions.ParameterException]", "default_value": "<class 'pedantic.decorators.validate.exceptions.ParameterException'>"}, {"fullname": "pedantic.Parameter.name", "modulename": "pedantic", "qualname": "Parameter.name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.validators", "modulename": "pedantic", "qualname": "Parameter.validators", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.default_value", "modulename": "pedantic", "qualname": "Parameter.default_value", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.value_type", "modulename": "pedantic", "qualname": "Parameter.value_type", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.is_required", "modulename": "pedantic", "qualname": "Parameter.is_required", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.validate", "modulename": "pedantic", "qualname": "Parameter.validate", "kind": "function", "doc": "

    Apply all validators to the given value and collect all ValidationErrors.

    \n", "signature": "(self, value: Any) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.Parameter.raise_exception", "modulename": "pedantic", "qualname": "Parameter.raise_exception", "kind": "function", "doc": "

    \n", "signature": "(\tself,\tmsg: str,\tvalue: Any = None,\tvalidator: pedantic.decorators.validate.validators.abstract_validator.Validator | None = None) -> NoReturn:", "funcdef": "def"}, {"fullname": "pedantic.ParameterException", "modulename": "pedantic", "qualname": "ParameterException", "kind": "class", "doc": "

    An exception that is raised inside a Parameter.

    \n", "bases": "pedantic.decorators.validate.exceptions.ValidateException"}, {"fullname": "pedantic.ParameterException.__init__", "modulename": "pedantic", "qualname": "ParameterException.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tmsg: str,\tparameter_name: str,\tvalue: Any | None = None,\tvalidator_name: str | None = None)"}, {"fullname": "pedantic.ParameterException.validator_name", "modulename": "pedantic", "qualname": "ParameterException.validator_name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ParameterException.parameter_name", "modulename": "pedantic", "qualname": "ParameterException.parameter_name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ParameterException.value", "modulename": "pedantic", "qualname": "ParameterException.value", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ParameterException.from_validator_exception", "modulename": "pedantic", "qualname": "ParameterException.from_validator_exception", "kind": "function", "doc": "

    Creates a parameter exception from a validator exception.

    \n", "signature": "(\tcls,\texception: pedantic.decorators.validate.exceptions.ValidatorException,\tparameter_name: str = '') -> pedantic.decorators.validate.exceptions.ParameterException:", "funcdef": "def"}, {"fullname": "pedantic.ParameterException.to_dict", "modulename": "pedantic", "qualname": "ParameterException.to_dict", "kind": "variable", "doc": "

    \n", "annotation": ": dict[str, str]"}, {"fullname": "pedantic.ReturnAs", "modulename": "pedantic", "qualname": "ReturnAs", "kind": "class", "doc": "

    \n", "bases": "enum.Enum"}, {"fullname": "pedantic.ReturnAs.ARGS", "modulename": "pedantic", "qualname": "ReturnAs.ARGS", "kind": "variable", "doc": "

    \n", "default_value": "<ReturnAs.ARGS: 'ARGS'>"}, {"fullname": "pedantic.ReturnAs.KWARGS_WITH_NONE", "modulename": "pedantic", "qualname": "ReturnAs.KWARGS_WITH_NONE", "kind": "variable", "doc": "

    \n", "default_value": "<ReturnAs.KWARGS_WITH_NONE: 'KWARGS_WITH_NONE'>"}, {"fullname": "pedantic.ReturnAs.KWARGS_WITHOUT_NONE", "modulename": "pedantic", "qualname": "ReturnAs.KWARGS_WITHOUT_NONE", "kind": "variable", "doc": "

    \n", "default_value": "<ReturnAs.KWARGS_WITHOUT_NONE: 'KWARGS_WITHOUT_NONE'>"}, {"fullname": "pedantic.TooManyArguments", "modulename": "pedantic", "qualname": "TooManyArguments", "kind": "class", "doc": "

    Is raised if the function got more arguments than expected.

    \n", "bases": "pedantic.decorators.validate.exceptions.ValidateException"}, {"fullname": "pedantic.ValidateException", "modulename": "pedantic", "qualname": "ValidateException", "kind": "class", "doc": "

    The base class for all exception thrown by the validate decorator.

    \n", "bases": "builtins.Exception"}, {"fullname": "pedantic.ValidateException.__init__", "modulename": "pedantic", "qualname": "ValidateException.__init__", "kind": "function", "doc": "

    \n", "signature": "(msg: str)"}, {"fullname": "pedantic.ValidateException.message", "modulename": "pedantic", "qualname": "ValidateException.message", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Validator", "modulename": "pedantic", "qualname": "Validator", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "abc.ABC"}, {"fullname": "pedantic.Validator.validate", "modulename": "pedantic", "qualname": "Validator.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Any) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.Validator.validate_param", "modulename": "pedantic", "qualname": "Validator.validate_param", "kind": "function", "doc": "

    Validates and converts the value, just like [validate()].\nThe difference is that a parameter_name is included in the exception, if an exception is raised.

    \n", "signature": "(self, value: Any, parameter_name: str) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.Validator.raise_exception", "modulename": "pedantic", "qualname": "Validator.raise_exception", "kind": "function", "doc": "

    \n", "signature": "(self, value: Any, msg: str) -> NoReturn:", "funcdef": "def"}, {"fullname": "pedantic.Validator.name", "modulename": "pedantic", "qualname": "Validator.name", "kind": "variable", "doc": "

    \n", "annotation": ": str"}, {"fullname": "pedantic.ValidatorException", "modulename": "pedantic", "qualname": "ValidatorException", "kind": "class", "doc": "

    An exception that is raised inside the validate() function of a Validator.

    \n", "bases": "pedantic.decorators.validate.exceptions.ValidateException"}, {"fullname": "pedantic.ValidatorException.__init__", "modulename": "pedantic", "qualname": "ValidatorException.__init__", "kind": "function", "doc": "

    \n", "signature": "(msg: str, validator_name: str, value: Any, parameter_name: str = '')"}, {"fullname": "pedantic.ValidatorException.validator_name", "modulename": "pedantic", "qualname": "ValidatorException.validator_name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ValidatorException.value", "modulename": "pedantic", "qualname": "ValidatorException.value", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ValidatorException.parameter_name", "modulename": "pedantic", "qualname": "ValidatorException.parameter_name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.WithDecoratedMethods", "modulename": "pedantic", "qualname": "WithDecoratedMethods", "kind": "class", "doc": "

    A mixin that is used to figure out which method is decorated with custom parameterized decorators.

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    class Decorators(DecoratorType):\n ... FOO = '_foo'\n ... BAR = '_bar'\n foo = create_decorator(decorator_type=Decorators.FOO)\n bar = create_decorator(decorator_type=Decorators.BAR)\n class MyClass(WithDecoratedMethods[Decorators]):\n ... @foo(42)\n ... def m1(self) -> None:\n ... print('bar')\n ...\n ... @foo(value=43)\n ... def m2(self) -> None:\n ... print('bar')\n ...\n ... @bar(value=44)\n ... def m3(self) -> None:\n ... print('bar')\n instance = MyClass()\n instance.get_decorated_functions() # doctest: +SKIP\n {\n : {\n >: 42,\n >: 43,\n },\n : {\n >: 44,\n }\n }

    \n
    \n
    \n
    \n", "bases": "abc.ABC, pedantic.mixins.generic_mixin.GenericMixin, typing.Generic[~DecoratorTypeVar]"}, {"fullname": "pedantic.WithDecoratedMethods.get_decorated_functions", "modulename": "pedantic", "qualname": "WithDecoratedMethods.get_decorated_functions", "kind": "function", "doc": "

    Returns a mapping of all functions that are decorated by the given decorator type.

    \n", "signature": "(self) -> dict[~DecoratorTypeVar, dict[~C, ~T]]:", "funcdef": "def"}, {"fullname": "pedantic.assert_value_matches_type", "modulename": "pedantic", "qualname": "assert_value_matches_type", "kind": "function", "doc": "

    Checks that the given value matches the given type.

    \n", "signature": "(\tvalue: Any,\ttype_: Any,\terr: str,\ttype_vars: Dict[TypeVar, Any],\tkey: str | None = None,\tmsg: str | None = None,\tcontext: Dict[str, Any] | None = None) -> None:", "funcdef": "def"}, {"fullname": "pedantic.calculate_in_subprocess", "modulename": "pedantic", "qualname": "calculate_in_subprocess", "kind": "function", "doc": "

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

    \n\n

    Arguments:\n func: The function that will be called in a subprocess.\n args: Positional arguments that will be passed to the function.\n kwargs: Keyword arguments that will be passed to the function.

    \n\n

    Returns:\n The calculated result of the function \"func\".

    \n\n

    Raises:\n Any Exception that is raised inside [func].

    \n\n

    Further reading: https://medium.com/devopss-hole/python-multiprocessing-pickle-issue-e2d35ccf96a9

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    import time\n import asyncio\n def f(value: int) -> int:\n ... time.sleep(0.1) # a long taking synchronous blocking calculation\n ... return 2 * value\n asyncio.run(calculate_in_subprocess(func=f, value=42))\n 84

    \n
    \n
    \n
    \n", "signature": "(\tfunc: Callable[~P, ~T | Awaitable[~T]],\t*args: P.args,\t**kwargs: P.kwargs) -> ~T:", "funcdef": "async def"}, {"fullname": "pedantic.create_decorator", "modulename": "pedantic", "qualname": "create_decorator", "kind": "function", "doc": "

    Creates a new decorator that is parametrized with one argument of an arbitrary type.

    \n\n

    You can also pass an arbitrary [transformation] to add custom behavior to the decorator.

    \n", "signature": "(\tdecorator_type: pedantic.mixins.with_decorated_methods.DecoratorType,\ttransformation: Callable[[~C, pedantic.mixins.with_decorated_methods.DecoratorType, ~T], ~C] | None = None) -> Callable[[~T], Callable[[~C], ~C]]:", "funcdef": "def"}, {"fullname": "pedantic.deprecated", "modulename": "pedantic", "qualname": "deprecated", "kind": "function", "doc": "

    Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.\nYou can specify an optional reason or message to display with the warning.

    \n\n

    If you use Python 3.13 or newer, consider using warnings.deprecated instead from the standard library.

    \n\n

    Example:

    \n\n
    \n
    >>> @deprecated\n... def my_function(a, b, c):\n...     pass\n>>> my_function(5, 4, 3)  # doctest: +SKIP\n>>> @deprecated(message='Will be removed soon. Please use my_function_new_instead.')\n... def my_function(a, b, c):\n...     pass\n>>> my_function(5, 4, 3)  # doctest: +SKIP\n
    \n
    \n", "signature": "(func: Callable[~P, ~R] | type | None = None, *, message: str = '') -> Any:", "funcdef": "def"}, {"fullname": "pedantic.frozen_dataclass", "modulename": "pedantic", "qualname": "frozen_dataclass", "kind": "function", "doc": "

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

    \n\n

    If [type_safe] is True, a type check is performed for each field after the __post_init__ method was called,\nwhich itself is directly called after the __init__ constructor.\nNote that this might have a negative impact on performance.\nIt's recommended to use this for debugging and testing only.

    \n\n

    In a nutshell, the following methods will be added to the decorated class automatically:

    \n\n
      \n
    • __init__() gives you a simple constructor like \"Foo(a=6, b='hi', c=True)\"
    • \n
    • __eq__() lets you compare objects easily with \"a == b\"
    • \n
    • __hash__() is also needed for instance comparison
    • \n
    • __repr__() gives you a nice output when you call \"print(foo)\"
    • \n
    • copy_with() allows you to quickly create new similar frozen instances. Use this instead of setters.
    • \n
    • deep_copy_with() allows you to create deep copies and modify them.
    • \n
    • validate_types() allows you to validate the types of the dataclass.\nThis is called automatically when [type_safe] is True.
    • \n
    \n\n

    If the [order] parameter is True (default is False), the following comparison methods\nwill be added additionally:

    \n\n
      \n
    • __lt__() lets you compare instance like \"a < b\"
    • \n
    • __le__() lets you compare instance like \"a <= b\"
    • \n
    • __gt__() lets you compare instance like \"a > b\"
    • \n
    • __ge__() lets you compare instance like \"a >= b\"
    • \n
    \n\n

    These compare the class as if it were a tuple of its fields, in order.\nBoth instances in the comparison must be of the identical type.

    \n\n

    Example:

    \n\n
    \n
    >>> @frozen_dataclass\n... class Foo:\n...     a: int\n...     b: str\n...     c: bool\n>>> foo = Foo(a=6, b='hi', c=True)\n>>> print(foo)\nFoo(a=6, b='hi', c=True)\n>>> print(foo.copy_with())\nFoo(a=6, b='hi', c=True)\n>>> print(foo.copy_with(a=42))\nFoo(a=42, b='hi', c=True)\n>>> print(foo.copy_with(b='Hello'))\nFoo(a=6, b='Hello', c=True)\n>>> print(foo.copy_with(c=False))\nFoo(a=6, b='hi', c=False)\n>>> print(foo.copy_with(a=676676, b='new', c=False))\nFoo(a=676676, b='new', c=False)\n
    \n
    \n\n

    If you want to get rid of those annoying \"Unresolved attribute reference 'copy_with' for class 'Foo'\" warnings\nyou can extend your models from FrozenDataclass:\nExample:

    \n\n
    \n
    >>> @frozen_dataclass\n... class Bar(FrozenDataclass):\n...     a: int\n...     b: str\n...     c: bool\n>>> bar = Bar(a=6, b='hi', c=True)\n>>> print(bar)\nBar(a=6, b='hi', c=True)\n>>> print(bar.copy_with())\nBar(a=6, b='hi', c=True)\n
    \n
    \n", "signature": "(\tcls: type[~T] | None = None,\ttype_safe: bool = False,\torder: bool = False,\tkw_only: bool = True,\tslots: bool = False) -> type[pedantic.decorators.frozen_dataclass.FrozenDataclass] | type[~T] | Callable[[type[~T]], type[~T]]:", "funcdef": "def"}, {"fullname": "pedantic.frozen_type_safe_dataclass", "modulename": "pedantic", "qualname": "frozen_type_safe_dataclass", "kind": "function", "doc": "

    Shortcut for @frozen_dataclass(type_safe=True)

    \n", "signature": "(cls: type[~T]) -> type[~T]:", "funcdef": "def"}, {"fullname": "pedantic.in_subprocess", "modulename": "pedantic", "qualname": "in_subprocess", "kind": "function", "doc": "

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

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    import time\n import asyncio\n @in_subprocess\n ... def f(value: int) -> int:\n ... time.sleep(0.1) # a long taking synchronous blocking calculation\n ... return 2 * value\n asyncio.run(f(value=42))\n 84

    \n
    \n
    \n
    \n", "signature": "(func: Callable[~P, ~T | Awaitable[~T]]) -> Callable[~P, Awaitable[~T]]:", "funcdef": "def"}, {"fullname": "pedantic.overrides", "modulename": "pedantic", "qualname": "overrides", "kind": "function", "doc": "

    Use this to mark methods which overrides methods of a parent class.

    \n\n

    Raises:\n PedanticOverrideException: if the decorated method is not a method in any parent class

    \n\n

    Example:

    \n\n
    \n
    >>> class Parent:\n...     def my_instance_method(self): pass\n>>> class Child(Parent):\n...     @overrides(Parent)\n...     def my_instance_method(self): pass\n
    \n
    \n", "signature": "(base_class: type) -> ~F:", "funcdef": "def"}, {"fullname": "pedantic.pedantic", "modulename": "pedantic", "qualname": "pedantic", "kind": "function", "doc": "

    A PedanticException is raised if one of the following happened:

    \n\n
      \n
    • The decorated function is called with positional arguments.
    • \n
    • The function has no type annotation for their return type or one or more parameters do not have type\nannotations.
    • \n
    • A type annotation is incorrect.
    • \n
    • A type annotation misses type arguments, e.g. typing.List instead of typing.List[int].
    • \n
    • The documented arguments do not match the argument list or their type annotations.
    • \n
    \n\n

    You can use this as a function or a class decorator.

    \n\n

    Example:

    \n\n
    \n
    >>> @pedantic\n... def my_function(a: int, b: float, c: str) -> bool:\n...     return float(a) == b and str(b) == c\n>>> my_function(a=42.0, b=14.0, c='hi')\nTraceback (most recent call last):\n...\npedantic.exceptions.PedanticTypeCheckException: In function my_function:\nType hint is incorrect: Argument a=42.0 of type <class 'float'> does not match expected type <class 'int'>.\n>>> my_function(a=42, b=None, c='hi')\nTraceback (most recent call last):\n...\npedantic.exceptions.PedanticTypeCheckException: In function my_function:\nType hint is incorrect: Argument b=None of type <class 'NoneType'> does not match expected type <class 'float'>.\n>>> my_function(a=42, b=42, c='hi')\nTraceback (most recent call last):\n...\npedantic.exceptions.PedanticTypeCheckException: In function my_function:\nType hint is incorrect: Argument b=42 of type <class 'int'> does not match expected type <class 'float'>.\n>>> my_function(5, 4.0, 'hi')\nTraceback (most recent call last):\n...\npedantic.exceptions.PedanticCallWithArgsException: In function my_function:\nUse kwargs when you call function my_function. Args: (5, 4.0, 'hi')\n
    \n
    \n", "signature": "(\tfunc: Callable[~P, ~R] | type | None = None,\t*,\trequire_docstring: bool = False) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.resolve_forward_ref", "modulename": "pedantic", "qualname": "resolve_forward_ref", "kind": "function", "doc": "

    Resolve a type annotation that is a string.

    \n\n

    Raises:\n NameError: in case of [type_] cannot be resolved.

    \n", "signature": "(\ttype_: str,\tglobals_: dict[str, Any] | None = None,\tcontext: dict | None = None) -> type:", "funcdef": "def"}, {"fullname": "pedantic.retry", "modulename": "pedantic", "qualname": "retry", "kind": "function", "doc": "

    Retries the decorated function/method attempts times if the exceptions listed\nin [exceptions] are thrown.

    \n\n

    Args:\n attempts: The number of times to repeat the wrapped function/method\n exceptions: Lists of exceptions that trigger a retry attempt.\n sleep_time: The time to wait between the retry attempts.\n logger: The logger used for logging.

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    @retry(attempts=3, exceptions=(ValueError, TypeError))\n ... def foo():\n ... raise ValueError('Some error')\n foo() # doctest: +SKIP

    \n
    \n
    \n
    \n", "signature": "(\t*,\tattempts: int,\texceptions: type[Exception] | tuple[type[Exception], ...] = <class 'Exception'>,\tsleep_time: datetime.timedelta = datetime.timedelta(0),\tlogger: logging.Logger | None = None) -> Callable[[~C], ~C]:", "funcdef": "def"}, {"fullname": "pedantic.run_doctest_of_single_function", "modulename": "pedantic", "qualname": "run_doctest_of_single_function", "kind": "function", "doc": "

    Useful for debugging a function with doctests.

    \n", "signature": "(f: Callable) -> None:", "funcdef": "def"}, {"fullname": "pedantic.trace", "modulename": "pedantic", "qualname": "trace", "kind": "function", "doc": "

    Decorate a function or class to trace calls, arguments, and return values.

    \n\n

    Can be used as:

    \n\n
    @trace\ndef foo(...): ...\n\n@trace(log=print)\nasync def foo(...): ...\n\n@trace\nclass Foo: ...\n\n@trace(log=logger.info)\nclass Foo: ...\n
    \n\n

    Supports:\n - synchronous functions\n - asynchronous functions\n - classes\n - instance methods\n - static methods\n - class methods

    \n\n

    Args:\n obj:\n The decorated object when used as @trace.

    \n\n
    log:\n    Callable used to emit trace messages.\n
    \n\n

    Returns:\n The wrapped function, class, or decorator.

    \n", "signature": "(\tobj: Callable[~P, ~R] | type | None = None,\t*,\tlog: Callable[[str], None] = <built-in function print>) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.validate", "modulename": "pedantic", "qualname": "validate", "kind": "function", "doc": "

    Validates the values that are passed to the function by using the validators in the given parameters.\nThe decorated function could also be async or an instance method as well as a normal function.

    \n\n

    Args:\n parameters (multiple Parameter): The parameters that will be validated.\n return_as (ReturnAs): Pass the arguments as kwargs to the decorated function if ReturnAs.KWARGS.\n Positional arguments are used otherwise.\n strict (bool): If strict is true, you have to define a Parameter for each of the\n arguments the decorated function takes.\n ignore_input (bool): If True, all given arguments passed to this decorator are ignored.\n This can be useful if you use only ExternalParameters.

    \n\n

    Returns:\n Callable: The decorated function.

    \n", "signature": "(\t*parameters: pedantic.decorators.validate.parameters.abstract_parameter.Parameter,\treturn_as: pedantic.decorators.validate.validate.ReturnAs = <ReturnAs.ARGS: 'ARGS'>,\tstrict: bool = True,\tignore_input: bool = False) -> Callable:", "funcdef": "def"}, {"fullname": "pedantic.FlaskFormParameter", "modulename": "pedantic", "qualname": "FlaskFormParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.flask_parameters.FlaskParameter"}, {"fullname": "pedantic.FlaskFormParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskFormParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict:", "funcdef": "def"}, {"fullname": "pedantic.FlaskGetParameter", "modulename": "pedantic", "qualname": "FlaskGetParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.flask_parameters.FlaskParameter"}, {"fullname": "pedantic.FlaskGetParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskGetParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict:", "funcdef": "def"}, {"fullname": "pedantic.FlaskGetParameter.load_value", "modulename": "pedantic", "qualname": "FlaskGetParameter.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.FlaskHeaderParameter", "modulename": "pedantic", "qualname": "FlaskHeaderParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.flask_parameters.FlaskParameter"}, {"fullname": "pedantic.FlaskHeaderParameter.exception_type", "modulename": "pedantic", "qualname": "FlaskHeaderParameter.exception_type", "kind": "variable", "doc": "

    \n", "default_value": "<class 'pedantic.decorators.validate.exceptions.InvalidHeader'>"}, {"fullname": "pedantic.FlaskHeaderParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskHeaderParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict:", "funcdef": "def"}, {"fullname": "pedantic.FlaskJsonParameter", "modulename": "pedantic", "qualname": "FlaskJsonParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.flask_parameters.FlaskParameter"}, {"fullname": "pedantic.FlaskJsonParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskJsonParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict:", "funcdef": "def"}, {"fullname": "pedantic.FlaskParameter", "modulename": "pedantic", "qualname": "FlaskParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_external_parameter.ExternalParameter, abc.ABC"}, {"fullname": "pedantic.FlaskParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict[str, typing.Any]:", "funcdef": "def"}, {"fullname": "pedantic.FlaskParameter.has_value", "modulename": "pedantic", "qualname": "FlaskParameter.has_value", "kind": "function", "doc": "

    Returns True if the value can be fetched.

    \n", "signature": "(self) -> bool:", "funcdef": "def"}, {"fullname": "pedantic.FlaskParameter.load_value", "modulename": "pedantic", "qualname": "FlaskParameter.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.FlaskPathParameter", "modulename": "pedantic", "qualname": "FlaskPathParameter", "kind": "class", "doc": "

    This is a special case because Flask passes path parameter as kwargs to validate().\nTherefore, this doesn't need to be an ExternalParameter.

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_parameter.Parameter"}, {"fullname": "pedantic.GenericFlaskDeserializer", "modulename": "pedantic", "qualname": "GenericFlaskDeserializer", "kind": "class", "doc": "

    A JSON deserializer for classes which implements the [Deserializable] interface.

    \n\n

    Further reading: https://github.com/LostInDarkMath/pedantic-python-decorators/issues/55

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_external_parameter.ExternalParameter"}, {"fullname": "pedantic.GenericFlaskDeserializer.__init__", "modulename": "pedantic", "qualname": "GenericFlaskDeserializer.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tcls: type[pedantic.decorators.validate.parameters.deserializable.Deserializable],\tcatch_exception: bool = True,\t**kwargs: Any)"}, {"fullname": "pedantic.GenericFlaskDeserializer.has_value", "modulename": "pedantic", "qualname": "GenericFlaskDeserializer.has_value", "kind": "function", "doc": "

    Returns True if the value can be fetched.

    \n", "signature": "(self) -> bool:", "funcdef": "def"}, {"fullname": "pedantic.GenericFlaskDeserializer.load_value", "modulename": "pedantic", "qualname": "GenericFlaskDeserializer.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}]; + /** pdoc search index */const docs = [{"fullname": "pedantic", "modulename": "pedantic", "kind": "module", "doc": "

    \n"}, {"fullname": "pedantic.ConversionError", "modulename": "pedantic", "qualname": "ConversionError", "kind": "class", "doc": "

    Is raised if a type cast failed.

    \n", "bases": "pedantic.decorators.validate.exceptions.ValidateException"}, {"fullname": "pedantic.DateTimeUnixTimestamp", "modulename": "pedantic", "qualname": "DateTimeUnixTimestamp", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.DateTimeUnixTimestamp.validate", "modulename": "pedantic", "qualname": "DateTimeUnixTimestamp.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: float | str) -> datetime.datetime:", "funcdef": "def"}, {"fullname": "pedantic.DatetimeIsoFormat", "modulename": "pedantic", "qualname": "DatetimeIsoFormat", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.DatetimeIsoFormat.validate", "modulename": "pedantic", "qualname": "DatetimeIsoFormat.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: str) -> datetime.datetime:", "funcdef": "def"}, {"fullname": "pedantic.DecoratorType", "modulename": "pedantic", "qualname": "DecoratorType", "kind": "class", "doc": "

    The interface that defines all possible decorators types.

    \n\n

    The values of this enum are used as property names and the properties are added to the decorated functions.\nSo I would recommend naming them with a leading underscore to keep them private and also write it lowercase.

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    class Decorators(DecoratorType):\n ... FOO = '_foo'

    \n
    \n
    \n
    \n", "bases": "enum.StrEnum"}, {"fullname": "pedantic.Deserializable", "modulename": "pedantic", "qualname": "Deserializable", "kind": "class", "doc": "

    A tiny interface which has a static from_json() method which acts like a named constructor.

    \n", "bases": "abc.ABC"}, {"fullname": "pedantic.Deserializable.from_json", "modulename": "pedantic", "qualname": "Deserializable.from_json", "kind": "function", "doc": "

    A named constructor which creates an object from JSON.

    \n", "signature": "(\tdata: dict[str, typing.Any]) -> pedantic.decorators.validate.parameters.deserializable.Deserializable:", "funcdef": "def"}, {"fullname": "pedantic.Email", "modulename": "pedantic", "qualname": "Email", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.Email.__init__", "modulename": "pedantic", "qualname": "Email.__init__", "kind": "function", "doc": "

    \n", "signature": "(\temail_pattern: str = '[^@\\\\s]+@[^@\\\\s]+\\\\.[a-zA-Z0-9]+$',\tpost_processor: Callable[[str], str] = <function Email.<lambda>>)"}, {"fullname": "pedantic.Email.validate", "modulename": "pedantic", "qualname": "Email.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: str) -> str:", "funcdef": "def"}, {"fullname": "pedantic.EnvironmentVariableParameter", "modulename": "pedantic", "qualname": "EnvironmentVariableParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_external_parameter.ExternalParameter"}, {"fullname": "pedantic.EnvironmentVariableParameter.__init__", "modulename": "pedantic", "qualname": "EnvironmentVariableParameter.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tname: str,\tenv_var_name: str | None = None,\tvalue_type: type[str | bool | int | float] = <class 'str'>,\tvalidators: Iterable[pedantic.decorators.validate.validators.abstract_validator.Validator] | None = None,\trequired: bool = True,\tdefault: Any = <class 'pedantic.decorators.validate.parameters.abstract_parameter.NoValue'>)"}, {"fullname": "pedantic.EnvironmentVariableParameter.has_value", "modulename": "pedantic", "qualname": "EnvironmentVariableParameter.has_value", "kind": "function", "doc": "

    Returns True if the value can be fetched.

    \n", "signature": "(self) -> bool:", "funcdef": "def"}, {"fullname": "pedantic.EnvironmentVariableParameter.load_value", "modulename": "pedantic", "qualname": "EnvironmentVariableParameter.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.ExceptionDictKey", "modulename": "pedantic", "qualname": "ExceptionDictKey", "kind": "class", "doc": "

    \n"}, {"fullname": "pedantic.ExceptionDictKey.VALUE", "modulename": "pedantic", "qualname": "ExceptionDictKey.VALUE", "kind": "variable", "doc": "

    \n", "default_value": "'VALUE'"}, {"fullname": "pedantic.ExceptionDictKey.MESSAGE", "modulename": "pedantic", "qualname": "ExceptionDictKey.MESSAGE", "kind": "variable", "doc": "

    \n", "default_value": "'MESSAGE'"}, {"fullname": "pedantic.ExceptionDictKey.PARAMETER", "modulename": "pedantic", "qualname": "ExceptionDictKey.PARAMETER", "kind": "variable", "doc": "

    \n", "default_value": "'PARAMETER'"}, {"fullname": "pedantic.ExceptionDictKey.VALIDATOR", "modulename": "pedantic", "qualname": "ExceptionDictKey.VALIDATOR", "kind": "variable", "doc": "

    \n", "default_value": "'VALIDATOR'"}, {"fullname": "pedantic.ExternalParameter", "modulename": "pedantic", "qualname": "ExternalParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_parameter.Parameter, abc.ABC"}, {"fullname": "pedantic.ExternalParameter.has_value", "modulename": "pedantic", "qualname": "ExternalParameter.has_value", "kind": "function", "doc": "

    Returns True if the value can be fetched.

    \n", "signature": "(self) -> bool:", "funcdef": "def"}, {"fullname": "pedantic.ExternalParameter.load_value", "modulename": "pedantic", "qualname": "ExternalParameter.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.ForEach", "modulename": "pedantic", "qualname": "ForEach", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.ForEach.__init__", "modulename": "pedantic", "qualname": "ForEach.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tvalidators: pedantic.decorators.validate.validators.abstract_validator.Validator | Iterable[pedantic.decorators.validate.validators.abstract_validator.Validator])"}, {"fullname": "pedantic.ForEach.validate", "modulename": "pedantic", "qualname": "ForEach.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Iterable[typing.Any]) -> list[typing.Any]:", "funcdef": "def"}, {"fullname": "pedantic.GenericMixin", "modulename": "pedantic", "qualname": "GenericMixin", "kind": "class", "doc": "

    A mixin that provides easy access to given type variables.

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    from typing import Generic, TypeVar\n T = TypeVar('T')\n U = TypeVar('U')\n class Foo(Generic[T, U], GenericMixin):\n ... values: list[T]\n ... value: U\n f = Foostr, int\n f.type_vars\n {~T: , ~U: }

    \n
    \n
    \n
    \n"}, {"fullname": "pedantic.GenericMixin.type_vars", "modulename": "pedantic", "qualname": "GenericMixin.type_vars", "kind": "variable", "doc": "

    Returns the mapping of type variables to types.

    \n\n

    DO NOT call this inside __init__()!

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    from typing import Generic, TypeVar\n T = TypeVar('T')\n U = TypeVar('U')\n class Foo(Generic[T, U], GenericMixin):\n ... values: list[T]\n ... value: U\n f = Foostr, int\n f.type_vars\n {~T: , ~U: }

    \n
    \n
    \n
    \n", "annotation": ": dict[typing.TypeVar, type]"}, {"fullname": "pedantic.InvalidHeader", "modulename": "pedantic", "qualname": "InvalidHeader", "kind": "class", "doc": "

    Is raised if there is a validation error in a FlaskHeaderParameter.

    \n", "bases": "pedantic.decorators.validate.exceptions.ParameterException"}, {"fullname": "pedantic.IsEnum", "modulename": "pedantic", "qualname": "IsEnum", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.IsEnum.__init__", "modulename": "pedantic", "qualname": "IsEnum.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tenum: enum.EnumType,\tconvert: bool = True,\tto_upper_case: bool = True)"}, {"fullname": "pedantic.IsEnum.validate", "modulename": "pedantic", "qualname": "IsEnum.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Any) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.IsUuid", "modulename": "pedantic", "qualname": "IsUuid", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.IsUuid.__init__", "modulename": "pedantic", "qualname": "IsUuid.__init__", "kind": "function", "doc": "

    \n", "signature": "(convert: bool = False)"}, {"fullname": "pedantic.IsUuid.validate", "modulename": "pedantic", "qualname": "IsUuid.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: str) -> str:", "funcdef": "def"}, {"fullname": "pedantic.MatchPattern", "modulename": "pedantic", "qualname": "MatchPattern", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.MatchPattern.__init__", "modulename": "pedantic", "qualname": "MatchPattern.__init__", "kind": "function", "doc": "

    \n", "signature": "(pattern: str)"}, {"fullname": "pedantic.MatchPattern.validate", "modulename": "pedantic", "qualname": "MatchPattern.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: str) -> str:", "funcdef": "def"}, {"fullname": "pedantic.Max", "modulename": "pedantic", "qualname": "Max", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.Max.__init__", "modulename": "pedantic", "qualname": "Max.__init__", "kind": "function", "doc": "
    \n
    >>> Max(7, True).validate(7)\n7\n>>> Max(7, False).validate(7)  # doctest: +IGNORE_EXCEPTION_DETAIL\nTraceback (most recent call last):\nValidatorException: ...\n>>> Max(7, False).validate(6.999)\n6.999\n
    \n
    \n", "signature": "(value: float, include_boundary: bool = True)"}, {"fullname": "pedantic.Max.validate", "modulename": "pedantic", "qualname": "Max.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: float) -> int | float:", "funcdef": "def"}, {"fullname": "pedantic.MaxLength", "modulename": "pedantic", "qualname": "MaxLength", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.MaxLength.__init__", "modulename": "pedantic", "qualname": "MaxLength.__init__", "kind": "function", "doc": "

    \n", "signature": "(length: int)"}, {"fullname": "pedantic.MaxLength.validate", "modulename": "pedantic", "qualname": "MaxLength.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Sized) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.Min", "modulename": "pedantic", "qualname": "Min", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.Min.__init__", "modulename": "pedantic", "qualname": "Min.__init__", "kind": "function", "doc": "
    \n
    >>> Min(7, True).validate(7)\n7\n>>> Min(7, False).validate(7)  # doctest: +IGNORE_EXCEPTION_DETAIL\nTraceback (most recent call last):\nValidatorException: ...\n>>> Min(7, False).validate(7.001)\n7.001\n
    \n
    \n", "signature": "(value: float, include_boundary: bool = True)"}, {"fullname": "pedantic.Min.validate", "modulename": "pedantic", "qualname": "Min.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: float) -> int | float:", "funcdef": "def"}, {"fullname": "pedantic.MinLength", "modulename": "pedantic", "qualname": "MinLength", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.MinLength.__init__", "modulename": "pedantic", "qualname": "MinLength.__init__", "kind": "function", "doc": "

    \n", "signature": "(length: int)"}, {"fullname": "pedantic.MinLength.validate", "modulename": "pedantic", "qualname": "MinLength.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Sized) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.NotEmpty", "modulename": "pedantic", "qualname": "NotEmpty", "kind": "class", "doc": "

    Validates that the given value is not empty.

    \n", "bases": "pedantic.decorators.validate.validators.abstract_validator.Validator"}, {"fullname": "pedantic.NotEmpty.__init__", "modulename": "pedantic", "qualname": "NotEmpty.__init__", "kind": "function", "doc": "

    If strip is True, the leading and trailing whitespace will be removed.

    \n", "signature": "(strip: bool = True)"}, {"fullname": "pedantic.NotEmpty.strip", "modulename": "pedantic", "qualname": "NotEmpty.strip", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.NotEmpty.validate", "modulename": "pedantic", "qualname": "NotEmpty.validate", "kind": "function", "doc": "

    Throws a ValidationError if the sequence is empty.\nIf the sequence is a string, it removes all leading and trailing whitespace.

    \n", "signature": "(self, value: Sequence) -> Sequence:", "funcdef": "def"}, {"fullname": "pedantic.Parameter", "modulename": "pedantic", "qualname": "Parameter", "kind": "class", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.__init__", "modulename": "pedantic", "qualname": "Parameter.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tname: str,\tvalue_type: type[bool | int | float | str | dict | list] | None = None,\tvalidators: Iterable[pedantic.decorators.validate.validators.abstract_validator.Validator] | None = None,\tdefault: Any = <class 'pedantic.decorators.validate.parameters.abstract_parameter.NoValue'>,\trequired: bool = True)"}, {"fullname": "pedantic.Parameter.exception_type", "modulename": "pedantic", "qualname": "Parameter.exception_type", "kind": "variable", "doc": "

    \n", "annotation": ": type[pedantic.decorators.validate.exceptions.ParameterException]", "default_value": "<class 'pedantic.decorators.validate.exceptions.ParameterException'>"}, {"fullname": "pedantic.Parameter.name", "modulename": "pedantic", "qualname": "Parameter.name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.validators", "modulename": "pedantic", "qualname": "Parameter.validators", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.default_value", "modulename": "pedantic", "qualname": "Parameter.default_value", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.value_type", "modulename": "pedantic", "qualname": "Parameter.value_type", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.is_required", "modulename": "pedantic", "qualname": "Parameter.is_required", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Parameter.validate", "modulename": "pedantic", "qualname": "Parameter.validate", "kind": "function", "doc": "

    Apply all validators to the given value and collect all ValidationErrors.

    \n", "signature": "(self, value: Any) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.Parameter.raise_exception", "modulename": "pedantic", "qualname": "Parameter.raise_exception", "kind": "function", "doc": "

    \n", "signature": "(\tself,\tmsg: str,\tvalue: Any = None,\tvalidator: pedantic.decorators.validate.validators.abstract_validator.Validator | None = None) -> NoReturn:", "funcdef": "def"}, {"fullname": "pedantic.ParameterException", "modulename": "pedantic", "qualname": "ParameterException", "kind": "class", "doc": "

    An exception that is raised inside a Parameter.

    \n", "bases": "pedantic.decorators.validate.exceptions.ValidateException"}, {"fullname": "pedantic.ParameterException.__init__", "modulename": "pedantic", "qualname": "ParameterException.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tmsg: str,\tparameter_name: str,\tvalue: Any | None = None,\tvalidator_name: str | None = None)"}, {"fullname": "pedantic.ParameterException.validator_name", "modulename": "pedantic", "qualname": "ParameterException.validator_name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ParameterException.parameter_name", "modulename": "pedantic", "qualname": "ParameterException.parameter_name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ParameterException.value", "modulename": "pedantic", "qualname": "ParameterException.value", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ParameterException.from_validator_exception", "modulename": "pedantic", "qualname": "ParameterException.from_validator_exception", "kind": "function", "doc": "

    Creates a parameter exception from a validator exception.

    \n", "signature": "(\tcls,\texception: pedantic.decorators.validate.exceptions.ValidatorException,\tparameter_name: str = '') -> pedantic.decorators.validate.exceptions.ParameterException:", "funcdef": "def"}, {"fullname": "pedantic.ParameterException.to_dict", "modulename": "pedantic", "qualname": "ParameterException.to_dict", "kind": "variable", "doc": "

    \n", "annotation": ": dict[str, str]"}, {"fullname": "pedantic.ReturnAs", "modulename": "pedantic", "qualname": "ReturnAs", "kind": "class", "doc": "

    \n", "bases": "enum.Enum"}, {"fullname": "pedantic.ReturnAs.ARGS", "modulename": "pedantic", "qualname": "ReturnAs.ARGS", "kind": "variable", "doc": "

    \n", "default_value": "<ReturnAs.ARGS: 'ARGS'>"}, {"fullname": "pedantic.ReturnAs.KWARGS_WITH_NONE", "modulename": "pedantic", "qualname": "ReturnAs.KWARGS_WITH_NONE", "kind": "variable", "doc": "

    \n", "default_value": "<ReturnAs.KWARGS_WITH_NONE: 'KWARGS_WITH_NONE'>"}, {"fullname": "pedantic.ReturnAs.KWARGS_WITHOUT_NONE", "modulename": "pedantic", "qualname": "ReturnAs.KWARGS_WITHOUT_NONE", "kind": "variable", "doc": "

    \n", "default_value": "<ReturnAs.KWARGS_WITHOUT_NONE: 'KWARGS_WITHOUT_NONE'>"}, {"fullname": "pedantic.TooManyArguments", "modulename": "pedantic", "qualname": "TooManyArguments", "kind": "class", "doc": "

    Is raised if the function got more arguments than expected.

    \n", "bases": "pedantic.decorators.validate.exceptions.ValidateException"}, {"fullname": "pedantic.ValidateException", "modulename": "pedantic", "qualname": "ValidateException", "kind": "class", "doc": "

    The base class for all exception thrown by the validate decorator.

    \n", "bases": "builtins.Exception"}, {"fullname": "pedantic.ValidateException.__init__", "modulename": "pedantic", "qualname": "ValidateException.__init__", "kind": "function", "doc": "

    \n", "signature": "(msg: str)"}, {"fullname": "pedantic.ValidateException.message", "modulename": "pedantic", "qualname": "ValidateException.message", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.Validator", "modulename": "pedantic", "qualname": "Validator", "kind": "class", "doc": "

    Base class for validator classes.

    \n", "bases": "abc.ABC"}, {"fullname": "pedantic.Validator.validate", "modulename": "pedantic", "qualname": "Validator.validate", "kind": "function", "doc": "

    Validates and convert the value.\nRaises an [ValidatorException] in case of an invalid value.\nTo raise this you can simply call self.raise_exception().

    \n", "signature": "(self, value: Any) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.Validator.validate_param", "modulename": "pedantic", "qualname": "Validator.validate_param", "kind": "function", "doc": "

    Validates and converts the value, just like [validate()].\nThe difference is that a parameter_name is included in the exception, if an exception is raised.

    \n", "signature": "(self, value: Any, parameter_name: str) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.Validator.raise_exception", "modulename": "pedantic", "qualname": "Validator.raise_exception", "kind": "function", "doc": "

    \n", "signature": "(self, value: Any, msg: str) -> NoReturn:", "funcdef": "def"}, {"fullname": "pedantic.Validator.name", "modulename": "pedantic", "qualname": "Validator.name", "kind": "variable", "doc": "

    \n", "annotation": ": str"}, {"fullname": "pedantic.ValidatorException", "modulename": "pedantic", "qualname": "ValidatorException", "kind": "class", "doc": "

    An exception that is raised inside the validate() function of a Validator.

    \n", "bases": "pedantic.decorators.validate.exceptions.ValidateException"}, {"fullname": "pedantic.ValidatorException.__init__", "modulename": "pedantic", "qualname": "ValidatorException.__init__", "kind": "function", "doc": "

    \n", "signature": "(msg: str, validator_name: str, value: Any, parameter_name: str = '')"}, {"fullname": "pedantic.ValidatorException.validator_name", "modulename": "pedantic", "qualname": "ValidatorException.validator_name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ValidatorException.value", "modulename": "pedantic", "qualname": "ValidatorException.value", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.ValidatorException.parameter_name", "modulename": "pedantic", "qualname": "ValidatorException.parameter_name", "kind": "variable", "doc": "

    \n"}, {"fullname": "pedantic.WithDecoratedMethods", "modulename": "pedantic", "qualname": "WithDecoratedMethods", "kind": "class", "doc": "

    A mixin that is used to figure out which method is decorated with custom parameterized decorators.

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    class Decorators(DecoratorType):\n ... FOO = '_foo'\n ... BAR = '_bar'\n foo = create_decorator(decorator_type=Decorators.FOO)\n bar = create_decorator(decorator_type=Decorators.BAR)\n class MyClass(WithDecoratedMethods[Decorators]):\n ... @foo(42)\n ... def m1(self) -> None:\n ... print('bar')\n ...\n ... @foo(value=43)\n ... def m2(self) -> None:\n ... print('bar')\n ...\n ... @bar(value=44)\n ... def m3(self) -> None:\n ... print('bar')\n instance = MyClass()\n instance.get_decorated_functions() # doctest: +SKIP\n {\n : {\n >: 42,\n >: 43,\n },\n : {\n >: 44,\n }\n }

    \n
    \n
    \n
    \n", "bases": "abc.ABC, pedantic.mixins.generic_mixin.GenericMixin, typing.Generic[~DecoratorTypeVar]"}, {"fullname": "pedantic.WithDecoratedMethods.get_decorated_functions", "modulename": "pedantic", "qualname": "WithDecoratedMethods.get_decorated_functions", "kind": "function", "doc": "

    Returns a mapping of all functions that are decorated by the given decorator type.

    \n", "signature": "(self) -> dict[~DecoratorTypeVar, dict[~C, ~T]]:", "funcdef": "def"}, {"fullname": "pedantic.assert_value_matches_type", "modulename": "pedantic", "qualname": "assert_value_matches_type", "kind": "function", "doc": "

    Checks that the given value matches the given type.

    \n", "signature": "(\tvalue: Any,\ttype_: Any,\terr: str,\ttype_vars: Dict[TypeVar, Any],\tkey: str | None = None,\tmsg: str | None = None,\tcontext: Dict[str, Any] | None = None) -> None:", "funcdef": "def"}, {"fullname": "pedantic.calculate_in_subprocess", "modulename": "pedantic", "qualname": "calculate_in_subprocess", "kind": "function", "doc": "

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

    \n\n

    Arguments:\n func: The function that will be called in a subprocess.\n args: Positional arguments that will be passed to the function.\n kwargs: Keyword arguments that will be passed to the function.

    \n\n

    Returns:\n The calculated result of the function \"func\".

    \n\n

    Raises:\n Any Exception that is raised inside [func].

    \n\n

    Further reading: https://medium.com/devopss-hole/python-multiprocessing-pickle-issue-e2d35ccf96a9

    \n\n

    Example:

    \n\n
    \n
    >>> import time\n>>> import asyncio\n>>> def f(value: int) -> int:\n...     time.sleep(0.1)  # a long taking synchronous blocking calculation\n...     return 2 * value\n>>> asyncio.run(calculate_in_subprocess(func=f, value=42))\n84\n
    \n
    \n", "signature": "(\tfunc: Callable[~P, ~T | Awaitable[~T]],\t*args: P.args,\t**kwargs: P.kwargs) -> ~T:", "funcdef": "async def"}, {"fullname": "pedantic.create_decorator", "modulename": "pedantic", "qualname": "create_decorator", "kind": "function", "doc": "

    Creates a new decorator that is parametrized with one argument of an arbitrary type.

    \n\n

    You can also pass an arbitrary [transformation] to add custom behavior to the decorator.

    \n", "signature": "(\tdecorator_type: pedantic.mixins.with_decorated_methods.DecoratorType,\ttransformation: Callable[[~C, pedantic.mixins.with_decorated_methods.DecoratorType, ~T], ~C] | None = None) -> Callable[[~T], Callable[[~C], ~C]]:", "funcdef": "def"}, {"fullname": "pedantic.decorate_class", "modulename": "pedantic", "qualname": "decorate_class", "kind": "function", "doc": "

    Applies a decorator with optional arguments to each method of a class.

    \n", "signature": "(\tcls: ~T,\tdecorate_callable: Callable[[Callable, ...], Callable],\t*args: Any,\tallowed_dunder_methods: list[str] | None = None) -> ~T:", "funcdef": "def"}, {"fullname": "pedantic.deprecated", "modulename": "pedantic", "qualname": "deprecated", "kind": "function", "doc": "

    Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.\nYou can specify an optional reason or message to display with the warning.

    \n\n

    If you use Python 3.13 or newer, consider using warnings.deprecated instead from the standard library.

    \n\n

    Example:

    \n\n
    \n
    >>> @deprecated\n... def my_function(a, b, c):\n...     pass\n>>> my_function(5, 4, 3)  # doctest: +SKIP\n>>> @deprecated(message='Will be removed soon. Please use my_function_new_instead.')\n... def my_function(a, b, c):\n...     pass\n>>> my_function(5, 4, 3)  # doctest: +SKIP\n
    \n
    \n", "signature": "(func: Callable[~P, ~R] | type | None = None, *, message: str = '') -> Any:", "funcdef": "def"}, {"fullname": "pedantic.frozen_dataclass", "modulename": "pedantic", "qualname": "frozen_dataclass", "kind": "function", "doc": "

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

    \n\n

    If [type_safe] is True, a type check is performed for each field after the __post_init__ method was called,\nwhich itself is directly called after the __init__ constructor.\nNote that this might have a negative impact on performance.\nIt's recommended to use this for debugging and testing only.

    \n\n

    In a nutshell, the following methods will be added to the decorated class automatically:

    \n\n
      \n
    • __init__() gives you a simple constructor like \"Foo(a=6, b='hi', c=True)\"
    • \n
    • __eq__() lets you compare objects easily with \"a == b\"
    • \n
    • __hash__() is also needed for instance comparison
    • \n
    • __repr__() gives you a nice output when you call \"print(foo)\"
    • \n
    • copy_with() allows you to quickly create new similar frozen instances. Use this instead of setters.
    • \n
    • deep_copy_with() allows you to create deep copies and modify them.
    • \n
    • validate_types() allows you to validate the types of the dataclass.\nThis is called automatically when [type_safe] is True.
    • \n
    \n\n

    If the [order] parameter is True (default is False), the following comparison methods\nwill be added additionally:

    \n\n
      \n
    • __lt__() lets you compare instance like \"a < b\"
    • \n
    • __le__() lets you compare instance like \"a <= b\"
    • \n
    • __gt__() lets you compare instance like \"a > b\"
    • \n
    • __ge__() lets you compare instance like \"a >= b\"
    • \n
    \n\n

    These compare the class as if it were a tuple of its fields, in order.\nBoth instances in the comparison must be of the identical type.

    \n\n

    Example:

    \n\n
    \n
    >>> @frozen_dataclass\n... class Foo:\n...     a: int\n...     b: str\n...     c: bool\n>>> foo = Foo(a=6, b='hi', c=True)\n>>> print(foo)\nFoo(a=6, b='hi', c=True)\n>>> print(foo.copy_with())\nFoo(a=6, b='hi', c=True)\n>>> print(foo.copy_with(a=42))\nFoo(a=42, b='hi', c=True)\n>>> print(foo.copy_with(b='Hello'))\nFoo(a=6, b='Hello', c=True)\n>>> print(foo.copy_with(c=False))\nFoo(a=6, b='hi', c=False)\n>>> print(foo.copy_with(a=676676, b='new', c=False))\nFoo(a=676676, b='new', c=False)\n
    \n
    \n\n

    If you want to get rid of those annoying \"Unresolved attribute reference 'copy_with' for class 'Foo'\" warnings\nyou can extend your models from FrozenDataclass:\nExample:

    \n\n
    \n
    >>> @frozen_dataclass\n... class Bar(FrozenDataclass):\n...     a: int\n...     b: str\n...     c: bool\n>>> bar = Bar(a=6, b='hi', c=True)\n>>> print(bar)\nBar(a=6, b='hi', c=True)\n>>> print(bar.copy_with())\nBar(a=6, b='hi', c=True)\n
    \n
    \n", "signature": "(\tcls: type[~T] | None = None,\ttype_safe: bool = False,\torder: bool = False,\tkw_only: bool = True,\tslots: bool = False) -> type[pedantic.decorators.frozen_dataclass.FrozenDataclass] | type[~T] | Callable[[type[~T]], type[~T]]:", "funcdef": "def"}, {"fullname": "pedantic.frozen_type_safe_dataclass", "modulename": "pedantic", "qualname": "frozen_type_safe_dataclass", "kind": "function", "doc": "

    Shortcut for @frozen_dataclass(type_safe=True)

    \n", "signature": "(cls: type[~T]) -> type[~T]:", "funcdef": "def"}, {"fullname": "pedantic.in_subprocess", "modulename": "pedantic", "qualname": "in_subprocess", "kind": "function", "doc": "

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

    \n\n

    Example:

    \n\n
    \n
    >>> import time\n>>> import asyncio\n>>> @in_subprocess\n... def f(value: int) -> int:\n...     time.sleep(0.1)  # a long taking synchronous blocking calculation\n...     return 2 * value\n>>> asyncio.run(f(value=42))\n84\n
    \n
    \n", "signature": "(func: Callable[~P, ~T | Awaitable[~T]]) -> Callable[~P, Awaitable[~T]]:", "funcdef": "def"}, {"fullname": "pedantic.overrides", "modulename": "pedantic", "qualname": "overrides", "kind": "function", "doc": "

    Use this to mark methods which overrides methods of a parent class.

    \n\n

    Raises:\n PedanticOverrideException: if the decorated method is not a method in any parent class

    \n\n

    Example:

    \n\n
    \n
    >>> class Parent:\n...     def my_instance_method(self): pass\n>>> class Child(Parent):\n...     @overrides(Parent)\n...     def my_instance_method(self): pass\n
    \n
    \n", "signature": "(base_class: type) -> ~F:", "funcdef": "def"}, {"fullname": "pedantic.pedantic", "modulename": "pedantic", "qualname": "pedantic", "kind": "function", "doc": "

    A PedanticException is raised if one of the following happened:

    \n\n
      \n
    • The decorated function is called with positional arguments.
    • \n
    • The function has no type annotation for their return type or one or more parameters do not have type\nannotations.
    • \n
    • A type annotation is incorrect.
    • \n
    • A type annotation misses type arguments, e.g. typing.List instead of typing.List[int].
    • \n
    • The documented arguments do not match the argument list or their type annotations.
    • \n
    \n\n

    You can use this as a function or a class decorator.

    \n\n

    Example:

    \n\n
    \n
    >>> @pedantic\n... def my_function(a: int, b: float, c: str) -> bool:\n...     return float(a) == b and str(b) == c\n>>> my_function(a=42.0, b=14.0, c='hi')\nTraceback (most recent call last):\n...\npedantic.exceptions.PedanticTypeCheckException: In function my_function:\nType hint is incorrect: Argument a=42.0 of type <class 'float'> does not match expected type <class 'int'>.\n>>> my_function(a=42, b=None, c='hi')\nTraceback (most recent call last):\n...\npedantic.exceptions.PedanticTypeCheckException: In function my_function:\nType hint is incorrect: Argument b=None of type <class 'NoneType'> does not match expected type <class 'float'>.\n>>> my_function(a=42, b=42, c='hi')\nTraceback (most recent call last):\n...\npedantic.exceptions.PedanticTypeCheckException: In function my_function:\nType hint is incorrect: Argument b=42 of type <class 'int'> does not match expected type <class 'float'>.\n>>> my_function(5, 4.0, 'hi')\nTraceback (most recent call last):\n...\npedantic.exceptions.PedanticCallWithArgsException: In function my_function:\nUse kwargs when you call function my_function. Args: (5, 4.0, 'hi')\n
    \n
    \n", "signature": "(\tfunc: Callable[~P, ~R] | type | None = None,\t*,\trequire_docstring: bool = False) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.resolve_forward_ref", "modulename": "pedantic", "qualname": "resolve_forward_ref", "kind": "function", "doc": "

    Resolve a type annotation that is a string.

    \n\n

    Raises:\n NameError: in case of [type_] cannot be resolved.

    \n", "signature": "(\ttype_: str,\tglobals_: dict[str, Any] | None = None,\tcontext: dict | None = None) -> type:", "funcdef": "def"}, {"fullname": "pedantic.retry", "modulename": "pedantic", "qualname": "retry", "kind": "function", "doc": "

    Retries the decorated function/method attempts times if the exceptions listed\nin [exceptions] are thrown.

    \n\n

    Args:\n attempts: The number of times to repeat the wrapped function/method\n exceptions: Lists of exceptions that trigger a retry attempt.\n sleep_time: The time to wait between the retry attempts.\n logger: The logger used for logging.

    \n\n

    Example:

    \n\n
    \n
    \n
    \n

    @retry(attempts=3, exceptions=(ValueError, TypeError))\n ... def foo():\n ... raise ValueError('Some error')\n foo() # doctest: +SKIP

    \n
    \n
    \n
    \n", "signature": "(\t*,\tattempts: int,\texceptions: type[Exception] | tuple[type[Exception], ...] = <class 'Exception'>,\tsleep_time: datetime.timedelta = datetime.timedelta(0),\tlogger: logging.Logger | None = None) -> Callable[[~C], ~C]:", "funcdef": "def"}, {"fullname": "pedantic.run_doctest_of_single_function", "modulename": "pedantic", "qualname": "run_doctest_of_single_function", "kind": "function", "doc": "

    Useful for debugging a function with doctests.

    \n", "signature": "(f: Callable) -> None:", "funcdef": "def"}, {"fullname": "pedantic.safe_async_contextmanager", "modulename": "pedantic", "qualname": "safe_async_contextmanager", "kind": "function", "doc": "

    @safe_async_contextmanager decorator.

    \n\n
     Typical usage:\n\n    @safe_async_contextmanager\n    async def some_async_generator(<arguments>):\n        <setup>\n        yield <value>\n        <cleanup>\n\nequivalent to this:\n\n    @asynccontextmanager\n    async def some_async_generator(<arguments>):\n        <setup>\n        try:\n            yield <value>\n        finally:\n            <cleanup>\n\nThis makes this:\n\n    async with some_async_generator(<arguments>) as <variable>:\n        <body>\n\nequivalent to this:\n\n    <setup>\n    try:\n        <variable> = <value>\n        <body>\n    finally:\n        <cleanup>\n
    \n", "signature": "(\tf: Callable[..., AsyncIterator[~T]]) -> Callable[..., contextlib.AbstractAsyncContextManager[~T]]:", "funcdef": "def"}, {"fullname": "pedantic.safe_contextmanager", "modulename": "pedantic", "qualname": "safe_contextmanager", "kind": "function", "doc": "

    @safe_contextmanager decorator.

    \n\n

    Typical usage:

    \n\n
    @safe_contextmanager\ndef some_generator(<arguments>):\n    <setup>\n    yield <value>\n    <cleanup>\n
    \n\n

    equivalent to this:

    \n\n
    @contextmanager\ndef some_generator(<arguments>):\n    <setup>\n    try:\n        yield <value>\n    finally:\n        <cleanup>\n
    \n\n

    This makes this:

    \n\n
    with some_generator(<arguments>) as <variable>:\n    <body>\n
    \n\n

    equivalent to this:

    \n\n
    <setup>\ntry:\n    <variable> = <value>\n    <body>\nfinally:\n    <cleanup>\n
    \n", "signature": "(\tf: Callable[..., Iterator[~T]]) -> Callable[..., contextlib.AbstractContextManager[~T]]:", "funcdef": "def"}, {"fullname": "pedantic.trace", "modulename": "pedantic", "qualname": "trace", "kind": "function", "doc": "

    Decorate a function or class to trace calls, arguments, and return values.

    \n\n

    Can be used as:

    \n\n
    @trace\ndef foo(...): ...\n\n@trace(log=print)\nasync def foo(...): ...\n\n@trace\nclass Foo: ...\n\n@trace(log=logger.info)\nclass Foo: ...\n
    \n\n

    Supports:\n - synchronous functions\n - asynchronous functions\n - classes\n - instance methods\n - static methods\n - class methods

    \n\n

    Args:\n obj:\n The decorated object when used as @trace.

    \n\n
    log:\n    Callable used to emit trace messages.\n
    \n\n

    Returns:\n The wrapped function, class, or decorator.

    \n", "signature": "(\tobj: Callable[~P, ~R] | type | None = None,\t*,\tlog: Callable[[str], None] = <built-in function print>) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.validate", "modulename": "pedantic", "qualname": "validate", "kind": "function", "doc": "

    Validates the values that are passed to the function by using the validators in the given parameters.\nThe decorated function could also be async or an instance method as well as a normal function.

    \n\n

    Args:\n parameters (multiple Parameter): The parameters that will be validated.\n return_as (ReturnAs): Pass the arguments as kwargs to the decorated function if ReturnAs.KWARGS.\n Positional arguments are used otherwise.\n strict (bool): If strict is true, you have to define a Parameter for each of the\n arguments the decorated function takes.\n ignore_input (bool): If True, all given arguments passed to this decorator are ignored.\n This can be useful if you use only ExternalParameters.

    \n\n

    Returns:\n Callable: The decorated function.

    \n", "signature": "(\t*parameters: pedantic.decorators.validate.parameters.abstract_parameter.Parameter,\treturn_as: pedantic.decorators.validate.validate.ReturnAs = <ReturnAs.ARGS: 'ARGS'>,\tstrict: bool = True,\tignore_input: bool = False) -> Callable:", "funcdef": "def"}, {"fullname": "pedantic.FlaskFormParameter", "modulename": "pedantic", "qualname": "FlaskFormParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.flask_parameters.FlaskParameter"}, {"fullname": "pedantic.FlaskFormParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskFormParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict:", "funcdef": "def"}, {"fullname": "pedantic.FlaskGetParameter", "modulename": "pedantic", "qualname": "FlaskGetParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.flask_parameters.FlaskParameter"}, {"fullname": "pedantic.FlaskGetParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskGetParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict:", "funcdef": "def"}, {"fullname": "pedantic.FlaskGetParameter.load_value", "modulename": "pedantic", "qualname": "FlaskGetParameter.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.FlaskHeaderParameter", "modulename": "pedantic", "qualname": "FlaskHeaderParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.flask_parameters.FlaskParameter"}, {"fullname": "pedantic.FlaskHeaderParameter.exception_type", "modulename": "pedantic", "qualname": "FlaskHeaderParameter.exception_type", "kind": "variable", "doc": "

    \n", "default_value": "<class 'pedantic.decorators.validate.exceptions.InvalidHeader'>"}, {"fullname": "pedantic.FlaskHeaderParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskHeaderParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict:", "funcdef": "def"}, {"fullname": "pedantic.FlaskJsonParameter", "modulename": "pedantic", "qualname": "FlaskJsonParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.flask_parameters.FlaskParameter"}, {"fullname": "pedantic.FlaskJsonParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskJsonParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict:", "funcdef": "def"}, {"fullname": "pedantic.FlaskParameter", "modulename": "pedantic", "qualname": "FlaskParameter", "kind": "class", "doc": "

    The interface for all external parameters.

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_external_parameter.ExternalParameter, abc.ABC"}, {"fullname": "pedantic.FlaskParameter.get_dict", "modulename": "pedantic", "qualname": "FlaskParameter.get_dict", "kind": "function", "doc": "

    Returns the actual values as a dictionary.

    \n", "signature": "(self) -> dict[str, typing.Any]:", "funcdef": "def"}, {"fullname": "pedantic.FlaskParameter.has_value", "modulename": "pedantic", "qualname": "FlaskParameter.has_value", "kind": "function", "doc": "

    Returns True if the value can be fetched.

    \n", "signature": "(self) -> bool:", "funcdef": "def"}, {"fullname": "pedantic.FlaskParameter.load_value", "modulename": "pedantic", "qualname": "FlaskParameter.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}, {"fullname": "pedantic.FlaskPathParameter", "modulename": "pedantic", "qualname": "FlaskPathParameter", "kind": "class", "doc": "

    This is a special case because Flask passes path parameter as kwargs to validate().\nTherefore, this doesn't need to be an ExternalParameter.

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_parameter.Parameter"}, {"fullname": "pedantic.GenericFlaskDeserializer", "modulename": "pedantic", "qualname": "GenericFlaskDeserializer", "kind": "class", "doc": "

    A JSON deserializer for classes which implements the [Deserializable] interface.

    \n\n

    Further reading: https://github.com/LostInDarkMath/pedantic-python-decorators/issues/55

    \n", "bases": "pedantic.decorators.validate.parameters.abstract_external_parameter.ExternalParameter"}, {"fullname": "pedantic.GenericFlaskDeserializer.__init__", "modulename": "pedantic", "qualname": "GenericFlaskDeserializer.__init__", "kind": "function", "doc": "

    \n", "signature": "(\tcls: type[pedantic.decorators.validate.parameters.deserializable.Deserializable],\tcatch_exception: bool = True,\t**kwargs: Any)"}, {"fullname": "pedantic.GenericFlaskDeserializer.has_value", "modulename": "pedantic", "qualname": "GenericFlaskDeserializer.has_value", "kind": "function", "doc": "

    Returns True if the value can be fetched.

    \n", "signature": "(self) -> bool:", "funcdef": "def"}, {"fullname": "pedantic.GenericFlaskDeserializer.load_value", "modulename": "pedantic", "qualname": "GenericFlaskDeserializer.load_value", "kind": "function", "doc": "

    Loads a value and returns it.

    \n", "signature": "(self) -> Any:", "funcdef": "def"}]; // mirrored in build-search-index.js (part 1) // Also split on html tags. this is a cheap heuristic, but good enough. diff --git a/pedantic/__init__.py b/pedantic/__init__.py index 45bf3d34..ce5e8e1f 100644 --- a/pedantic/__init__.py +++ b/pedantic/__init__.py @@ -1,5 +1,6 @@ from pedantic.decorators import ( calculate_in_subprocess, + decorate_class, deprecated, frozen_dataclass, frozen_type_safe_dataclass, @@ -7,6 +8,8 @@ overrides, pedantic, retry, + safe_async_contextmanager, + safe_contextmanager, trace, ) from pedantic.decorators.validate.exceptions import ( @@ -88,6 +91,7 @@ 'assert_value_matches_type', 'calculate_in_subprocess', 'create_decorator', + 'decorate_class', 'deprecated', 'frozen_dataclass', 'frozen_type_safe_dataclass', @@ -97,6 +101,8 @@ 'resolve_forward_ref', 'retry', 'run_doctest_of_single_function', + 'safe_async_contextmanager', + 'safe_contextmanager', 'trace', 'validate', ] diff --git a/pedantic/decorators/__init__.py b/pedantic/decorators/__init__.py index 89ec943c..c5e9c158 100644 --- a/pedantic/decorators/__init__.py +++ b/pedantic/decorators/__init__.py @@ -1,5 +1,6 @@ from .deprecated import deprecated from .frozen_dataclass import frozen_dataclass, frozen_type_safe_dataclass +from .helpers import decorate_class from .in_subprocess import calculate_in_subprocess, in_subprocess from .overrides import overrides from .pedantic_decorator import pedantic @@ -9,6 +10,7 @@ __all__ = [ 'calculate_in_subprocess', + 'decorate_class', 'deprecated', 'deprecated', 'frozen_dataclass', diff --git a/pedantic/decorators/in_subprocess.py b/pedantic/decorators/in_subprocess.py index 074c393b..e5b343f9 100644 --- a/pedantic/decorators/in_subprocess.py +++ b/pedantic/decorators/in_subprocess.py @@ -33,14 +33,14 @@ def in_subprocess(func: Callable[P, T | Awaitable[T]]) -> Callable[P, Awaitable[ 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 + >>> 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) @@ -68,13 +68,13 @@ async def calculate_in_subprocess(func: Callable[P, T | Awaitable[T]], *args: P. 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 + >>> 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: diff --git a/poetry.lock b/poetry.lock index 479394ea..da335725 100644 --- a/poetry.lock +++ b/poetry.lock @@ -576,31 +576,31 @@ packaging = ">=23.2" [[package]] name = "ruff" -version = "0.15.16" +version = "0.15.17" description = "An extremely fast Python linter and code formatter, written in Rust." optional = true python-versions = ">=3.7" groups = ["main"] markers = "extra == \"dev\"" files = [ - {file = "ruff-0.15.16-py3-none-linux_armv6l.whl", hash = "sha256:6ac3c0b3969cc6cf6b158c4e2f8f682acb58e7d700d8a44b65ecdc72d66ab0b2"}, - {file = "ruff-0.15.16-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:197c207ed75ffba54a0dec23db4aa939a27a3053073e085e0042433cbdc58e4a"}, - {file = "ruff-0.15.16-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3a39fec45ab316cc23e7558f23fea4a70403ddb5648ea9a4a3854a16973d0071"}, - {file = "ruff-0.15.16-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba93191d79003116b95128c9d306e045200fdbd0bccb782b110f3cd1d4abc5cf"}, - {file = "ruff-0.15.16-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6ee4b90520630120ef032aa5cc10db483852dff950e78b1d717e2993a61ac8d"}, - {file = "ruff-0.15.16-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e4215bc938bc3c8215c1472c1aa437e310fee20cd427335fec9d7e609563628"}, - {file = "ruff-0.15.16-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c8d26be963b090f10e29abc8b3e74a2a321f6fa34e02424e30b5af89350ecbb"}, - {file = "ruff-0.15.16-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f198cf4123602a2280ed46c307bcbafe41758d6fee5b456b6b6058ca1514b3b4"}, - {file = "ruff-0.15.16-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb27515fa6240fb586ae82b901a59e67d24acff86f2190b433dc542fe0435aeb"}, - {file = "ruff-0.15.16-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a267c46ba1593fc26b8eecbea050b39d40c0b6bb7781ee11c90a02cd10032951"}, - {file = "ruff-0.15.16-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:528c68f39a91498a8d50e91ff5985df3d105782bab49cc378e73ac26bff083e8"}, - {file = "ruff-0.15.16-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7ed55c58950df60589a9a7a5d2f8fa5f54ebd287163be805adfe6ee95a9de123"}, - {file = "ruff-0.15.16-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d482feaf51512b50f9790ceb417a56a61dd1e9d9bf967662b9ed27c01b34f53a"}, - {file = "ruff-0.15.16-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1e15bc8c94513dae2a40cc9ef07c94fdd4ecc9e29dabebeebe170f952322c9e3"}, - {file = "ruff-0.15.16-py3-none-win32.whl", hash = "sha256:580378f7bd4aa25f72e74aa54948a9622f142b1e509521dd10902e886681cc1e"}, - {file = "ruff-0.15.16-py3-none-win_amd64.whl", hash = "sha256:408256017284eddf98fff77b29aa4fb30f586042d535b2d9befc6512f400aaec"}, - {file = "ruff-0.15.16-py3-none-win_arm64.whl", hash = "sha256:8cd61783afb39638a7133ef0d2dfb1e91277593962f81b5a8423eb0b888a6121"}, - {file = "ruff-0.15.16.tar.gz", hash = "sha256:d05e78d38c78caf020b03789e25106c93017db5a0cb6e2819885018c61343b78"}, + {file = "ruff-0.15.17-py3-none-linux_armv6l.whl", hash = "sha256:d9feddb927fc68bd295f5eebc587a7e42cfaf9b65f60ca4a2386febff575da8f"}, + {file = "ruff-0.15.17-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:25805a226d741c47d274a35ad5c10a7dde175fcddfa511d7cf3da0a21eb3eab7"}, + {file = "ruff-0.15.17-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f6ad73b14c2d18a3bf8ad7cb6974294d7f613a7898604826058e6ac64918ef4d"}, + {file = "ruff-0.15.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ba0c1e4f95bcb3869d0d30cbd5917071ef2e28665abfec970cdab0492c713ed"}, + {file = "ruff-0.15.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81647960f10bff57d2e51cadd0c3950fe598400c852863a038720ef5b8cca91e"}, + {file = "ruff-0.15.17-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e01a84ddbc8c16c23055ba3924476850f1bbc1917cebbb9376665a63e74260d"}, + {file = "ruff-0.15.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fe9f653152f8f294f9f7e03bf3a453d8b4a27f7a59c78c8666167f2b17b96c"}, + {file = "ruff-0.15.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c0fe88a7676e7a05b73174d4d4a59cb2ac21ff8263583f87a81a6018475a978"}, + {file = "ruff-0.15.17-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecfc3c7878fff94633ab0348524e093f9ce3243080416dd7d14f8ba400174719"}, + {file = "ruff-0.15.17-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:b8461180b22420b1bdc289909410930761629fddf2a5aaf60fae1ab26cedc4c4"}, + {file = "ruff-0.15.17-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6eccbe50a038b503e7140b441aa9c7fc8c1f36edf23ebef9f4165c2f28f568b7"}, + {file = "ruff-0.15.17-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:382fc0521025f5a8ad447d8bdd523545d0d7646adb718eb1c2dac5065ec27c0f"}, + {file = "ruff-0.15.17-py3-none-musllinux_1_2_i686.whl", hash = "sha256:456d41fcd1b2777ad63f09a6e7121d43f7b688bbc76a800c10f7f8fb1f912c3f"}, + {file = "ruff-0.15.17-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b1a04bcc94ae6194e9db05d16ad31f298a7194bfbcb08258bbe589cee1d587b8"}, + {file = "ruff-0.15.17-py3-none-win32.whl", hash = "sha256:596065960ab1ff593f744220c9fe6580eda00a95003cffa9f4048bb5b1bf0392"}, + {file = "ruff-0.15.17-py3-none-win_amd64.whl", hash = "sha256:6769e5fa1710b179b92e0bfa5a51735b35baea9013dadb06d5f44cbcf9547084"}, + {file = "ruff-0.15.17-py3-none-win_arm64.whl", hash = "sha256:f3be1fbb34bcdfd146240d8fb92a709d4c2c8191348580a3c044ec60fa0b4456"}, + {file = "ruff-0.15.17.tar.gz", hash = "sha256:2ec446937fd16c8c4de2674a209cc5af64d9c6f17d21fbf1151054fa0bcf5219"}, ] [[package]] @@ -699,4 +699,4 @@ dev = ["Flask", "coverage", "deptry", "docstring-parser", "multiprocess", "pytes [metadata] lock-version = "2.1" python-versions = ">=3.11,<4.0" -content-hash = "f59f3449fab535b66dc5156568cec03597225b31fb31cedfa375bf01bb0be86d" +content-hash = "99521ace0b332506da9b218cfc36d4ed6eca57b963b0eefe65dba5a91222e283"