diff -Nru python-typing-extensions-3.7.4.3/debian/changelog python-typing-extensions-3.10.0.2/debian/changelog --- python-typing-extensions-3.7.4.3/debian/changelog 2020-10-08 13:07:27.000000000 +0000 +++ python-typing-extensions-3.10.0.2/debian/changelog 2021-10-07 08:56:08.000000000 +0000 @@ -1,3 +1,18 @@ +python-typing-extensions (3.10.0.2-1) unstable; urgency=medium + + [ Adam Cecile ] + * New upstream release including Python 3.9/3.10 new features. + Closes: #995853 + + [ Michael R. Crusoe ] + * d/control: confirm team maintenance. Closes: #995852 + * Standards-Version: 4.6.0 (routine-update) + * watch file standard 4 (routine-update) + * d/control: depend on :any python, to help with cross-building + * d/control: correct the homepage + + -- Michael R. Crusoe Thu, 07 Oct 2021 10:56:08 +0200 + python-typing-extensions (3.7.4.3-1) unstable; urgency=medium [ Michael R. Crusoe ] diff -Nru python-typing-extensions-3.7.4.3/debian/clean python-typing-extensions-3.10.0.2/debian/clean --- python-typing-extensions-3.7.4.3/debian/clean 1970-01-01 00:00:00.000000000 +0000 +++ python-typing-extensions-3.10.0.2/debian/clean 2021-10-07 08:18:56.000000000 +0000 @@ -0,0 +1 @@ +src_py3/typing_extensions.egg-info/ diff -Nru python-typing-extensions-3.7.4.3/debian/control python-typing-extensions-3.10.0.2/debian/control --- python-typing-extensions-3.7.4.3/debian/control 2020-10-08 13:07:27.000000000 +0000 +++ python-typing-extensions-3.10.0.2/debian/control 2021-10-07 08:55:21.000000000 +0000 @@ -1,16 +1,17 @@ Source: python-typing-extensions -Maintainer: Michael R. Crusoe +Maintainer: Debian Python Team +Uploaders: Michael R. Crusoe Section: python Testsuite: autopkgtest-pkg-python Priority: optional Build-Depends: debhelper-compat (= 13), dh-python, - python3-all, + python3-all:any, python3-setuptools -Standards-Version: 4.5.0 +Standards-Version: 4.6.0 Vcs-Browser: https://salsa.debian.org/python-team/packages/python-typing-extensions Vcs-Git: https://salsa.debian.org/python-team/packages/python-typing-extensions.git -Homepage: https://pypi.python.org/pypi/typing-extensions/ +Homepage: https://github.com/python/typing/blob/master/typing_extensions/README.rst Rules-Requires-Root: no Package: python3-typing-extensions diff -Nru python-typing-extensions-3.7.4.3/debian/watch python-typing-extensions-3.10.0.2/debian/watch --- python-typing-extensions-3.7.4.3/debian/watch 2019-07-23 10:09:48.000000000 +0000 +++ python-typing-extensions-3.10.0.2/debian/watch 2021-10-07 08:23:08.000000000 +0000 @@ -1,3 +1,3 @@ -version=3 +version=4 opts=uversionmangle=s/(rc|a|b|c)/~$1/ \ https://pypi.debian.net/typing-extensions/typing_extensions-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) diff -Nru python-typing-extensions-3.7.4.3/PKG-INFO python-typing-extensions-3.10.0.2/PKG-INFO --- python-typing-extensions-3.7.4.3/PKG-INFO 2020-08-23 16:33:40.000000000 +0000 +++ python-typing-extensions-3.10.0.2/PKG-INFO 2021-08-30 18:43:58.817377800 +0000 @@ -1,28 +1,11 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: typing_extensions -Version: 3.7.4.3 +Version: 3.10.0.2 Summary: Backported and Experimental Type Hints for Python 3.5+ Home-page: https://github.com/python/typing/blob/master/typing_extensions/README.rst -Author: Guido van Rossum, Jukka Lehtosalo, Lukasz Langa, Michael Lee +Author: Guido van Rossum, Jukka Lehtosalo, Łukasz Langa, Michael Lee Author-email: levkivskyi@gmail.com License: PSF -Description: Typing Extensions -- Backported and Experimental Type Hints for Python - - The ``typing`` module was added to the standard library in Python 3.5 on - a provisional basis and will no longer be provisional in Python 3.7. However, - this means users of Python 3.5 - 3.6 who are unable to upgrade will not be - able to take advantage of new types added to the ``typing`` module, such as - ``typing.Text`` or ``typing.Coroutine``. - - The ``typing_extensions`` module contains both backports of these changes - as well as experimental types that will eventually be added to the ``typing`` - module, such as ``Protocol`` or ``TypedDict``. - - Users of other Python versions should continue to install and use - the ``typing`` module from PyPi instead of using this one unless specifically - writing code that must be compatible with multiple Python versions or requires - experimental types. - Keywords: typing function annotations type hints hinting checking checker typehints typehinting typechecking backport Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha @@ -37,4 +20,26 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 Classifier: Topic :: Software Development +License-File: LICENSE + +Typing Extensions -- Backported and Experimental Type Hints for Python + +The ``typing`` module was added to the standard library in Python 3.5, but +many new features have been added to the module since then. +This means users of Python 3.5 - 3.6 who are unable to upgrade will not be +able to take advantage of new types added to the ``typing`` module, such as +``typing.Protocol`` or ``typing.TypedDict``. + +The ``typing_extensions`` module contains backports of these changes. +Experimental types that will eventually be added to the ``typing`` +module are also included in ``typing_extensions``, such as +``typing.ParamSpec`` and ``typing.TypeGuard``. + +Users of Python versions before 3.5 should install and use +the ``typing`` module from PyPI instead of using this one, unless specifically +writing code that must be compatible with multiple Python versions or requires +experimental types. + + diff -Nru python-typing-extensions-3.7.4.3/README.rst python-typing-extensions-3.10.0.2/README.rst --- python-typing-extensions-3.7.4.3/README.rst 2020-02-11 18:17:38.000000000 +0000 +++ python-typing-extensions-3.10.0.2/README.rst 2021-08-29 15:36:03.000000000 +0000 @@ -21,7 +21,7 @@ static duck typing) or ``TypedDict`` (see PEP 589). Users of other Python versions should continue to install and use -use the ``typing`` module from PyPi instead of using this one unless +the ``typing`` module from PyPi instead of using this one unless specifically writing code that must be compatible with multiple Python versions or requires experimental types. @@ -44,21 +44,29 @@ - ``NewType`` - ``NoReturn`` - ``overload`` (note that older versions of ``typing`` only let you use ``overload`` in stubs) +- ``OrderedDict`` - ``Protocol`` (except on Python 3.5.0) -- ``runtime`` (except on Python 3.5.0) +- ``runtime_checkable`` (except on Python 3.5.0) - ``Text`` - ``Type`` - ``TypedDict`` +- ``TypeAlias`` - ``TYPE_CHECKING`` Python 3.4+ only: ----------------- - ``ChainMap`` +- ``ParamSpec`` +- ``Concatenate`` +- ``ParamSpecArgs`` +- ``ParamSpecKwargs`` +- ``TypeGuard`` Python 3.5+ only: ----------------- +- ``Annotated`` (except on Python 3.5.0-3.5.2) - ``AsyncIterable`` - ``AsyncIterator`` - ``AsyncContextManager`` @@ -80,6 +88,12 @@ These changes are _not_ backported to prevent subtle compatibility issues when mixing the differing implementations of modified classes. +Certain types have incorrect runtime behavior due to limitations of older +versions of the typing module. For example, ``ParamSpec`` and ``Concatenate`` +will not work with ``get_args``, ``get_origin``. Certain PEP 612 special cases +in user-defined ``Generic``\ s are also not available. +These types are only guaranteed to work for static type checking. + Running tests ============= diff -Nru python-typing-extensions-3.7.4.3/setup.py python-typing-extensions-3.10.0.2/setup.py --- python-typing-extensions-3.7.4.3/setup.py 2020-08-23 16:32:30.000000000 +0000 +++ python-typing-extensions-3.10.0.2/setup.py 2021-08-30 18:43:17.000000000 +0000 @@ -9,23 +9,24 @@ 'to install the typing package.\n') exit(1) -version = '3.7.4.3' +version = '3.10.0.2' description = 'Backported and Experimental Type Hints for Python 3.5+' long_description = '''\ Typing Extensions -- Backported and Experimental Type Hints for Python -The ``typing`` module was added to the standard library in Python 3.5 on -a provisional basis and will no longer be provisional in Python 3.7. However, -this means users of Python 3.5 - 3.6 who are unable to upgrade will not be +The ``typing`` module was added to the standard library in Python 3.5, but +many new features have been added to the module since then. +This means users of Python 3.5 - 3.6 who are unable to upgrade will not be able to take advantage of new types added to the ``typing`` module, such as -``typing.Text`` or ``typing.Coroutine``. +``typing.Protocol`` or ``typing.TypedDict``. -The ``typing_extensions`` module contains both backports of these changes -as well as experimental types that will eventually be added to the ``typing`` -module, such as ``Protocol`` or ``TypedDict``. +The ``typing_extensions`` module contains backports of these changes. +Experimental types that will eventually be added to the ``typing`` +module are also included in ``typing_extensions``, such as +``typing.ParamSpec`` and ``typing.TypeGuard``. -Users of other Python versions should continue to install and use -the ``typing`` module from PyPi instead of using this one unless specifically +Users of Python versions before 3.5 should install and use +the ``typing`` module from PyPI instead of using this one, unless specifically writing code that must be compatible with multiple Python versions or requires experimental types. ''' @@ -43,6 +44,7 @@ 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', 'Topic :: Software Development', ] @@ -57,7 +59,7 @@ version=version, description=description, long_description=long_description, - author='Guido van Rossum, Jukka Lehtosalo, Lukasz Langa, Michael Lee', + author='Guido van Rossum, Jukka Lehtosalo, Łukasz Langa, Michael Lee', author_email='levkivskyi@gmail.com', url='https://github.com/python/typing/blob/master/typing_extensions/README.rst', license='PSF', diff -Nru python-typing-extensions-3.7.4.3/src_py3/test_typing_extensions.py python-typing-extensions-3.10.0.2/src_py3/test_typing_extensions.py --- python-typing-extensions-3.7.4.3/src_py3/test_typing_extensions.py 2020-07-07 22:29:25.000000000 +0000 +++ python-typing-extensions-3.10.0.2/src_py3/test_typing_extensions.py 2021-08-30 18:39:51.000000000 +0000 @@ -7,13 +7,14 @@ import subprocess import types from unittest import TestCase, main, skipUnless, skipIf -from typing import TypeVar, Optional +from typing import TypeVar, Optional, Union from typing import T, KT, VT # Not in __all__. -from typing import Tuple, List, Dict, Iterator +from typing import Tuple, List, Dict, Iterator, Callable from typing import Generic from typing import no_type_check from typing_extensions import NoReturn, ClassVar, Final, IntVar, Literal, Type, NewType, TypedDict -from typing_extensions import TypeAlias +from typing_extensions import TypeAlias, ParamSpec, Concatenate, ParamSpecArgs, ParamSpecKwargs, TypeGuard + try: from typing_extensions import Protocol, runtime, runtime_checkable except ImportError: @@ -51,6 +52,8 @@ TYPING_3_5_1 = TYPING_LATEST or sys.version_info[:3] >= (3, 5, 1) TYPING_3_5_3 = TYPING_LATEST or sys.version_info[:3] >= (3, 5, 3) TYPING_3_6_1 = TYPING_LATEST or sys.version_info[:3] >= (3, 6, 1) +TYPING_3_10_0 = TYPING_LATEST or sys.version_info[:3] >= (3, 10, 0) +TYPING_3_11_0 = TYPING_LATEST or sys.version_info[:3] >= (3, 11, 0) # For typing versions where issubclass(...) and # isinstance(...) checks are forbidden. @@ -464,6 +467,10 @@ @skipUnless(PY36, 'Python 3.6 required') def test_get_type_hints_modules(self): ann_module_type_hints = {1: 2, 'f': Tuple[int, int], 'x': int, 'y': str} + if (TYPING_3_11_0 + or (TYPING_3_10_0 and sys.version_info.releaselevel in {'candidate', 'final'})): + # More tests were added in 3.10rc1. + ann_module_type_hints['u'] = int | float self.assertEqual(gth(ann_module), ann_module_type_hints) self.assertEqual(gth(ann_module2), {}) self.assertEqual(gth(ann_module3), {}) @@ -517,6 +524,80 @@ self.assertNotEqual(gth(Loop, globals())['attr'], Final) +@skipUnless(PEP_560, "Python 3.7+ required") +class GetUtilitiesTestCase(TestCase): + def test_get_origin(self): + from typing_extensions import get_origin + + T = TypeVar('T') + P = ParamSpec('P') + class C(Generic[T]): pass + self.assertIs(get_origin(C[int]), C) + self.assertIs(get_origin(C[T]), C) + self.assertIs(get_origin(int), None) + self.assertIs(get_origin(ClassVar[int]), ClassVar) + self.assertIs(get_origin(Union[int, str]), Union) + self.assertIs(get_origin(Literal[42, 43]), Literal) + self.assertIs(get_origin(Final[List[int]]), Final) + self.assertIs(get_origin(Generic), Generic) + self.assertIs(get_origin(Generic[T]), Generic) + self.assertIs(get_origin(List[Tuple[T, T]][int]), list) + self.assertIs(get_origin(Annotated[T, 'thing']), Annotated) + self.assertIs(get_origin(List), list) + self.assertIs(get_origin(Tuple), tuple) + self.assertIs(get_origin(Callable), collections.abc.Callable) + if sys.version_info >= (3, 9): + self.assertIs(get_origin(list[int]), list) + self.assertIs(get_origin(list), None) + self.assertIs(get_origin(P.args), P) + self.assertIs(get_origin(P.kwargs), P) + + def test_get_args(self): + from typing_extensions import get_args + + T = TypeVar('T') + class C(Generic[T]): pass + self.assertEqual(get_args(C[int]), (int,)) + self.assertEqual(get_args(C[T]), (T,)) + self.assertEqual(get_args(int), ()) + self.assertEqual(get_args(ClassVar[int]), (int,)) + self.assertEqual(get_args(Union[int, str]), (int, str)) + self.assertEqual(get_args(Literal[42, 43]), (42, 43)) + self.assertEqual(get_args(Final[List[int]]), (List[int],)) + self.assertEqual(get_args(Union[int, Tuple[T, int]][str]), + (int, Tuple[str, int])) + self.assertEqual(get_args(typing.Dict[int, Tuple[T, T]][Optional[int]]), + (int, Tuple[Optional[int], Optional[int]])) + self.assertEqual(get_args(Callable[[], T][int]), ([], int)) + self.assertEqual(get_args(Callable[..., int]), (..., int)) + self.assertEqual(get_args(Union[int, Callable[[Tuple[T, ...]], str]]), + (int, Callable[[Tuple[T, ...]], str])) + self.assertEqual(get_args(Tuple[int, ...]), (int, ...)) + self.assertEqual(get_args(Tuple[()]), ((),)) + self.assertEqual(get_args(Annotated[T, 'one', 2, ['three']]), (T, 'one', 2, ['three'])) + self.assertEqual(get_args(List), ()) + self.assertEqual(get_args(Tuple), ()) + self.assertEqual(get_args(Callable), ()) + if sys.version_info >= (3, 9): + self.assertEqual(get_args(list[int]), (int,)) + self.assertEqual(get_args(list), ()) + if sys.version_info >= (3, 9): + # Support Python versions with and without the fix for + # https://bugs.python.org/issue42195 + # The first variant is for 3.9.2+, the second for 3.9.0 and 1 + self.assertIn(get_args(collections.abc.Callable[[int], str]), + (([int], str), ([[int]], str))) + self.assertIn(get_args(collections.abc.Callable[[], str]), + (([], str), ([[]], str))) + self.assertEqual(get_args(collections.abc.Callable[..., str]), (..., str)) + P = ParamSpec('P') + # In 3.9 and lower we use typing_extensions's hacky implementation + # of ParamSpec, which gets incorrectly wrapped in a list + self.assertIn(get_args(Callable[P, int]), [(P, int), ([P], int)]) + self.assertEqual(get_args(Callable[Concatenate[int, P], int]), + (Concatenate[int, P], int)) + + class CollectionsAbcTests(BaseTestCase): def test_isinstance_collections(self): @@ -609,6 +690,30 @@ if TYPING_3_5_3: self.assertNotIsSubclass(collections.defaultdict, MyDefDict) + @skipUnless(CAN_INSTANTIATE_COLLECTIONS, "Behavior added in typing 3.6.1") + def test_ordereddict_instantiation(self): + self.assertIs( + type(typing_extensions.OrderedDict()), + collections.OrderedDict) + self.assertIs( + type(typing_extensions.OrderedDict[KT, VT]()), + collections.OrderedDict) + self.assertIs( + type(typing_extensions.OrderedDict[str, int]()), + collections.OrderedDict) + + def test_ordereddict_subclass(self): + + class MyOrdDict(typing_extensions.OrderedDict[str, int]): + pass + + od = MyOrdDict() + self.assertIsInstance(od, MyOrdDict) + + self.assertIsSubclass(MyOrdDict, collections.OrderedDict) + if TYPING_3_5_3: + self.assertNotIsSubclass(collections.OrderedDict, MyOrdDict) + def test_chainmap_instantiation(self): self.assertIs(type(typing_extensions.ChainMap()), collections.ChainMap) self.assertIs(type(typing_extensions.ChainMap[KT, VT]()), collections.ChainMap) @@ -1240,8 +1345,9 @@ self.assertIsSubclass(P, PR) with self.assertRaises(TypeError): PR[int] - with self.assertRaises(TypeError): - PR[int, 1] + if not TYPING_3_10_0: + with self.assertRaises(TypeError): + PR[int, 1] class P1(Protocol, Generic[T]): def bar(self, x: T) -> str: ... class P2(Generic[T], Protocol): @@ -1254,7 +1360,7 @@ def bar(self, x: str) -> str: return x self.assertIsInstance(Test(), PSub) - if TYPING_3_5_3: + if TYPING_3_5_3 and not TYPING_3_10_0: with self.assertRaises(TypeError): PR[int, ClassVar] @@ -1421,6 +1527,15 @@ self.assertIsSubclass(B, Custom) self.assertNotIsSubclass(A, Custom) + def test_no_init_same_for_different_protocol_implementations(self): + class CustomProtocolWithoutInitA(Protocol): + pass + + class CustomProtocolWithoutInitB(Protocol): + pass + + self.assertEqual(CustomProtocolWithoutInitA.__init__, CustomProtocolWithoutInitB.__init__) + class TypedDictTests(BaseTestCase): @@ -1494,7 +1609,7 @@ def test_typeddict_errors(self): Emp = TypedDict('Emp', {'name': str, 'id': int}) - if sys.version_info[:2] >= (3, 9): + if sys.version_info >= (3, 9, 2): self.assertEqual(TypedDict.__module__, 'typing') else: self.assertEqual(TypedDict.__module__, 'typing_extensions') @@ -1516,7 +1631,7 @@ def test_py36_class_syntax_usage(self): self.assertEqual(LabelPoint2D.__name__, 'LabelPoint2D') self.assertEqual(LabelPoint2D.__module__, __name__) - self.assertEqual(LabelPoint2D.__annotations__, {'x': int, 'y': int, 'label': str}) + self.assertEqual(get_type_hints(LabelPoint2D), {'x': int, 'y': int, 'label': str}) self.assertEqual(LabelPoint2D.__bases__, (dict,)) self.assertEqual(LabelPoint2D.__total__, True) self.assertNotIsSubclass(LabelPoint2D, typing.Sequence) @@ -1550,11 +1665,15 @@ self.assertEqual(D(), {}) self.assertEqual(D(x=1), {'x': 1}) self.assertEqual(D.__total__, False) + self.assertEqual(D.__required_keys__, frozenset()) + self.assertEqual(D.__optional_keys__, {'x'}) if PY36: self.assertEqual(Options(), {}) self.assertEqual(Options(log_level=2), {'log_level': 2}) self.assertEqual(Options.__total__, False) + self.assertEqual(Options.__required_keys__, frozenset()) + self.assertEqual(Options.__optional_keys__, {'log_level', 'log_path'}) @skipUnless(PY36, 'Python 3.6 required') def test_optional_keys(self): @@ -1565,11 +1684,11 @@ def test_keys_inheritance(self): assert BaseAnimal.__required_keys__ == frozenset(['name']) assert BaseAnimal.__optional_keys__ == frozenset([]) - assert BaseAnimal.__annotations__ == {'name': str} + assert get_type_hints(BaseAnimal) == {'name': str} assert Animal.__required_keys__ == frozenset(['name']) assert Animal.__optional_keys__ == frozenset(['tail', 'voice']) - assert Animal.__annotations__ == { + assert get_type_hints(Animal) == { 'name': str, 'tail': bool, 'voice': str, @@ -1577,7 +1696,7 @@ assert Cat.__required_keys__ == frozenset(['name', 'fur_color']) assert Cat.__optional_keys__ == frozenset(['tail', 'voice']) - assert Cat.__annotations__ == { + assert get_type_hints(Cat) == { 'fur_color': str, 'name': str, 'tail': bool, @@ -1872,6 +1991,209 @@ with self.assertRaises(TypeError): TypeAlias[int] +class ParamSpecTests(BaseTestCase): + + def test_basic_plain(self): + P = ParamSpec('P') + self.assertEqual(P, P) + self.assertIsInstance(P, ParamSpec) + # Should be hashable + hash(P) + + def test_repr(self): + P = ParamSpec('P') + P_co = ParamSpec('P_co', covariant=True) + P_contra = ParamSpec('P_contra', contravariant=True) + P_2 = ParamSpec('P_2') + self.assertEqual(repr(P), '~P') + self.assertEqual(repr(P_2), '~P_2') + + # Note: PEP 612 doesn't require these to be repr-ed correctly, but + # just follow CPython. + self.assertEqual(repr(P_co), '+P_co') + self.assertEqual(repr(P_contra), '-P_contra') + + def test_valid_uses(self): + P = ParamSpec('P') + T = TypeVar('T') + C1 = typing.Callable[P, int] + # Callable in Python 3.5.2 might be bugged when collecting __args__. + # https://github.com/python/cpython/blob/91185fe0284a04162e0b3425b53be49bdbfad67d/Lib/typing.py#L1026 + PY_3_5_2 = sys.version_info[:3] == (3, 5, 2) + if not PY_3_5_2: + self.assertEqual(C1.__args__, (P, int)) + self.assertEqual(C1.__parameters__, (P,)) + C2 = typing.Callable[P, T] + if not PY_3_5_2: + self.assertEqual(C2.__args__, (P, T)) + self.assertEqual(C2.__parameters__, (P, T)) + + + # Test collections.abc.Callable too. + if sys.version_info[:2] >= (3, 9): + # Note: no tests for Callable.__parameters__ here + # because types.GenericAlias Callable is hardcoded to search + # for tp_name "TypeVar" in C. This was changed in 3.10. + C3 = collections.abc.Callable[P, int] + self.assertEqual(C3.__args__, (P, int)) + C4 = collections.abc.Callable[P, T] + self.assertEqual(C4.__args__, (P, T)) + + # ParamSpec instances should also have args and kwargs attributes. + # Note: not in dir(P) because of __class__ hacks + self.assertTrue(hasattr(P, 'args')) + self.assertTrue(hasattr(P, 'kwargs')) + + def test_args_kwargs(self): + P = ParamSpec('P') + # Note: not in dir(P) because of __class__ hacks + self.assertTrue(hasattr(P, 'args')) + self.assertTrue(hasattr(P, 'kwargs')) + self.assertIsInstance(P.args, ParamSpecArgs) + self.assertIsInstance(P.kwargs, ParamSpecKwargs) + self.assertIs(P.args.__origin__, P) + self.assertIs(P.kwargs.__origin__, P) + self.assertEqual(repr(P.args), "P.args") + self.assertEqual(repr(P.kwargs), "P.kwargs") + + def test_user_generics(self): + T = TypeVar("T") + P = ParamSpec("P") + P_2 = ParamSpec("P_2") + + class X(Generic[T, P]): + pass + + G1 = X[int, P_2] + self.assertEqual(G1.__args__, (int, P_2)) + self.assertEqual(G1.__parameters__, (P_2,)) + + G2 = X[int, Concatenate[int, P_2]] + self.assertEqual(G2.__args__, (int, Concatenate[int, P_2])) + self.assertEqual(G2.__parameters__, (P_2,)) + + # The following are some valid uses cases in PEP 612 that don't work: + # These do not work in 3.9, _type_check blocks the list and ellipsis. + # G3 = X[int, [int, bool]] + # G4 = X[int, ...] + # G5 = Z[[int, str, bool]] + # Not working because this is special-cased in 3.10. + # G6 = Z[int, str, bool] + + class Z(Generic[P]): + pass + + def test_pickle(self): + global P, P_co, P_contra + P = ParamSpec('P') + P_co = ParamSpec('P_co', covariant=True) + P_contra = ParamSpec('P_contra', contravariant=True) + for proto in range(pickle.HIGHEST_PROTOCOL): + with self.subTest('Pickle protocol {proto}'.format(proto=proto)): + for paramspec in (P, P_co, P_contra): + z = pickle.loads(pickle.dumps(paramspec, proto)) + self.assertEqual(z.__name__, paramspec.__name__) + self.assertEqual(z.__covariant__, paramspec.__covariant__) + self.assertEqual(z.__contravariant__, paramspec.__contravariant__) + self.assertEqual(z.__bound__, paramspec.__bound__) + + def test_eq(self): + P = ParamSpec('P') + self.assertEqual(P, P) + self.assertEqual(hash(P), hash(P)) + # ParamSpec should compare by id similar to TypeVar in CPython + self.assertNotEqual(ParamSpec('P'), P) + self.assertIsNot(ParamSpec('P'), P) + # Note: normally you don't test this as it breaks when there's + # a hash collision. However, ParamSpec *must* guarantee that + # as long as two objects don't have the same ID, their hashes + # won't be the same. + self.assertNotEqual(hash(ParamSpec('P')), hash(P)) + + +class ConcatenateTests(BaseTestCase): + def test_basics(self): + P = ParamSpec('P') + + class MyClass: ... + + c = Concatenate[MyClass, P] + self.assertNotEqual(c, Concatenate) + + def test_valid_uses(self): + P = ParamSpec('P') + T = TypeVar('T') + C1 = typing.Callable[Concatenate[int, P], int] + C2 = typing.Callable[Concatenate[int, T, P], T] + + # Test collections.abc.Callable too. + if sys.version_info[:2] >= (3, 9): + C3 = collections.abc.Callable[Concatenate[int, P], int] + C4 = collections.abc.Callable[Concatenate[int, T, P], T] + + def test_basic_introspection(self): + P = ParamSpec('P') + C1 = Concatenate[int, P] + C2 = Concatenate[int, T, P] + self.assertEqual(C1.__origin__, Concatenate) + self.assertEqual(C1.__args__, (int, P)) + self.assertEqual(C2.__origin__, Concatenate) + self.assertEqual(C2.__args__, (int, T, P)) + + def test_eq(self): + P = ParamSpec('P') + C1 = Concatenate[int, P] + C2 = Concatenate[int, P] + C3 = Concatenate[int, T, P] + self.assertEqual(C1, C2) + self.assertEqual(hash(C1), hash(C2)) + self.assertNotEqual(C1, C3) + + +class TypeGuardTests(BaseTestCase): + def test_basics(self): + TypeGuard[int] # OK + self.assertEqual(TypeGuard[int], TypeGuard[int]) + + def foo(arg) -> TypeGuard[int]: ... + self.assertEqual(gth(foo), {'return': TypeGuard[int]}) + + def test_repr(self): + if hasattr(typing, 'TypeGuard'): + mod_name = 'typing' + else: + mod_name = 'typing_extensions' + self.assertEqual(repr(TypeGuard), '{}.TypeGuard'.format(mod_name)) + cv = TypeGuard[int] + self.assertEqual(repr(cv), '{}.TypeGuard[int]'.format(mod_name)) + cv = TypeGuard[Employee] + self.assertEqual(repr(cv), '{}.TypeGuard[{}.Employee]'.format(mod_name, __name__)) + cv = TypeGuard[Tuple[int]] + self.assertEqual(repr(cv), '{}.TypeGuard[typing.Tuple[int]]'.format(mod_name)) + + @skipUnless(SUBCLASS_CHECK_FORBIDDEN, "Behavior added in typing 3.5.3") + def test_cannot_subclass(self): + with self.assertRaises(TypeError): + class C(type(TypeGuard)): + pass + with self.assertRaises(TypeError): + class C(type(TypeGuard[int])): + pass + + def test_cannot_init(self): + with self.assertRaises(TypeError): + TypeGuard() + with self.assertRaises(TypeError): + type(TypeGuard)() + with self.assertRaises(TypeError): + type(TypeGuard[Optional[int]])() + + def test_no_isinstance(self): + with self.assertRaises(TypeError): + isinstance(1, TypeGuard[int]) + with self.assertRaises(TypeError): + issubclass(int, TypeGuard) + class AllTests(BaseTestCase): @@ -1888,6 +2210,10 @@ self.assertIn('overload', a) self.assertIn('Text', a) self.assertIn('TYPE_CHECKING', a) + self.assertIn('TypeAlias', a) + self.assertIn('ParamSpec', a) + self.assertIn("Concatenate", a) + if TYPING_3_5_3: self.assertIn('Annotated', a) if PEP_560: @@ -1907,6 +2233,10 @@ self.assertIn('Protocol', a) self.assertIn('runtime', a) + # Check that all objects in `__all__` are present in the module + for name in a: + self.assertTrue(hasattr(typing_extensions, name)) + def test_typing_extensions_defers_when_possible(self): exclude = { 'overload', @@ -1916,7 +2246,7 @@ 'Final', 'get_type_hints' } - if sys.version_info[:2] == (3, 8): + if sys.version_info < (3, 10): exclude |= {'get_args', 'get_origin'} for item in typing_extensions.__all__: if item not in exclude and hasattr(typing, item): diff -Nru python-typing-extensions-3.7.4.3/src_py3/typing_extensions.egg-info/PKG-INFO python-typing-extensions-3.10.0.2/src_py3/typing_extensions.egg-info/PKG-INFO --- python-typing-extensions-3.7.4.3/src_py3/typing_extensions.egg-info/PKG-INFO 2020-08-23 16:33:40.000000000 +0000 +++ python-typing-extensions-3.10.0.2/src_py3/typing_extensions.egg-info/PKG-INFO 2021-08-30 18:43:58.000000000 +0000 @@ -1,28 +1,11 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: typing-extensions -Version: 3.7.4.3 +Version: 3.10.0.2 Summary: Backported and Experimental Type Hints for Python 3.5+ Home-page: https://github.com/python/typing/blob/master/typing_extensions/README.rst -Author: Guido van Rossum, Jukka Lehtosalo, Lukasz Langa, Michael Lee +Author: Guido van Rossum, Jukka Lehtosalo, Łukasz Langa, Michael Lee Author-email: levkivskyi@gmail.com License: PSF -Description: Typing Extensions -- Backported and Experimental Type Hints for Python - - The ``typing`` module was added to the standard library in Python 3.5 on - a provisional basis and will no longer be provisional in Python 3.7. However, - this means users of Python 3.5 - 3.6 who are unable to upgrade will not be - able to take advantage of new types added to the ``typing`` module, such as - ``typing.Text`` or ``typing.Coroutine``. - - The ``typing_extensions`` module contains both backports of these changes - as well as experimental types that will eventually be added to the ``typing`` - module, such as ``Protocol`` or ``TypedDict``. - - Users of other Python versions should continue to install and use - the ``typing`` module from PyPi instead of using this one unless specifically - writing code that must be compatible with multiple Python versions or requires - experimental types. - Keywords: typing function annotations type hints hinting checking checker typehints typehinting typechecking backport Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha @@ -37,4 +20,26 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 Classifier: Topic :: Software Development +License-File: LICENSE + +Typing Extensions -- Backported and Experimental Type Hints for Python + +The ``typing`` module was added to the standard library in Python 3.5, but +many new features have been added to the module since then. +This means users of Python 3.5 - 3.6 who are unable to upgrade will not be +able to take advantage of new types added to the ``typing`` module, such as +``typing.Protocol`` or ``typing.TypedDict``. + +The ``typing_extensions`` module contains backports of these changes. +Experimental types that will eventually be added to the ``typing`` +module are also included in ``typing_extensions``, such as +``typing.ParamSpec`` and ``typing.TypeGuard``. + +Users of Python versions before 3.5 should install and use +the ``typing`` module from PyPI instead of using this one, unless specifically +writing code that must be compatible with multiple Python versions or requires +experimental types. + + diff -Nru python-typing-extensions-3.7.4.3/src_py3/typing_extensions.py python-typing-extensions-3.10.0.2/src_py3/typing_extensions.py --- python-typing-extensions-3.7.4.3/src_py3/typing_extensions.py 2020-07-07 22:29:25.000000000 +0000 +++ python-typing-extensions-3.10.0.2/src_py3/typing_extensions.py 2021-08-30 18:39:51.000000000 +0000 @@ -18,6 +18,7 @@ if PEP_560: GenericMeta = TypingMeta = type + from typing import _GenericAlias else: from typing import GenericMeta, TypingMeta OLD_GENERICS = False @@ -115,7 +116,9 @@ __all__ = [ # Super-special typing primitives. 'ClassVar', + 'Concatenate', 'Final', + 'ParamSpec', 'Type', # ABCs (from collections.abc). @@ -134,6 +137,7 @@ 'Counter', 'Deque', 'DefaultDict', + 'OrderedDict', 'TypedDict', # Structural checks, a.k.a. protocols. @@ -146,6 +150,8 @@ 'NewType', 'overload', 'Text', + 'TypeAlias', + 'TypeGuard', 'TYPE_CHECKING', ] @@ -938,6 +944,34 @@ return _generic_new(collections.defaultdict, cls, *args, **kwds) +if hasattr(typing, 'OrderedDict'): + OrderedDict = typing.OrderedDict +elif (3, 7, 0) <= sys.version_info[:3] < (3, 7, 2): + OrderedDict = typing._alias(collections.OrderedDict, (KT, VT)) +elif _geqv_defined: + class OrderedDict(collections.OrderedDict, typing.MutableMapping[KT, VT], + metaclass=_ExtensionsGenericMeta, + extra=collections.OrderedDict): + + __slots__ = () + + def __new__(cls, *args, **kwds): + if _geqv(cls, OrderedDict): + return collections.OrderedDict(*args, **kwds) + return _generic_new(collections.OrderedDict, cls, *args, **kwds) +else: + class OrderedDict(collections.OrderedDict, typing.MutableMapping[KT, VT], + metaclass=_ExtensionsGenericMeta, + extra=collections.OrderedDict): + + __slots__ = () + + def __new__(cls, *args, **kwds): + if cls._gorg is OrderedDict: + return collections.OrderedDict(*args, **kwds) + return _generic_new(collections.OrderedDict, cls, *args, **kwds) + + if hasattr(typing, 'Counter'): Counter = typing.Counter elif (3, 5, 0) <= sys.version_info[:3] <= (3, 5, 1): @@ -1119,6 +1153,11 @@ if hasattr(typing, 'Protocol'): Protocol = typing.Protocol elif HAVE_PROTOCOLS and not PEP_560: + + def _no_init(self, *args, **kwargs): + if type(self)._is_protocol: + raise TypeError('Protocols cannot be instantiated') + class _ProtocolMeta(GenericMeta): """Internal metaclass for Protocol. @@ -1209,9 +1248,6 @@ raise TypeError('Protocols can only inherit from other' ' protocols, got %r' % base) - def _no_init(self, *args, **kwargs): - if type(self)._is_protocol: - raise TypeError('Protocols cannot be instantiated') cls.__init__ = _no_init def _proto_hook(other): @@ -1364,7 +1400,11 @@ elif PEP_560: - from typing import _type_check, _GenericAlias, _collect_type_vars # noqa + from typing import _type_check, _collect_type_vars # noqa + + def _no_init(self, *args, **kwargs): + if type(self)._is_protocol: + raise TypeError('Protocols cannot be instantiated') class _ProtocolMeta(abc.ABCMeta): # This metaclass is a bit unfortunate and exists only because of the lack @@ -1542,10 +1582,6 @@ isinstance(base, _ProtocolMeta) and base._is_protocol): raise TypeError('Protocols can only inherit from other' ' protocols, got %r' % base) - - def _no_init(self, *args, **kwargs): - if type(self)._is_protocol: - raise TypeError('Protocols cannot be instantiated') cls.__init__ = _no_init @@ -1584,9 +1620,11 @@ pass -if sys.version_info[:2] >= (3, 9): +if sys.version_info >= (3, 9, 2): # The standard library TypedDict in Python 3.8 does not store runtime information # about which (if any) keys are optional. See https://bugs.python.org/issue38834 + # The standard library TypedDict in Python 3.9.0/1 does not honour the "total" + # keyword with old-style TypedDict(). See https://bugs.python.org/issue42059 TypedDict = typing.TypedDict else: def _check_fails(cls, other): @@ -1643,19 +1681,25 @@ raise TypeError("TypedDict takes either a dict or keyword arguments," " but not both") - ns = {'__annotations__': dict(fields), '__total__': total} + ns = {'__annotations__': dict(fields)} try: # Setting correct module is necessary to make typed dict classes pickleable. ns['__module__'] = sys._getframe(1).f_globals.get('__name__', '__main__') except (AttributeError, ValueError): pass - return _TypedDictMeta(typename, (), ns) + return _TypedDictMeta(typename, (), ns, total=total) _typeddict_new.__text_signature__ = ('($cls, _typename, _fields=None,' ' /, *, total=True, **kwargs)') class _TypedDictMeta(type): + def __init__(cls, name, bases, ns, total=True): + # In Python 3.4 and 3.5 the __init__ method also needs to support the + # keyword arguments. + # See https://www.python.org/dev/peps/pep-0487/#implementation-details + super(_TypedDictMeta, cls).__init__(name, bases, ns) + def __new__(cls, name, bases, ns, total=True): # Create new typed dict class object. # This method is called directly when TypedDict is subclassed, @@ -2024,11 +2068,22 @@ # Python 3.8 has get_origin() and get_args() but those implementations aren't # Annotated-aware, so we can't use those, only Python 3.9 versions will do. -if sys.version_info[:2] >= (3, 9): +# Similarly, Python 3.9's implementation doesn't support ParamSpecArgs and +# ParamSpecKwargs. +if sys.version_info[:2] >= (3, 10): get_origin = typing.get_origin get_args = typing.get_args elif PEP_560: - from typing import _GenericAlias # noqa + try: + # 3.9+ + from typing import _BaseGenericAlias + except ImportError: + _BaseGenericAlias = _GenericAlias + try: + # 3.9+ + from typing import GenericAlias + except ImportError: + GenericAlias = _GenericAlias def get_origin(tp): """Get the unsubscripted version of a type. @@ -2043,10 +2098,12 @@ get_origin(Generic[T]) is Generic get_origin(Union[T, int]) is Union get_origin(List[Tuple[T, T]][int]) == list + get_origin(P.args) is P """ if isinstance(tp, _AnnotatedAlias): return Annotated - if isinstance(tp, _GenericAlias): + if isinstance(tp, (_GenericAlias, GenericAlias, _BaseGenericAlias, + ParamSpecArgs, ParamSpecKwargs)): return tp.__origin__ if tp is Generic: return Generic @@ -2065,7 +2122,9 @@ """ if isinstance(tp, _AnnotatedAlias): return (tp.__origin__,) + tp.__metadata__ - if isinstance(tp, _GenericAlias): + if isinstance(tp, (_GenericAlias, GenericAlias)): + if getattr(tp, "_special", False): + return () res = tp.__args__ if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis: res = (list(res[:-1]), res[-1]) @@ -2166,3 +2225,619 @@ It's invalid when used anywhere except as in the example above. """ __slots__ = () + + +# Python 3.10+ has PEP 612 +if hasattr(typing, 'ParamSpecArgs'): + ParamSpecArgs = typing.ParamSpecArgs + ParamSpecKwargs = typing.ParamSpecKwargs +else: + class _Immutable: + """Mixin to indicate that object should not be copied.""" + __slots__ = () + + def __copy__(self): + return self + + def __deepcopy__(self, memo): + return self + + class ParamSpecArgs(_Immutable): + """The args for a ParamSpec object. + + Given a ParamSpec object P, P.args is an instance of ParamSpecArgs. + + ParamSpecArgs objects have a reference back to their ParamSpec: + + P.args.__origin__ is P + + This type is meant for runtime introspection and has no special meaning to + static type checkers. + """ + def __init__(self, origin): + self.__origin__ = origin + + def __repr__(self): + return "{}.args".format(self.__origin__.__name__) + + class ParamSpecKwargs(_Immutable): + """The kwargs for a ParamSpec object. + + Given a ParamSpec object P, P.kwargs is an instance of ParamSpecKwargs. + + ParamSpecKwargs objects have a reference back to their ParamSpec: + + P.kwargs.__origin__ is P + + This type is meant for runtime introspection and has no special meaning to + static type checkers. + """ + def __init__(self, origin): + self.__origin__ = origin + + def __repr__(self): + return "{}.kwargs".format(self.__origin__.__name__) + +if hasattr(typing, 'ParamSpec'): + ParamSpec = typing.ParamSpec +else: + + # Inherits from list as a workaround for Callable checks in Python < 3.9.2. + class ParamSpec(list): + """Parameter specification variable. + + Usage:: + + P = ParamSpec('P') + + Parameter specification variables exist primarily for the benefit of static + type checkers. They are used to forward the parameter types of one + callable to another callable, a pattern commonly found in higher order + functions and decorators. They are only valid when used in ``Concatenate``, + or s the first argument to ``Callable``. In Python 3.10 and higher, + they are also supported in user-defined Generics at runtime. + See class Generic for more information on generic types. An + example for annotating a decorator:: + + T = TypeVar('T') + P = ParamSpec('P') + + def add_logging(f: Callable[P, T]) -> Callable[P, T]: + '''A type-safe decorator to add logging to a function.''' + def inner(*args: P.args, **kwargs: P.kwargs) -> T: + logging.info(f'{f.__name__} was called') + return f(*args, **kwargs) + return inner + + @add_logging + def add_two(x: float, y: float) -> float: + '''Add two numbers together.''' + return x + y + + Parameter specification variables defined with covariant=True or + contravariant=True can be used to declare covariant or contravariant + generic types. These keyword arguments are valid, but their actual semantics + are yet to be decided. See PEP 612 for details. + + Parameter specification variables can be introspected. e.g.: + + P.__name__ == 'T' + P.__bound__ == None + P.__covariant__ == False + P.__contravariant__ == False + + Note that only parameter specification variables defined in global scope can + be pickled. + """ + + # Trick Generic __parameters__. + __class__ = TypeVar + + @property + def args(self): + return ParamSpecArgs(self) + + @property + def kwargs(self): + return ParamSpecKwargs(self) + + def __init__(self, name, *, bound=None, covariant=False, contravariant=False): + super().__init__([self]) + self.__name__ = name + self.__covariant__ = bool(covariant) + self.__contravariant__ = bool(contravariant) + if bound: + self.__bound__ = typing._type_check(bound, 'Bound must be a type.') + else: + self.__bound__ = None + + # for pickling: + try: + def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + def_mod = None + if def_mod != 'typing_extensions': + self.__module__ = def_mod + + def __repr__(self): + if self.__covariant__: + prefix = '+' + elif self.__contravariant__: + prefix = '-' + else: + prefix = '~' + return prefix + self.__name__ + + def __hash__(self): + return object.__hash__(self) + + def __eq__(self, other): + return self is other + + def __reduce__(self): + return self.__name__ + + # Hack to get typing._type_check to pass. + def __call__(self, *args, **kwargs): + pass + + if not PEP_560: + # Only needed in 3.6 and lower. + def _get_type_vars(self, tvars): + if self not in tvars: + tvars.append(self) + + +# Inherits from list as a workaround for Callable checks in Python < 3.9.2. +class _ConcatenateGenericAlias(list): + + # Trick Generic into looking into this for __parameters__. + if PEP_560: + __class__ = typing._GenericAlias + elif sys.version_info[:3] == (3, 5, 2): + __class__ = typing.TypingMeta + else: + __class__ = typing._TypingBase + + # Flag in 3.8. + _special = False + # Attribute in 3.6 and earlier. + if sys.version_info[:3] == (3, 5, 2): + _gorg = typing.GenericMeta + else: + _gorg = typing.Generic + + def __init__(self, origin, args): + super().__init__(args) + self.__origin__ = origin + self.__args__ = args + + def __repr__(self): + _type_repr = typing._type_repr + return '{origin}[{args}]' \ + .format(origin=_type_repr(self.__origin__), + args=', '.join(_type_repr(arg) for arg in self.__args__)) + + def __hash__(self): + return hash((self.__origin__, self.__args__)) + + # Hack to get typing._type_check to pass in Generic. + def __call__(self, *args, **kwargs): + pass + + @property + def __parameters__(self): + return tuple(tp for tp in self.__args__ if isinstance(tp, (TypeVar, ParamSpec))) + + if not PEP_560: + # Only required in 3.6 and lower. + def _get_type_vars(self, tvars): + if self.__origin__ and self.__parameters__: + typing._get_type_vars(self.__parameters__, tvars) + + +@_tp_cache +def _concatenate_getitem(self, parameters): + if parameters == (): + raise TypeError("Cannot take a Concatenate of no types.") + if not isinstance(parameters, tuple): + parameters = (parameters,) + if not isinstance(parameters[-1], ParamSpec): + raise TypeError("The last parameter to Concatenate should be a " + "ParamSpec variable.") + msg = "Concatenate[arg, ...]: each arg must be a type." + parameters = tuple(typing._type_check(p, msg) for p in parameters) + return _ConcatenateGenericAlias(self, parameters) + + +if hasattr(typing, 'Concatenate'): + Concatenate = typing.Concatenate + _ConcatenateGenericAlias = typing._ConcatenateGenericAlias # noqa +elif sys.version_info[:2] >= (3, 9): + @_TypeAliasForm + def Concatenate(self, parameters): + """Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """ + return _concatenate_getitem(self, parameters) + +elif sys.version_info[:2] >= (3, 7): + class _ConcatenateForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + def __getitem__(self, parameters): + return _concatenate_getitem(self, parameters) + + Concatenate = _ConcatenateForm( + 'Concatenate', + doc="""Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """) + +elif hasattr(typing, '_FinalTypingBase'): + class _ConcatenateAliasMeta(typing.TypingMeta): + """Metaclass for Concatenate.""" + + def __repr__(self): + return 'typing_extensions.Concatenate' + + class _ConcatenateAliasBase(typing._FinalTypingBase, + metaclass=_ConcatenateAliasMeta, + _root=True): + """Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """ + __slots__ = () + + def __instancecheck__(self, obj): + raise TypeError("Concatenate cannot be used with isinstance().") + + def __subclasscheck__(self, cls): + raise TypeError("Concatenate cannot be used with issubclass().") + + def __repr__(self): + return 'typing_extensions.Concatenate' + + def __getitem__(self, parameters): + return _concatenate_getitem(self, parameters) + + Concatenate = _ConcatenateAliasBase(_root=True) +# For 3.5.0 - 3.5.2 +else: + class _ConcatenateAliasMeta(typing.TypingMeta): + """Metaclass for Concatenate.""" + + def __instancecheck__(self, obj): + raise TypeError("TypeAlias cannot be used with isinstance().") + + def __subclasscheck__(self, cls): + raise TypeError("TypeAlias cannot be used with issubclass().") + + def __call__(self, *args, **kwargs): + raise TypeError("Cannot instantiate TypeAlias") + + def __getitem__(self, parameters): + return _concatenate_getitem(self, parameters) + + class Concatenate(metaclass=_ConcatenateAliasMeta, _root=True): + """Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """ + __slots__ = () + +if hasattr(typing, 'TypeGuard'): + TypeGuard = typing.TypeGuard +elif sys.version_info[:2] >= (3, 9): + class _TypeGuardForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + @_TypeGuardForm + def TypeGuard(self, parameters): + """Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """ + item = typing._type_check(parameters, '{} accepts only single type.'.format(self)) + return _GenericAlias(self, (item,)) + +elif sys.version_info[:2] >= (3, 7): + class _TypeGuardForm(typing._SpecialForm, _root=True): + + def __repr__(self): + return 'typing_extensions.' + self._name + + def __getitem__(self, parameters): + item = typing._type_check(parameters, + '{} accepts only a single type'.format(self._name)) + return _GenericAlias(self, (item,)) + + TypeGuard = _TypeGuardForm( + 'TypeGuard', + doc="""Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """) +elif hasattr(typing, '_FinalTypingBase'): + class _TypeGuard(typing._FinalTypingBase, _root=True): + """Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """ + + __slots__ = ('__type__',) + + def __init__(self, tp=None, **kwds): + self.__type__ = tp + + def __getitem__(self, item): + cls = type(self) + if self.__type__ is None: + return cls(typing._type_check(item, + '{} accepts only a single type.'.format(cls.__name__[1:])), + _root=True) + raise TypeError('{} cannot be further subscripted' + .format(cls.__name__[1:])) + + def _eval_type(self, globalns, localns): + new_tp = typing._eval_type(self.__type__, globalns, localns) + if new_tp == self.__type__: + return self + return type(self)(new_tp, _root=True) + + def __repr__(self): + r = super().__repr__() + if self.__type__ is not None: + r += '[{}]'.format(typing._type_repr(self.__type__)) + return r + + def __hash__(self): + return hash((type(self).__name__, self.__type__)) + + def __eq__(self, other): + if not isinstance(other, _TypeGuard): + return NotImplemented + if self.__type__ is not None: + return self.__type__ == other.__type__ + return self is other + + TypeGuard = _TypeGuard(_root=True) +else: + class _TypeGuardMeta(typing.TypingMeta): + """Metaclass for TypeGuard""" + + def __new__(cls, name, bases, namespace, tp=None, _root=False): + self = super().__new__(cls, name, bases, namespace, _root=_root) + if tp is not None: + self.__type__ = tp + return self + + def __instancecheck__(self, obj): + raise TypeError("TypeGuard cannot be used with isinstance().") + + def __subclasscheck__(self, cls): + raise TypeError("TypeGuard cannot be used with issubclass().") + + def __getitem__(self, item): + cls = type(self) + if self.__type__ is not None: + raise TypeError('{} cannot be further subscripted' + .format(cls.__name__[1:])) + + param = typing._type_check( + item, + '{} accepts only single type.'.format(cls.__name__[1:])) + return cls(self.__name__, self.__bases__, + dict(self.__dict__), tp=param, _root=True) + + def _eval_type(self, globalns, localns): + new_tp = typing._eval_type(self.__type__, globalns, localns) + if new_tp == self.__type__: + return self + return type(self)(self.__name__, self.__bases__, + dict(self.__dict__), tp=self.__type__, + _root=True) + + def __repr__(self): + r = super().__repr__() + if self.__type__ is not None: + r += '[{}]'.format(typing._type_repr(self.__type__)) + return r + + def __hash__(self): + return hash((type(self).__name__, self.__type__)) + + def __eq__(self, other): + if not hasattr(other, "__type__"): + return NotImplemented + if self.__type__ is not None: + return self.__type__ == other.__type__ + return self is other + + class TypeGuard(typing.Final, metaclass=_TypeGuardMeta, _root=True): + """Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """ + __type__ = None