Codebase list python-typing-inspect / 0273af4
Update upstream source from tag 'upstream/0.8.0' Update to upstream version '0.8.0' with Debian dir 335577bb2c792583cf7221bc98753aa97dc0ddfe Louis-Philippe VĂ©ronneau 1 year, 8 months ago
6 changed file(s) with 116 addition(s) and 29 deletion(s). Raw diff Collapse all Expand all
33 matrix:
44 fast_finish: true
55 include:
6 - python: "3.10"
7 dist: focal
68 - python: 3.9
79 - python: 3.9.1
810 - python: 3.8
00 typing >= 3.7.4
11 mypy_extensions >= 0.3.0
2 typing_extensions >= 3.7.4
2 typing_extensions >= 3.7.4.2
44 import sys
55 from setuptools import setup
66
7 version = '0.7.1'
7 version = '0.8.0'
88 description = 'Runtime inspection utilities for typing module.'
99 long_description = '''
1010 Typing Inspect
00 flake8; python_version >= '3.6'
11 flake8-bugbear; python_version >= '3.6'
2 pytest>=2.8; python_version >= '3.3'
2 importlib-metadata<3.0; python_version < '3.6'
3 packaging<21.0; python_version < '3.6'
4 pytest~=4.6; python_version < '3.6'
5 pytest>=4.6; python_version >= '3.6'
6 pathlib2 < 2.3.7; python_version == '3.5.0' or python_version == '3.5.1'
37 typing >= 3.7.4; python_version < '3.5'
48 mypy_extensions >= 0.3.0
5 typing_extensions >= 3.7.4
9 typing_extensions >= 3.7.4; python_version >= '3.6'
10 typing_extensions >= 3.7.4, < 3.10; python_version < '3.6'
00 import sys
1
2 import pytest
3
14 from typing_inspect import (
25 is_generic_type, is_callable_type, is_new_type, is_tuple_type, is_union_type,
36 is_optional_type, is_final_type, is_literal_type, is_typevar, is_classvar,
47 is_forward_ref, get_origin, get_parameters, get_last_args, get_args, get_bound,
58 get_constraints, get_generic_type, get_generic_bases, get_last_origin,
6 typed_dict_keys, get_forward_arg, WITH_FINAL, WITH_LITERAL, LEGACY_TYPING)
9 typed_dict_keys, get_forward_arg, WITH_FINAL, WITH_LITERAL, LEGACY_TYPING, WITH_NEWTYPE,
10 )
711 from unittest import TestCase, main, skipIf, skipUnless
812 from typing import (
913 Union, Callable, Optional, TypeVar, Sequence, AnyStr, Mapping,
1418 from typing_extensions import TypedDict as TETypedDict
1519 from typing_extensions import Final
1620 from typing_extensions import Literal
17
18 # Does this raise an exception ?
19 # from typing import NewType
20 if sys.version_info < (3, 5, 2):
21 WITH_NEWTYPE = False
22 else:
23 from typing import NewType
24 WITH_NEWTYPE = True
25
21 from typing_extensions import NewType as NewType_
2622
2723 # Does this raise an exception ?
2824 # from typing import ClassVar
119115 exec(PY36_TESTS)
120116
121117
118 # It is important for the test that this function is called 'NewType' to simulate the same __qualname__
119 # - which is "NewType.<locals>.new_type" - as typing.NewType has, i.e. it should be checked that is_new_type
120 # still do not accept a function which has the same __qualname__ and an attribute called __supertype__.
121 def NewType(name, tp):
122 def new_type(x):
123 return x
124
125 new_type.__name__ = name
126 new_type.__supertype__ = tp
127 return new_type
128
129
122130 class IsUtilityTestCase(TestCase):
123131 def sample_test(self, fun, samples, nonsamples):
124132 msg = "Error asserting that %s(%s) is %s"
165173 S = TypeVar('S')
166174 samples = [Union, Union[T, int], Union[int, Union[T, S]]]
167175 nonsamples = [int, Union[int, int], [], Iterable[Any]]
176 self.sample_test(is_union_type, samples, nonsamples)
177
178 @pytest.mark.skipif(sys.version_info < (3, 10), reason="requires 3.10 or higher")
179 def test_union_pep604(self):
180 T = TypeVar('T')
181 S = TypeVar('S')
182 samples = [T | int, int | (T | S), int | str]
183 nonsamples = [int, int | int, [], Iterable[Any]]
168184 self.sample_test(is_union_type, samples, nonsamples)
169185
170186 def test_optional_type(self):
247263 @skipIf(not WITH_NEWTYPE, "NewType is not present")
248264 def test_new_type(self):
249265 T = TypeVar('T')
266
267 class WithAttrSuperTypeCls:
268 __supertype__ = str
269
270 class WithAttrSuperTypeObj:
271 def __init__(self):
272 self.__supertype__ = str
273
250274 samples = [
251 NewType('A', int),
252 NewType('B', complex),
253 NewType('C', List[int]),
254 NewType('D', Union['p', 'y', 't', 'h', 'o', 'n']),
255 NewType('E', List[Dict[str, float]]),
256 NewType('F', NewType('F_', int)),
275 NewType_,
276 NewType_('A', int),
277 NewType_('B', complex),
278 NewType_('C', List[int]),
279 NewType_('D', Union['p', 'y', 't', 'h', 'o', 'n']),
280 NewType_('E', List[Dict[str, float]]),
281 NewType_('F', NewType('F_', int)),
257282 ]
258283 nonsamples = [
259284 int,
263288 Union["u", "v"],
264289 type,
265290 T,
291 NewType,
292 NewType('N', int),
293 WithAttrSuperTypeCls,
294 WithAttrSuperTypeCls(),
295 WithAttrSuperTypeObj,
296 WithAttrSuperTypeObj(),
266297 ]
267298 self.sample_test(is_new_type, samples, nonsamples)
268299
305336 self.assertEqual(get_origin(ClassVar[int]), None)
306337 self.assertEqual(get_origin(Generic), Generic)
307338 self.assertEqual(get_origin(Generic[T]), Generic)
339 # Cannot use assertEqual on Py3.5.2.
340 self.assertIs(get_origin(Literal[42]), Literal)
308341 if PY39:
309342 self.assertEqual(get_origin(list[int]), list)
310343 if GENERIC_TUPLE_PARAMETRIZABLE:
404437 # This would return (~T,) before Python 3.9.
405438 self.assertEqual(get_args(List), ())
406439
440 if sys.version_info >= (3, 10):
441 self.assertEqual(get_args(int | str), (int, str))
442 self.assertEqual(get_args((int | tuple[T, int])[str]), (int, tuple[str, int]))
443
407444 def test_bound(self):
408445 T = TypeVar('T')
409446 TB = TypeVar('TB', bound=int)
1515 if (3, 4, 0) <= sys.version_info[:3] < (3, 9, 2):
1616 from typing_extensions import _TypedDictMeta as _TypedDictMeta_TE
1717 elif sys.version_info[:3] >= (3, 9, 2):
18 # typing_extensions.TypedDict is a re-export from typing.
19 from typing import _TypedDictMeta as _TypedDictMeta_TE
18 # Situation with typing_extensions.TypedDict is complicated.
19 # Use the one defined in typing_extentions, and if there is none,
20 # fall back to typing.
21 try:
22 from typing_extensions import _TypedDictMeta as _TypedDictMeta_TE
23 except ImportError:
24 from typing import _TypedDictMeta as _TypedDictMeta_TE
2025 else:
2126 # typing_extensions.TypedDict is a re-export from typing.
2227 from typing import TypedDict
2934 WITH_FINAL = True
3035 WITH_LITERAL = True
3136 WITH_CLASSVAR = True
37 WITH_NEWTYPE = True
3238 LEGACY_TYPING = False
3339
3440 if NEW_TYPING:
3541 from typing import (
36 Generic, Callable, Union, TypeVar, ClassVar, Tuple, _GenericAlias, ForwardRef
42 Generic, Callable, Union, TypeVar, ClassVar, Tuple, _GenericAlias,
43 ForwardRef, NewType,
3744 )
3845 from typing_extensions import Final, Literal
3946 if sys.version_info[:3] >= (3, 9, 0):
4350 typingGenericAlias = (_GenericAlias,)
4451 else:
4552 from typing import (
46 Callable, CallableMeta, Union, Tuple, TupleMeta, TypeVar, GenericMeta, _ForwardRef
53 Callable, CallableMeta, Union, Tuple, TupleMeta, TypeVar, GenericMeta,
54 _ForwardRef,
4755 )
4856 try:
4957 from typing import _Union, _ClassVar
6270 WITH_FINAL = False
6371
6472 try: # python 3.6
65 from typing_extensions import _Literal
73 from typing_extensions import Literal
6674 except ImportError: # python 2.7
6775 try:
68 from typing import _Literal
76 from typing import Literal
6977 except ImportError:
7078 WITH_LITERAL = False
79
80 try: # python < 3.5.2
81 from typing_extensions import NewType
82 except ImportError:
83 try:
84 from typing import NewType
85 except ImportError:
86 WITH_NEWTYPE = False
7187
7288
7389 def _gorg(cls):
193209 return WITH_FINAL and type(tp) is _Final
194210
195211
212 try:
213 MaybeUnionType = types.UnionType
214 except AttributeError:
215 MaybeUnionType = None
216
217
196218 def is_union_type(tp):
197219 """Test if the type is a union type. Examples::
198220
200222 is_union_type(Union) == True
201223 is_union_type(Union[int, int]) == False
202224 is_union_type(Union[T, int]) == True
225 is_union_type(int | int) == False
226 is_union_type(T | int) == True
203227 """
204228 if NEW_TYPING:
205229 return (tp is Union or
206 isinstance(tp, typingGenericAlias) and tp.__origin__ is Union)
230 (isinstance(tp, typingGenericAlias) and tp.__origin__ is Union) or
231 (MaybeUnionType and isinstance(tp, MaybeUnionType)))
207232 return type(tp) is _Union
208233
209234
211236 if NEW_TYPING:
212237 return (tp is Literal or
213238 isinstance(tp, typingGenericAlias) and tp.__origin__ is Literal)
214 return WITH_LITERAL and type(tp) is _Literal
239 return WITH_LITERAL and type(tp) is type(Literal)
215240
216241
217242 def is_typevar(tp):
246271 """Tests if the type represents a distinct type. Examples::
247272
248273 is_new_type(int) == False
274 is_new_type(NewType) == True
249275 is_new_type(NewType('Age', int)) == True
250276 is_new_type(NewType('Scores', List[Dict[str, float]])) == True
251277 """
252 return getattr(tp, '__supertype__', None) is not None
278 if not WITH_NEWTYPE:
279 return False
280 elif sys.version_info[:3] >= (3, 10, 0) and sys.version_info.releaselevel != 'beta':
281 return tp is NewType or isinstance(tp, NewType)
282 elif sys.version_info[:3] >= (3, 0, 0):
283 return (tp is NewType or
284 (getattr(tp, '__supertype__', None) is not None and
285 getattr(tp, '__qualname__', '') == 'NewType.<locals>.new_type' and
286 tp.__module__ in ('typing', 'typing_extensions')))
287 else: # python 2
288 # __qualname__ is not available in python 2, so we simplify the test here
289 return (tp is NewType or
290 (getattr(tp, '__supertype__', None) is not None and
291 tp.__module__ in ('typing', 'typing_extensions')))
253292
254293
255294 def is_forward_ref(tp):
312351 return Union
313352 if is_tuple_type(tp):
314353 return Tuple
354 if is_literal_type(tp):
355 return Literal
315356
316357 return None
317358
472513 if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis:
473514 res = (list(res[:-1]), res[-1])
474515 return res
516 if MaybeUnionType and isinstance(tp, MaybeUnionType):
517 return tp.__args__
475518 return ()
476519 if is_classvar(tp) or is_final_type(tp):
477520 return (tp.__type__,) if tp.__type__ is not None else ()