Skip to main content

Pedantic

Coverage Status PyPI version Conda Version Last Commit Stars Open Issues Open PRs

A collection of useful decorators in mixins for Python development.

GenericMixin

Do you need a way to figure out to which type a type variable is bound? With GenericMixin you can do exactly this:

from pedantic import GenericMixin

class Foo[T, U](GenericMixin):
    values: list[T]
    value: U

f = Foo[str, int]()
print(f.type_vars)  # {T: <class 'str'>, U: <class 'int'>}

@frozen_dataclass

With @frozen_dataclass you can create immutable data classes with provides a copy_with() instance method. So you can write

from pedantic import frozen_dataclass

@frozen_dataclass
class Foo:
    a: int
    b: str

foo = Foo(a=6, b='hi')
bar = foo.copy_with(a=42)

instead of

from dataclasses import dataclass, replace
@dataclass(frozen=True)
class Foo:
    a: int
    b: str

foo = Foo(a=6, b='hi')
bar = replace(foo, a=42)

You also can enforce run-time type checks for you dataclasses with @frozen_dataclass(type_safe=True).

@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.

import time
from pedantic import in_subprocess

@in_subprocess
def f() -> int:
    time.sleep(10)  # a long-taking synchronous operation, e.g., a calculation
    return 42

await f() == 42  # calculation is done in a separate process => event loop is not blocked

WithDecoratedMethods

You want to register instance methods of a class as callbacks with a decorator? Easy!

from pedantic import DecoratorType, create_decorator, WithDecoratedMethods

class Decorators(DecoratorType):
    ON_SUBJECT = 'on_subject'

on_subject = create_decorator(decorator_type=Decorators.ON_SUBJECT)

class MyClass(WithDecoratedMethods[Decorators]):
    message_broker_client = None
    
    @on_subject("msg_received")
    def on_new_message(self, msg) -> None:
        print(msg)

    def subscribe(self) -> None:
        to_subscribe = self.get_decorated_functions()[Decorators.ON_SUBJECT]
        
        for callback, subject in to_subscribe.items():
            self.message_broker_client.subscribe(subject=subject, on_new_message=callback)        

@pedantic

The @pedantic decorator enforces type annotations and check that passed arguments and returned values match those type annotations.

from pedantic import pedantic

@pedantic
class MyClass:
    def print(self, s: str) -> None: pass

m = MyClass()
m.calc(b=42)
m.print(s='Hi')
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).

@validate

This is an alternative to the flask-request-validator that allows you to make parsing arguments from requests and validate them easy.

from flask import Flask, Response, jsonify

from pedantic import (
    FlaskJsonParameter,
    NotEmpty,
    ParameterException,
    ReturnAs,
    TooManyArguments,
    validate,
)

app = Flask(__name__)

@app.route('/')
@validate(
    FlaskJsonParameter(name='key', validators=[NotEmpty()]),
)
def hello_world(key: str) -> Response:
    return jsonify(key)


@app.route('/required')
@validate(
    FlaskJsonParameter(name='required', required=True),
    FlaskJsonParameter(name='not_required', required=False),
    FlaskJsonParameter(name='not_required_with_default', required=False, default=42),
)
def required_params(required, not_required, not_required_with_default) -> Response:
    return jsonify({
        'required': required,
        'not_required': not_required,
        'not_required_with_default': not_required_with_default,
    })


@app.route('/types')
@validate(
    FlaskJsonParameter(name='bool_param', value_type=bool),
    FlaskJsonParameter(name='int_param', value_type=int),
    FlaskJsonParameter(name='float_param', value_type=float),
    FlaskJsonParameter(name='str_param', value_type=str),
    FlaskJsonParameter(name='list_param', value_type=list),
    FlaskJsonParameter(name='dict_param', value_type=dict),
)
def different_types(  # noqa: PLR0913
        bool_param,
        int_param,
        float_param,
        str_param,
        list_param,
        dict_param,
) -> Response:
    return jsonify({
        'bool_param': bool_param,
        'int_param': int_param,
        'float_param': float_param,
        'str_param': str_param,
        'list_param': list_param,
        'dict_param': dict_param,
    })


@app.route('/args')
@validate(
    FlaskJsonParameter(name='a', validators=[NotEmpty()]),
    FlaskJsonParameter(name='b', validators=[NotEmpty()]),
    return_as=ReturnAs.ARGS,
)
def names_do_not_need_to_match(my_key: str, another: str) -> Response:
    return jsonify({
        'my_key': my_key,
        'another': another,
    })


@app.errorhandler(ParameterException)
def handle_parameter_exception(exception: ParameterException) -> Response:
    response = jsonify(exception.to_dict)
    response.status_code = 422
    return response


@app.errorhandler(TooManyArguments)
def handle_too_many_arguments(exception: TooManyArguments) -> Response:
    response = jsonify(str(exception))
    response.status_code = 400
    return response

And it is not only for flask! The implementation is fully generic.

Content of the package

Decorators

Mixins

Helper Functions

Contributing

This project is based on poetry and taskfile. Tip: Run task validate before making commits.

Metadata

Release files for pedantic 3.0.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pedantic 3.0.5
File Size Uploaded
pedantic-3.0.5.tar.gz 77.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pedantic 3.0.5
File Interpreter ABI Platform
pedantic-3.0.5-py3-none-any.whl Python 3 none any Details

Total release size: 184.8 kB

Release files / pedantic-3.0.5.tar.gz

Download URL pedantic-3.0.5.tar.gz
Size 77.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c670bb5a15d3aff228a6bba37dd488efcf236d1392642a9671407345970d24d0
BLAKE2b-256 checksum
How to use checksums
53abdb801decd898fd71019021dcb6e20a483975786f57400a46f236f29f5e36
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / pedantic-3.0.5-py3-none-any.whl

Download URL pedantic-3.0.5-py3-none-any.whl
Size 107.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
06b7cb9f1afaddf8d88d231cfce764a83710493d6e86d4472b4739cdb8c383b2
BLAKE2b-256 checksum
How to use checksums
67d984f2b63436aeb974a4f114ba8e0fa38ebf23c39c8a285e9a730bfcb02243
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

3.0.5 This release

2 release files

3.0.4

2 release files

3.0.3

2 release files

3.0.2

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.4.0

2 release files

2.3.3

2 release files

2.3.2

2 release files

2.3.1

2 release files

2.3.0

2 release files

2.2.3

2 release files

2.2.2

2 release files

2.2.1

2 release files

2.2.0

2 release files

2.1.11

1 release file

2.1.10

1 release file

2.1.9

1 release file

2.1.8

1 release file

2.1.7

1 release file

2.1.6

1 release file

2.1.5

1 release file

2.1.4

2 release files

2.1.3

2 release files

2.1.2

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.16.4

2 release files

1.16.3

2 release files

1.16.0

2 release files

1.15.1

2 release files

1.15.0

2 release files

1.14.6

2 release files

1.14.4

2 release files

1.14.3

2 release files

1.14.2

2 release files

1.14.1

2 release files

1.13.3

2 release files

1.13.2

2 release files

1.13.1

2 release files

1.13.0

2 release files

1.12.8

2 release files

1.12.7

2 release files

1.12.6

2 release files

1.12.5

2 release files

1.12.4

2 release files

1.12.3

2 release files

1.12.2

2 release files

1.12.1

2 release files

1.12.0

2 release files

1.11.3

2 release files

1.11.2

2 release files

1.11.0

2 release files

1.10.0

2 release files

1.9.1

2 release files

1.9.0

2 release files

1.8.5

2 release files

1.8.4

2 release files

1.8.3

2 release files

1.8.2

2 release files

1.8.1

2 release files

1.8.0

2 release files

1.7.1

2 release files

1.7.0

2 release files

1.6.3

2 release files

1.6.2

2 release files

1.6.1

2 release files

1.6.0

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.9

2 release files

1.4.8

2 release files

1.4.7

2 release files

1.4.6

2 release files

1.4.5

2 release files

1.4.4

2 release files

1.4.3

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.7

2 release files

1.2.6

2 release files

1.2.5

2 release files

1.2.4

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page