Getting Started

Installation

You can install the latest release from PyPI as follows:

$ pip install --upgrade typing-validation

Usage

The core functionality of this library is provided by the validate function:

>>> from typing_validation import validate

The validate function is invoked with a value and a type as its arguments and it returns True when the given value is valid for the given type:

>>> validate(12, int)
True # no error raised => 12 is a valid int

If the value is invalid for the given type, the validate function raises a TypeError:

>>> validate(12, str)
TypeError: Runtime validation error raised by validate(val, t), details below.
For type <class 'str'>, invalid value: 12

For nested types (e.g. parametric collection/mapping types), the full chain of validation failures is shown by the type error:

>>> validate([0, 1, "hi"], list[int])
TypeError: Runtime validation error raised by validate(val, t), details below.
For type list[int], invalid value at idx: 2
  For type <class 'int'>, invalid value: 'hi'

For union types, detailed validation failures are shown for individual union member types, where available:

>>> from typing import *
>>> validate([[0, 1, 2], {"hi": 0}], list[Union[Collection[int], dict[str, str]]])
TypeError: Runtime validation error raised by validate(val, t), details below.
For type list[typing.Union[typing.Collection[int], dict[str, str]]], invalid value at idx: 1
  For union type typing.Union[typing.Collection[int], dict[str, str]], invalid value: {'hi': 0}
    For member type typing.Collection[int], invalid value at idx: 0
      For type <class 'int'>, invalid value: 'hi'
    For member type dict[str, str], invalid value at key: 'hi'
      For type <class 'str'>, invalid value: 0

For NumPy array types, the array dtype is validated against the NDArray dtype annotation (unions of dtypes and Any are allowed):

>>> from typing_validation import validate
>>> import numpy as np
>>> import numpy.typing as npt
>>> a = np.zeros(5, dtype=np.float64)
>>> validate(a, npt.NDArray[np.float64])
True
>>> validate(a, npt.NDArray[Any])
True
>>> validate(a, npt.NDArray[np.uint8])
TypeError: Runtime validation error raised by validate(val, t), details below.
For type numpy.ndarray[typing.Any, numpy.dtype[numpy.uint8]], invalid array dtype float64

The function is_valid is a variant of the validate function which returns False in case of validation failure, instead of raising TypeError:

>>> from typing_validation import is_valid
>>> is_valid([0, 1, "hi"], list[int])
False

The function latest_validation_failure can be used to access detailed information immediately after a failure:

>>> from typing_validation import latest_validation_failure
>>> is_valid([0, 1, "hi"], list[int])
False
>>> failure = latest_validation_failure()
>>> print(failure)
Runtime validation error raised by validate(val, t), details below.
For type list[int], invalid value at idx: 2
  For type <class 'int'>, invalid value: 'hi'

Detailed information about types supported by validate is provided by the can_validate function:

>>> from typing_validation import can_validate

The can_validate function is invoked with a type as its argument and it returns a TypeInspector object, containing detailed information about the structure of the type that was being validated, including the presence of types not supported by validate (wrapped into a UnsupportedType):

>>> from typing import *
>>> from typing_validation import can_validate
>>> can_validate(tuple[list[str], Union[int, float, Callable[[int], int]]])
The following type cannot be validated against:
tuple[
    list[
        str
    ],
    Union[
        int,
        float,
        UnsupportedType[
            typing.Callable[[int], int]
        ],
    ],
]

The validation_aliases can be used to define set simple type aliases that can be used by validate to resolve forward references. For example, the following snippet validates a value against a recursive type alias for JSON-like objects, using typing_validation.validation.validation_aliases to create a context where typing_validation.validation.validate internally evaluates the forward reference "JSON" to the type alias JSON:

>>> from typing import *
>>> from typing_validation import validate, validation_aliases
>>> JSON = Union[int, float, bool, None, str, list["JSON"], dict[str, "JSON"]]
>>> with validation_aliases(JSON=JSON):
>>>     validate([1, 2.2, {"a": ["Hello", None, {"b": True}]}], list["JSON"])

The result of can_validate can be used wherever a bool is expected, returning True upon (implicit or explicit) bool conversion if and only if the type can be validated:

>>> bool(can_validate(Callable[[int], int]))
False
>>> "can validate" if can_validate(Callable[[int], int]) else "cannot validate"
'cannot validate'

Note. Traceback information was hidden in the above examples, for clarity: Note. For Python 3.7 and 3.8, use Tuple and List instead of tuple and list for the above examples.

>>> import sys
>>> sys.tracebacklimit = 0

GitHub repo: https://github.com/hashberg-io/typing-validation