|
1
|
|
|
""" |
|
2
|
|
|
PRIVATE MODULE: do not import (from) it directly. |
|
3
|
|
|
|
|
4
|
|
|
This module contains functionality for supporting the compatibility with |
|
5
|
|
|
multiple Python versions. |
|
6
|
|
|
""" |
|
7
|
|
|
import sys |
|
8
|
|
|
from typing import ( |
|
9
|
|
|
get_type_hints as get_type_hints_, |
|
10
|
|
|
Type, |
|
11
|
|
|
Callable, |
|
12
|
|
|
Dict, |
|
13
|
|
|
Tuple, |
|
14
|
|
|
Optional) |
|
15
|
|
|
|
|
16
|
|
|
|
|
17
|
|
|
def get_naked_class(cls: type) -> type: |
|
18
|
|
|
""" |
|
19
|
|
|
Return the given type without generics. For example, ``List[int]`` will |
|
20
|
|
|
result in ``List``. |
|
21
|
|
|
:param cls: the type that should be stripped off its generic type. |
|
22
|
|
|
:return: a type without generics. |
|
23
|
|
|
""" |
|
24
|
|
|
# Python3.5: typing classes have __extra__ |
|
25
|
|
|
# Python3.6: typing classes have __extra__ |
|
26
|
|
|
# Python3.7: typing classes have __origin__ |
|
27
|
|
|
# Return the non-generic class (e.g. dict) of a generic type (e.g. Dict). |
|
28
|
|
|
attr = '__origin__' |
|
29
|
|
|
if sys.version_info[1] in (5, 6): |
|
30
|
|
|
attr = '__extra__' |
|
31
|
|
|
return getattr(cls, attr, cls) |
|
32
|
|
|
|
|
33
|
|
|
|
|
34
|
|
|
def get_type_hints(func: callable) -> Dict[str, type]: |
|
35
|
|
|
""" |
|
36
|
|
|
Return the type hints of the parameters of the given callable. |
|
37
|
|
|
:param func: the callable of which the type hints are to be returned. |
|
38
|
|
|
:return: a dict with parameter names and their types. |
|
39
|
|
|
""" |
|
40
|
|
|
# Python3.5: get_type_hints raises on classes without explicit constructor |
|
41
|
|
|
try: |
|
42
|
|
|
result = get_type_hints_(func) |
|
43
|
|
|
except AttributeError: |
|
44
|
|
|
result = {} |
|
45
|
|
|
return result |
|
46
|
|
|
|
|
47
|
|
|
|
|
48
|
|
|
def get_args_and_return_type( |
|
49
|
|
|
hint: Type[Callable]) -> Tuple[Optional[Tuple[type]], Optional[type]]: |
|
50
|
|
|
""" |
|
51
|
|
|
Get the argument types and the return type of a callable type hint |
|
52
|
|
|
(e.g. ``Callable[[int], str]). |
|
53
|
|
|
|
|
54
|
|
|
Example: |
|
55
|
|
|
``` |
|
56
|
|
|
arg_types, return_type = get_args_and_return_type(Callable[[int], str]) |
|
57
|
|
|
# args_types is (int, ) |
|
58
|
|
|
# return_type is str |
|
59
|
|
|
``` |
|
60
|
|
|
|
|
61
|
|
|
Example for when ``hint`` has no generics: |
|
62
|
|
|
``` |
|
63
|
|
|
arg_types, return_type = get_args_and_return_type(Callable) |
|
64
|
|
|
# args_types is None |
|
65
|
|
|
# return_type is None |
|
66
|
|
|
``` |
|
67
|
|
|
:param hint: the callable type hint. |
|
68
|
|
|
:return: a tuple of the argument types (as a tuple) and the return type. |
|
69
|
|
|
""" |
|
70
|
|
|
if hint in (callable, Callable): |
|
71
|
|
|
arg_types = None |
|
72
|
|
|
return_type = None |
|
73
|
|
|
elif hasattr(hint, '__result__'): |
|
74
|
|
|
arg_types = hint.__args__ |
|
75
|
|
|
return_type = hint.__result__ |
|
76
|
|
|
else: |
|
77
|
|
|
arg_types = hint.__args__[0:-1] |
|
78
|
|
|
return_type = hint.__args__[-1] |
|
79
|
|
|
return arg_types, return_type |
|
80
|
|
|
|