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
3 | 3 | matrix: |
4 | 4 | fast_finish: true |
5 | 5 | include: |
6 | - python: "3.10" | |
7 | dist: focal | |
6 | 8 | - python: 3.9 |
7 | 9 | - python: 3.9.1 |
8 | 10 | - python: 3.8 |
0 | 0 | typing >= 3.7.4 |
1 | 1 | mypy_extensions >= 0.3.0 |
2 | typing_extensions >= 3.7.4 | |
2 | typing_extensions >= 3.7.4.2 |
4 | 4 | import sys |
5 | 5 | from setuptools import setup |
6 | 6 | |
7 | version = '0.7.1' | |
7 | version = '0.8.0' | |
8 | 8 | description = 'Runtime inspection utilities for typing module.' |
9 | 9 | long_description = ''' |
10 | 10 | Typing Inspect |
0 | 0 | flake8; python_version >= '3.6' |
1 | 1 | 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' | |
3 | 7 | typing >= 3.7.4; python_version < '3.5' |
4 | 8 | 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' |
0 | 0 | import sys |
1 | ||
2 | import pytest | |
3 | ||
1 | 4 | from typing_inspect import ( |
2 | 5 | is_generic_type, is_callable_type, is_new_type, is_tuple_type, is_union_type, |
3 | 6 | is_optional_type, is_final_type, is_literal_type, is_typevar, is_classvar, |
4 | 7 | is_forward_ref, get_origin, get_parameters, get_last_args, get_args, get_bound, |
5 | 8 | 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 | ) | |
7 | 11 | from unittest import TestCase, main, skipIf, skipUnless |
8 | 12 | from typing import ( |
9 | 13 | Union, Callable, Optional, TypeVar, Sequence, AnyStr, Mapping, |
14 | 18 | from typing_extensions import TypedDict as TETypedDict |
15 | 19 | from typing_extensions import Final |
16 | 20 | 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_ | |
26 | 22 | |
27 | 23 | # Does this raise an exception ? |
28 | 24 | # from typing import ClassVar |
119 | 115 | exec(PY36_TESTS) |
120 | 116 | |
121 | 117 | |
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 | ||
122 | 130 | class IsUtilityTestCase(TestCase): |
123 | 131 | def sample_test(self, fun, samples, nonsamples): |
124 | 132 | msg = "Error asserting that %s(%s) is %s" |
165 | 173 | S = TypeVar('S') |
166 | 174 | samples = [Union, Union[T, int], Union[int, Union[T, S]]] |
167 | 175 | 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]] | |
168 | 184 | self.sample_test(is_union_type, samples, nonsamples) |
169 | 185 | |
170 | 186 | def test_optional_type(self): |
247 | 263 | @skipIf(not WITH_NEWTYPE, "NewType is not present") |
248 | 264 | def test_new_type(self): |
249 | 265 | T = TypeVar('T') |
266 | ||
267 | class WithAttrSuperTypeCls: | |
268 | __supertype__ = str | |
269 | ||
270 | class WithAttrSuperTypeObj: | |
271 | def __init__(self): | |
272 | self.__supertype__ = str | |
273 | ||
250 | 274 | 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)), | |
257 | 282 | ] |
258 | 283 | nonsamples = [ |
259 | 284 | int, |
263 | 288 | Union["u", "v"], |
264 | 289 | type, |
265 | 290 | T, |
291 | NewType, | |
292 | NewType('N', int), | |
293 | WithAttrSuperTypeCls, | |
294 | WithAttrSuperTypeCls(), | |
295 | WithAttrSuperTypeObj, | |
296 | WithAttrSuperTypeObj(), | |
266 | 297 | ] |
267 | 298 | self.sample_test(is_new_type, samples, nonsamples) |
268 | 299 | |
305 | 336 | self.assertEqual(get_origin(ClassVar[int]), None) |
306 | 337 | self.assertEqual(get_origin(Generic), Generic) |
307 | 338 | self.assertEqual(get_origin(Generic[T]), Generic) |
339 | # Cannot use assertEqual on Py3.5.2. | |
340 | self.assertIs(get_origin(Literal[42]), Literal) | |
308 | 341 | if PY39: |
309 | 342 | self.assertEqual(get_origin(list[int]), list) |
310 | 343 | if GENERIC_TUPLE_PARAMETRIZABLE: |
404 | 437 | # This would return (~T,) before Python 3.9. |
405 | 438 | self.assertEqual(get_args(List), ()) |
406 | 439 | |
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 | ||
407 | 444 | def test_bound(self): |
408 | 445 | T = TypeVar('T') |
409 | 446 | TB = TypeVar('TB', bound=int) |
15 | 15 | if (3, 4, 0) <= sys.version_info[:3] < (3, 9, 2): |
16 | 16 | from typing_extensions import _TypedDictMeta as _TypedDictMeta_TE |
17 | 17 | 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 | |
20 | 25 | else: |
21 | 26 | # typing_extensions.TypedDict is a re-export from typing. |
22 | 27 | from typing import TypedDict |
29 | 34 | WITH_FINAL = True |
30 | 35 | WITH_LITERAL = True |
31 | 36 | WITH_CLASSVAR = True |
37 | WITH_NEWTYPE = True | |
32 | 38 | LEGACY_TYPING = False |
33 | 39 | |
34 | 40 | if NEW_TYPING: |
35 | 41 | from typing import ( |
36 | Generic, Callable, Union, TypeVar, ClassVar, Tuple, _GenericAlias, ForwardRef | |
42 | Generic, Callable, Union, TypeVar, ClassVar, Tuple, _GenericAlias, | |
43 | ForwardRef, NewType, | |
37 | 44 | ) |
38 | 45 | from typing_extensions import Final, Literal |
39 | 46 | if sys.version_info[:3] >= (3, 9, 0): |
43 | 50 | typingGenericAlias = (_GenericAlias,) |
44 | 51 | else: |
45 | 52 | from typing import ( |
46 | Callable, CallableMeta, Union, Tuple, TupleMeta, TypeVar, GenericMeta, _ForwardRef | |
53 | Callable, CallableMeta, Union, Tuple, TupleMeta, TypeVar, GenericMeta, | |
54 | _ForwardRef, | |
47 | 55 | ) |
48 | 56 | try: |
49 | 57 | from typing import _Union, _ClassVar |
62 | 70 | WITH_FINAL = False |
63 | 71 | |
64 | 72 | try: # python 3.6 |
65 | from typing_extensions import _Literal | |
73 | from typing_extensions import Literal | |
66 | 74 | except ImportError: # python 2.7 |
67 | 75 | try: |
68 | from typing import _Literal | |
76 | from typing import Literal | |
69 | 77 | except ImportError: |
70 | 78 | 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 | |
71 | 87 | |
72 | 88 | |
73 | 89 | def _gorg(cls): |
193 | 209 | return WITH_FINAL and type(tp) is _Final |
194 | 210 | |
195 | 211 | |
212 | try: | |
213 | MaybeUnionType = types.UnionType | |
214 | except AttributeError: | |
215 | MaybeUnionType = None | |
216 | ||
217 | ||
196 | 218 | def is_union_type(tp): |
197 | 219 | """Test if the type is a union type. Examples:: |
198 | 220 | |
200 | 222 | is_union_type(Union) == True |
201 | 223 | is_union_type(Union[int, int]) == False |
202 | 224 | is_union_type(Union[T, int]) == True |
225 | is_union_type(int | int) == False | |
226 | is_union_type(T | int) == True | |
203 | 227 | """ |
204 | 228 | if NEW_TYPING: |
205 | 229 | 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))) | |
207 | 232 | return type(tp) is _Union |
208 | 233 | |
209 | 234 | |
211 | 236 | if NEW_TYPING: |
212 | 237 | return (tp is Literal or |
213 | 238 | 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) | |
215 | 240 | |
216 | 241 | |
217 | 242 | def is_typevar(tp): |
246 | 271 | """Tests if the type represents a distinct type. Examples:: |
247 | 272 | |
248 | 273 | is_new_type(int) == False |
274 | is_new_type(NewType) == True | |
249 | 275 | is_new_type(NewType('Age', int)) == True |
250 | 276 | is_new_type(NewType('Scores', List[Dict[str, float]])) == True |
251 | 277 | """ |
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'))) | |
253 | 292 | |
254 | 293 | |
255 | 294 | def is_forward_ref(tp): |
312 | 351 | return Union |
313 | 352 | if is_tuple_type(tp): |
314 | 353 | return Tuple |
354 | if is_literal_type(tp): | |
355 | return Literal | |
315 | 356 | |
316 | 357 | return None |
317 | 358 | |
472 | 513 | if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis: |
473 | 514 | res = (list(res[:-1]), res[-1]) |
474 | 515 | return res |
516 | if MaybeUnionType and isinstance(tp, MaybeUnionType): | |
517 | return tp.__args__ | |
475 | 518 | return () |
476 | 519 | if is_classvar(tp) or is_final_type(tp): |
477 | 520 | return (tp.__type__,) if tp.__type__ is not None else () |