Allows type inspections for the typing
and typing_extensions
libraries. Works in Python 2.7 and 3 - Python 3.5.0+ is supported.
This library is designed to ease use in all Python versions, and so functions like get_typing
return multiple types.
The rational for this comes in three parts:
- Different versions of Python change what types they hold. Take
__origin__
, which changed from returning typing types (e.g.typing.Mapping
) to class types (e.g.collections.abc.Mapping
) in Python 3.7.
Meaning the functionget_origin
would have version incompatibilities between 3.7 and other versions of Python. - Different versions of Python contain different information. Take
__extra__
, which was removed in Python 3.7.
Meaning there isn't an easy way to get the typing type from aget_origin
function in Python 3.7. And the result from aget_extra
function is alwaysNone
. - Internally converting to and from typing and class types is easy. Meaning there's little overhead to returning all the available types.
And so your code can focus on using the type information you need, rather than having to check version incompatibilities. Whilst the library is designed to reduce version incompatibility it doesn't guarantee that there is none. Please look at Python compatibility to see which are known.
Currently the following functions are supported:
get_typing
get_args
get_parameters
get_type_info
get_type_var_info
get_bases
get_mro
get_mro_orig
- (WIP)
build_types
This returns the typing type and the class type of the type passed to it.
from typing import Mapping, Union
import collections.abc
from typing_inspect_lib import get_typing
typing_, class_ = get_typing(Mapping[str, int])
assert typing_ is Mapping
assert class_ is collections.abc.Mapping
# Not all types have custom classes
typing_, class_ = get_typing(Union[str, int])
assert typing_ is Union
assert class_ is Union
This returns the arguments stored in the type provided.
from typing import Mapping, Union
from typing_inspect_lib import get_args
assert get_args(Mapping) == ()
assert get_args(Mapping[str, int]) == (str, int)
assert get_args(Mapping[Union[str, int], int]) == (Union[str, int], int)
This returns the parameters stored in the type provided.
from typing import Mapping, TypeVar
from typing_inspect_lib import get_parameters
TKey = TypeVar('TKey')
TValue = TypeVar('TValue')
assert get_parameters(Mapping[str, int]) == ()
assert get_parameters(Mapping[TKey, TValue]) == (TKey, TValue)
This returns all the type information for a type.
from typing import Mapping, TypeVar
from typing_inspect_lib import get_type_info
import collections
TKey = TypeVar('TKey')
type_ = get_type_info(Mapping[TKey, int])
assert type_ == (Mapping, collections.abc.Mapping, (int,), (TKey,))
assert type_.typing == Mapping
assert type_.class_ == collections.abc.Mapping
assert type_.args == (int,)
assert type_.parameters == (TKey,)
This returns all the information stored in the TypeVar provided.
from typing import Mapping, TypeVar
from typing_inspect_lib import get_parameters, get_type_var_info
TExample = TypeVar('TExample', bound=int)
t_example = get_type_var_info(TExample)
assert t_example == ('TExample', int, False, False)
assert t_example.name == 'TExample'
assert t_example.bound == int
assert not t_example.covariant
assert not t_example.contravariant
# Using this with unwrapped typing types
assert get_parameters(Mapping) != ()
mapping_parameters = tuple(get_type_var_info(p) for p in get_parameters(Mapping))
assert (('KT', None, False, False), ('VT_co', None, True, False)) == mapping_parameters
Gets the bases of the type, returns the typing type, class type and orig type.
This returns different values in different versions of Python. The below is Python 3.7.
from typing import Mapping, Collection
from collections import abc
from typing_inspect_lib import get_bases
assert get_bases(Mapping) == ((Collection, abc.Collection, None),)
assert get_bases(abc.Mapping) == ((Collection, abc.Collection, None),)
assert get_bases(Mapping[int, int]) == ((Collection, abc.Collection, Collection[int]),)
Gets the mro of the type. Returning them as class types.
Builtin types are converted to their class type to get the MRO and so Generic
may be missing.
This returns different values in different versions of Python. The below is Python 3.7.
from typing import Mapping
from collections import abc
from typing_inspect_lib import get_mro
mro = (
abc.Mapping,
abc.Collection,
abc.Sized,
abc.Iterable,
abc.Container,
object
)
assert get_mro(Mapping) == mro
assert get_mro(abc.Mapping) == mro
assert get_mro(Mapping[int, str]) == mro
This builds the type object in, soon to be, easy to use classes.
from typing import Mapping, Union
import collections.abc
from typing_inspect_lib import build_types
type_ = build_types(Mapping[Union[str, int], int])
assert type_.typing is Mapping
assert type_.class_ is collections.abc.Mapping
assert type_.args[0].typing is Union
assert type_.args[0].args[0].typing is str
- <3.5.[0-1]> Passing
get_args(typing_extensions.Counter[T])
returns(T, int)
rather than(T,)
. - Some parameters change between versions:
- <3.5.2>
typing.Type
isCT
, rather thanCT_co
. (It is still covariant and bound totype
)
FIX:typing_extensions.Type
works fine. - <3.5.[0-1]>
typing.ItemsView
isT_co, KT, VT_co
rather thanKT, VT_co
. - <3.5.[0-1]>
typing_extensions.Coroutine
isV_co, T_co, T_contra
rather thanT_co, T_contra, T_co
.
- <3.5.2>
- Due to changes in
collections.abc
the following functions return different results in different Python versions:get_bases
get_mro
get_mro_orig
Help! I'm using Python 3.5.1 and 3.6 and don't have access to typing.ClassVar
in 3.5.1. What do I do?
There are two ways to fix this:
-
Install
typing_extensions
and usetyping_extensions.ClassVar
.This is the preferred method, as this allows you to use
ClassVar
just the same way you would withtyping
.from typing import Union from typing_extensions import ClassVar from typing_inspect_lib import get_type_info assert get_type_info(Union).typing is not ClassVar assert get_type_info(ClassVar).typing is ClassVar assert get_type_info(ClassVar[int]).typing is ClassVar
-
You can use
ClassVar_
exported bytyping_inspect_lib
.This defaults to just an
object()
, and so should only be used to on the right hand side ofget_special_object
checks:from typing import Union from typing_inspect_lib import get_type_info, ClassVar_ assert get_type_info(Union).typing is not ClassVar_ assert get_type_info(ClassVar_).typing is ClassVar_ assert get_type_info(ClassVar_[int]).typing is ClassVar_ # Error in 3.5.1
This depends on if you have typing_extensions
installed. For the most part if you have it installed then you shouldn't need to use these. These also only affect older Python versions. Below is the list of when you may need to use these objects.
- <3.5.0>
Protocol_
- <2.x & 3.x>
Protocol_
- <2.x & 3.x>
NewType_
- <3.5.[0-2]>
ClassVar_