Reputation: 7070
I have a function accepting another Python functions which are annotated with type hints (__annotations__
). I would like to use those hints to do some type checking during runtime. The issue is that type classes from typing module does not seem very easy to work with (no isinstance, no issubclass). So, I wonder, is there a way to convert them to mypy type objects, and then use mypy.subtypes.is_subtype
to compare types from type hints?
Upvotes: 3
Views: 2182
Reputation: 177
I can provide a way to convert the most typing types into builtin types. Maybe this helps.
The typing module gives us the function get_origin
. From documentation:
Get the unsubscripted version of a type: for a typing object of the form X[Y, Z, ...] return X.
If X is a typing-module alias for a builtin or collections class, it will be normalized to the original class. If X is an instance of ParamSpecArgs or ParamSpecKwargs, return the underlying ParamSpec. Return None for unsupported objects.
from typing import get_origin
import typing
def convert_typing_types(typing_type):
converted = get_origin(typing_type)
if converted in vars(typing).values():
# do something with supported but not mappable types for example Literal
pass
if converted is None:
# do something with unsupported typing Constructs, such like Self or NoReturn
pass
return converted
Now you can use the function like this:
>>> convert_typing_types(typing.List)
<class 'list'>
>>> convert_typing_types(typing.Dict)
<class 'dict'>
Because get_origin
is not just for converting typing-aliases to builtins, there is a side effect, if, for example str
is passed to get_origin
, None is returned, so we have to do the following:
def convert_to_mypy(typ: Any) -> MyPyType:
try:
return convert_builtin_or_abc(typ)
except ValueError:
return convert_builtin_or_abc(convert_typing_types(typ))
Upvotes: 0
Reputation: 16951
The short answer is there is no easy way. The typing
module is, by design, not going to provide much help for runtime checking. PEP 484 says
This PEP aims to provide a standard syntax for type annotations, opening up Python code to easier static analysis and refactoring, potential runtime type checking, and (perhaps, in some contexts) code generation utilizing type information.
Of these goals, static analysis is the most important. This includes support for off-line type checkers such as
mypy
, as well as providing a standard notation that can be used by IDEs for code completion and refactoring.Non-goals
While the proposed
typing
module will contain some building blocks for runtime type checking -- in particular theget_type_hints()
function -- third party packages would have to be developed to implement specific runtime type checking functionality, for example using decorators or metaclasses. Using type hints for performance optimizations is left as an exercise for the reader.
Upvotes: 1