Beartype 0.4.0 released.
This stable release significantly improves beartype's compliance with Python Enhancement Proposals (PEPs), including full compliance with:
- PEP 483 -- The Theory of Type Hints.
- PEP 484 -- Type Hints.
- PEP 544 -- Protocols: Structural subtyping (static duck typing).
- PEP 560 -- Core support for typing module and generic types.
- PEP 563 -- Postponed Evaluation of Annotations.
- PEP 593 -- Flexible function and variable annotations.
With respect to PEPs 483 and 484, "full compliance" means "beartype deeply type-checks a lot and at least shallowly type-checks the remainder." With respect to the remaining PEPs, "full compliance" means "beartype deeply type-checks everything."
Specific changes include:
Compatibility Broken
- Call-time type hint exception classes renamed. For orthogonality with decoration-time type hint exception classes, all call-time type hint exception classes have been renamed from
beartype.roar.BeartypeCallCheck*Exception
tobeartype.roar.BeartypeCallHint*Exception
(e.g., frombeartype.roar.BeartypeCallCheckPepParamException
tobeartype.roar.BeartypeCallHintPepParamException
).
Features Added
- Deep
typing.Annotated
type-checking. Under Python ≥ 3.9, the@beartype
decorator now deeply type-checks parameters and return values annotated by PEP 593 (i.e., "Flexible function and variable annotations")-complianttyping.Annotated
type hints in guaranteed constant time. - Deep
typing.Generic
type-checking. The@beartype
decorator now type-checks both the shallow types and deep contents of parameters and return values annotated by PEP 484-compliant generics (i.e., type hints subclassing a combination of one or more of thetyping.Generic
superclass and/or othertyping
non-class pseudo-superclasses) in guaranteed constant time. Specifically, beartype iteratively walks up the superclass hierarchy of each generic and deeply type-checks that the current parameter or return value satisfies all constraints implied by that superclass. This includes:typing.IO
. This was no small feat, as this abstract base class (ABC) fails to leverage structural subtyping (e.g., via the PEP 544-complianttyping.Protocol
ABC) and is thus unusable at runtime... like mosttyping
objects, sadly. Our solution is to ignore the existing implementation of these classes, declare our own internaltyping.Protocol
-based variants of these classes, and implicitly substitute all instances of these classes with our own variants during our breadth-first traversal (BFS) over PEP-compliant type hints.typing.BinaryIO
.typing.TextIO
.
- Deep
typing.NewType
support. The@beartype
decorator now deeply type-checks parameters and return values annotated by PEP 484-compliant new types (i.e., closures generated by thetyping.NewType
closure factory) in guaranteed constant time. - Deep
typing.NoReturn
support. The@beartype
decorator now fully type-checks that callables annotated by thetyping.NoReturn
singleton return no values (i.e., either halt the active Python process or raise an exception) in guaranteed constant time. - Deep
typing.Protocol
type-checking. Under Python ≥ 3.8, the@beartype
decorator now type-checks both the shallow types and deep contents of parameters and return values annotated by PEP 544 (i.e., "Protocols: Structural subtyping (static duck typing)")-compliant protocols (i.e., type hints subclassing a combination of one or more of thetyping.Protocol
superclass and/or othertyping
non-class pseudo-superclasses) in guaranteed constant time, similarly to how beartype type-checks generics. This includes:typing.SupportsAbs
.typing.SupportsBytes
.typing.SupportsComplex
.typing.SupportsIndex
.typing.SupportsInt
.typing.SupportsFloat
.typing.SupportsRound
.
- Deep
typing.Tuple
type-checking. The@beartype
decorator now type-checks both the shallow types and deep contents of parameters and return values annotated by PEP 484-complianttyping.Tuple
type hints in guaranteed constant time. The three syntactic variants standardized by PEP 484 are all supported, including:typing.Tuple[()]
, type-checking empty tuples.typing.Tuple[{typename}, ...]
, type-checking tuples containing arbitrarily many items all satisfying the PEP-compliant child hint{typename}
(e.g.,typing.Tuple[str, ...]
, a tuple of strings).typing.Tuple[{typename1}, ..., {typenameN}]
, type-checking tuples containing exactlyN
items each satisfying a unique PEP-compliant child hint{typenameI}
(e.g.,typing.Tuple[str, int, float]
, a tuple containing exactly one string, one integer, and one floating-point number in that order).
- Shallow
typing.AsyncContextManager
,typing.ContextManager
,typing.Match
, andtyping.Pattern
support. The@beartype
decorator now type-checks the shallow types (but not deep contents) of parameters and return values annotated by the PEP 484-complianttyping.AsyncContextManager
,typing.ContextManager
,typing.Match
, andtyping.Pattern
objects. This was no small feat, as the implementations of:typing.AsyncContextManager
andtyping.ContextManager
define__repr__()
dunder methods returning erroneous machine-readable representations obstructing proper support under prior releases.typing.Match
andtyping.Pattern
under Python 3.6 are non-trivially obtuse and basically broken at runtime.
- Shallow type variable support. The
@beartype
decorator now shallowly type-checks all otherwise supported PEP-compliant type hints parametrized by one or more type variables (e.g.,List[T]
, whereT = TypeVar('T')
). Previously, this decorator raised exceptions when decorating callables with such hints. This decorator does not yet deeply type-check type variables to be constrained across callable parameters and return values or class methods. Fordef muh_func(muh_param: List[T]) -> T: return muh_param[0]
, as example, this decorator now shallowly type-checks the passed parametermuh_param
to be a list but does not yet deeply type-check that this function returns values of the same types as items of this list.
Features Optimized
- Nested PEP-compliant type hint type-checking. Under Python ≥ 3.8, the
@beartype
decorator now generates optimized code when deeply type-checking items contained in arbitrarily nested PEP-compliant type hints (e.g.,typing.List[typing.Union[bool, str, typing.List[int]]]
) with PEP 572-style assignment expressions, generalizing similar sequence-specific optimizations introduced with beartype 0.3.0. - PEP-compliant type hint breadth-first search (BFS). The
@beartype
decorator now internally catalogues PEP-compliant type hints during the breadth-first search (BFS) it performs over these hints as simple tuples rather than fixed lists, as the former are both mildly faster than the latter and significantly more maintainable (which is the main gain here).
Issues Resolved
- PEP-compliant type hint code generation memoization. The
@beartype
decorator now properly memoizes the type-checking code it generates for PEP-compliant type hints. Prior beartype releases silently failed to memoize this code across different callables annotated by the same hints.
API Changed
- In the
beartype.cave
submodule, added:- A new public
beartype.cave.HintPep585Type
attribute, defined as the C-based type of all PEP 585-compliant type hints (i.e., C-based type hint instantiated by subscripting either a concrete builtin container class likelist
ortuple
or an abstract base class (ABC) declared by thecollections.abc
submodule likecollections.abc.Iterable
orcollections.abc.Sequence
) if the active Python interpreter targets at least Python 3.9.0 orbeartype.cave.UnavailableType
otherwise. This is a prerequisite for PEP 585 support in a subsequent stable release.
- A new public
- In the
beartype.roar
submodule, renamed:BeartypeCallCheckException
toBeartypeCallHintException
.BeartypeCallCheckPepException
toBeartypeCallHintPepException
.BeartypeCallCheckPepParamException
to
BeartypeCallHintPepParamException
.BeartypeCallCheckPepReturnException
to
BeartypeCallHintPepReturnException
.BeartypeCallCheckNonPepException
to
BeartypeCallHintNonPepException
.BeartypeCallCheckNonPepParamException
to
BeartypeCallHintNonPepParamException
.BeartypeCallCheckNonPepReturnException
to
BeartypeCallHintNonPepReturnException
.