Pedantic
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
- @deprecated
- @frozen_dataclass
- @frozen_type_safe_dataclass
- @in_subprocess
- @overrides
- @pedantic
- @retry
- @safe_async_contextmanager
- @safe_contextmanager
- @trace
- @validate
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)
| File | Size | Uploaded | |
|---|---|---|---|
| pedantic-3.0.5.tar.gz | 77.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|