typing-validation
A library to perform runtime validation of Python objects using type hints.
Install
Install the latest release from PyPI:
$ pip install --upgrade typing-validation
Usage
Validate a value against a type hint. validate returns True on success and raises on failure:
>>> from typing_validation import validate
>>> validate([1, 2, 3], list[int])
True
The True return exists so that validation can be gated behind an assertion, and compiled out entirely under -O:
assert validate(val, t)
When a value does not conform, the error says where:
>>> validate({"a": [1, "b"]}, dict[str, list[int]])
Traceback (most recent call last):
...
typing_validation.errors.ValidationError: For type dict[str, list[int]]: a component failed
For type list[int] value at key 'a': a component failed
For type <class 'int'> index 1: not an instance, got 'b'
The structured explanation is on the exception, for reading programmatically:
>>> try:
... validate([1, "b"], list[int])
... except ValidationError as e:
... print(e.failure.causes[0].location.at)
1
Validating the same type repeatedly
validate analyses the type on every call. When you validate many values against
one type, validator analyses it once and hands back a function:
>>> from typing_validation import validator
>>> check = validator(list[int])
>>> check([1, 2, 3])
True
Same contract, same verdict, 2.7× faster per call. It repays the cost of building it almost immediately — the benchmark suite reports exactly when, per type:
| Type | validate |
validator |
repays after |
|---|---|---|---|
list[int] (1000 items) |
61.3 µs | 22.6 µs | 0 values |
list[int] (20 items) |
1.50 µs | 0.54 µs | 3 values |
dict[str, int] (20 items) |
2.79 µs | 1.04 µs | 3 values |
tuple[int, str] |
436 ns | 216 ns | 22 values |
int |
51.9 ns | 46.8 ns | 303 values |
So: use validate for one-off checks, and validator when the type is fixed and
the values keep coming. Run python -m benchmark for the numbers on your machine.
One difference, and it is deliberate. validator analyses the whole type before
it sees any value, so it rejects an unsupported type immediately:
validator(list[Callable[[int], int]]) # UnsupportedTypeError, at once
validate([], list[Callable[[int], int]]) # True — no value reached the Callable
The rest of the surface
from typing_validation import is_valid, validated, validated_iter
is_valid([1, "a"], list[int]) # False — a boolean, at boolean prices
validated(payload, list[int]) # returns payload, for use in an expression
validated_iter(stream, Iterator[int]) # checks each item as it is yielded
is_valid deliberately builds no explanation: a caller who wants one calls validate and catches the exception.
validated_iter is not a convenience wrapper. Determining the items of a one-shot iterator consumes it, so Iterator[int] cannot check its items eagerly without destroying the value — checking them on the way past is the only honest way.
Asking about a type
Support is all-or-nothing: if any component of a type is unsupported, the whole type is. can_validate answers up front:
>>> from typing_validation import can_validate, inspect_type
>>> can_validate(list[int])
True
>>> can_validate(tuple[int, Callable[[int], int]]) # poisoned by the Callable
False
inspect_type returns the whole structure and names precisely what poisoned it, so "unsupported" is never opaque:
>>> node = inspect_type(tuple[int, Callable[[int], int]])
>>> [c.t for c in node.unsupported_components()]
[typing.Callable[[int], int]]
NumPy
NumPy array types are supported by an extension, which you enable by importing:
import typing_validation.numpy # required
from numpy.typing import NDArray
validate(np.array([1, 2], dtype=np.uint8), NDArray[np.uint8])
The import is required rather than automatic, so that the supported surface never depends on whether some unrelated dependency happened to import NumPy.
Extending
A parametrised class can say how its own type arguments are validated:
class Box[T]:
@classmethod
def __validate__(cls, val, args):
return is_valid(val.item, args[0])
For classes you do not own, use register_validator(cls, check).
API
The full API documentation is available at typing-validation.readthedocs.io.
Structure
typing_validation/— the package source.knowledge/— design documents: the architecture, and the catalogue of supported type forms.test/— the conformance suite, with the case corpus intest/cases.py.benchmark/— the benchmark suite; run it withpython -m benchmark.docs/— the Sphinx documentation pipeline.
License
LGPL-3.0-or-later © Hashberg Ltd
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file typing_validation-2.1.0.tar.gz.
File metadata
- Download URL: typing_validation-2.1.0.tar.gz
- Upload date:
- Size: 54.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be129511a3be2b1f584884a14b9d411c9efd0ff4abde5d4a4790505d8f774ee8
|
|
| MD5 |
342e24978f5f8cc5d508eb369af2e34a
|
|
| BLAKE2b-256 |
03e24ba9e1aaf885ee85eedf31f6603d502b52ce80ae608ead807940c1d0d7c6
|
File details
Details for the file typing_validation-2.1.0-py3-none-any.whl.
File metadata
- Download URL: typing_validation-2.1.0-py3-none-any.whl
- Upload date:
- Size: 62.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5647a204b90911a34f8f31665aa7a7143b011c3e6ee513809e3de0e0871f0a91
|
|
| MD5 |
b2d845ef7758b211d93a23b879b4a853
|
|
| BLAKE2b-256 |
38c845029d1811cef5f9f0c955c4eef710803cb8592748b130055f25984179a1
|