I am reading the typing module code and also looking into mypy to understand how it does type checking. Unfortunately for me, mypy
builds a very smart tree with typed expressions that I still don't understand, and it's all based on static analysis.
I would like to implement a type check system that is dynamic (no static analysis) in Python. Assuming the function that performs type checks is called check_type
, I want to accomplish the following:
>>> import typing
>>>
>>> check_type(1, int)
True
>>> check_type(1, float)
False
>>> check_type([1], typing.List[int])
True
>>> check_type([1], typing.List[float])
False
>>> check_type([1], typing.List[typing.Any])
True
>>> check_type((1,), typing.Tuple[int])
True
I thought about recreating the object type from its value, such as:
>>> get_type([1])
typing.List<~T>[int]
But this doesn't work with issubclass
:
>>> issubclass(typing.List[int], typing.List[typing.Any])
False
I don't see a simple way to check types in Python without assuming a lot of things about the internals of the typing
stdlib module (e.g., accessing __args__
or __tuple_params__
).
How can I properly implement a check_type
function that work for the cases previously listed? I am using Python 2.7.
You can easily get the very limited functionality that works correctly for the simple examples provided in your question:
import mypy.api
def check_type(value, typ):
program_text = 'from typing import *; v: {} = {}'.format(typ, repr(value))
normal_report, error_report, exit_code = mypy.api.run(['-c', program_text])
return exit_code == 0
int_ = 1
str_ = 'a'
list_str_ = ['a']
list_int_ = [1]
tuple_int_ = (1,)
assert check_type(int_, 'int')
assert not check_type(str_, 'int')
assert check_type(list_int_, 'List[int]')
assert not check_type(list_str_, 'List[int]')
assert check_type(list_int_, 'List[Any]')
assert check_type(tuple_int_, 'Tuple[int]')
You can even do some more advanced stuff (for example, refer to the types that correspond to classes you defined in your program) by extending this code a bit, so that mypy gets to parse your entire source code as opposed to just the current line.
Alternatively, you might want to look at enforce or typeguard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With