aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelle Zijlstra <jelle.zijlstra@gmail.com>2022-03-17 01:09:58 -0700
committerGitHub <noreply@github.com>2022-03-17 09:09:58 +0100
commit0ca0e458324ed27f96d81265faf94595f57d84af (patch)
treeea8ceab394926738436068772dde37c635772b94
parent95c9c2bab2034f0359e8457360d93a288a65e55d (diff)
downloadtyping-0ca0e458324ed27f96d81265faf94595f57d84af.tar.gz
typing-extensions: Drop Python 3.6 (#1104)
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--typing_extensions/CHANGELOG4
-rw-r--r--typing_extensions/README.rst9
-rw-r--r--typing_extensions/pyproject.toml2
-rw-r--r--typing_extensions/src/test_typing_extensions.py90
-rw-r--r--typing_extensions/src/typing_extensions.py1205
7 files changed, 108 insertions, 1206 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f0e6d67..302b2ca 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -18,7 +18,7 @@ jobs:
# Python version, because typing sometimes changed between bugfix releases.
# For available versions, see:
# https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json
- python-version: ["3.6", "3.6.7", "3.7", "3.7.1", "3.8", "3.8.0", "3.9", "3.9.0", "3.10", "3.10.0", "3.11-dev"]
+ python-version: ["3.7", "3.7.1", "3.8", "3.8.0", "3.9", "3.9.0", "3.10", "3.10.0", "3.11-dev"]
runs-on: ubuntu-latest
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 63c5034..095e826 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,7 +18,7 @@ standard library, so that users can experiment with them before they are added t
standard library. Such features should ideally already be specified in a PEP or draft
PEP.
-`typing_extensions` supports Python versions 3.6 and up.
+`typing_extensions` supports Python versions 3.7 and up.
# Versioning scheme
diff --git a/typing_extensions/CHANGELOG b/typing_extensions/CHANGELOG
index d27af29..f098464 100644
--- a/typing_extensions/CHANGELOG
+++ b/typing_extensions/CHANGELOG
@@ -1,3 +1,7 @@
+# Unreleased
+
+- Drop support for Python 3.6. Original patch by Adam Turner (@AA-Turner).
+
# Release 4.1.1 (February 13, 2022)
- Fix importing `typing_extensions` on Python 3.7.0 and 3.7.1. Original
diff --git a/typing_extensions/README.rst b/typing_extensions/README.rst
index 5db69d1..bb89068 100644
--- a/typing_extensions/README.rst
+++ b/typing_extensions/README.rst
@@ -30,6 +30,10 @@ Therefore, it's safe to depend
on ``typing_extensions`` like this: ``typing_extensions >=x.y, <(x+1)``,
where ``x.y`` is the first version that includes all features you need.
+``typing_extensions`` supports Python versions 3.7 and higher. In the future,
+support for older Python versions will be dropped some time after that version
+reaches end of life.
+
Included items
==============
@@ -101,7 +105,7 @@ This module currently contains the following:
- ``Text``
- ``Type``
- ``TYPE_CHECKING``
- - ``get_type_hints`` (``typing_extensions`` provides this function only in Python 3.7+)
+ - ``get_type_hints``
Other Notes and Limitations
===========================
@@ -131,9 +135,6 @@ versions of the typing module:
- ``ParamSpec`` and ``Concatenate`` will not work with ``get_args`` and
``get_origin``. Certain PEP 612 special cases in user-defined
``Generic``\ s are also not available.
-- ``Unpack`` from PEP 646 does not work properly with user-defined
- ``Generic``\ s in Python 3.6: ``class X(Generic[Unpack[Ts]]):`` does
- not work.
These types are only guaranteed to work for static type checking.
diff --git a/typing_extensions/pyproject.toml b/typing_extensions/pyproject.toml
index fd6e185..fbd0180 100644
--- a/typing_extensions/pyproject.toml
+++ b/typing_extensions/pyproject.toml
@@ -9,7 +9,7 @@ name = "typing_extensions"
version = "4.1.1"
description = "Backported and Experimental Type Hints for Python 3.6+"
readme = "README.rst"
-requires-python = ">=3.6"
+requires-python = ">=3.7"
urls.Home = "https://github.com/python/typing/blob/master/typing_extensions/README.rst"
license.file = "LICENSE"
keywords = [
diff --git a/typing_extensions/src/test_typing_extensions.py b/typing_extensions/src/test_typing_extensions.py
index a66a2f2..20e35f4 100644
--- a/typing_extensions/src/test_typing_extensions.py
+++ b/typing_extensions/src/test_typing_extensions.py
@@ -23,32 +23,14 @@ from typing_extensions import TypeAlias, ParamSpec, Concatenate, ParamSpecArgs,
from typing_extensions import Awaitable, AsyncIterator, AsyncContextManager, Required, NotRequired
from typing_extensions import Protocol, runtime, runtime_checkable, Annotated, overload, final, is_typeddict
from typing_extensions import TypeVarTuple, Unpack, dataclass_transform, reveal_type, Never, assert_never, LiteralString
-try:
- from typing_extensions import get_type_hints
-except ImportError:
- from typing import get_type_hints
-
-PEP_560 = sys.version_info[:3] >= (3, 7, 0)
-
-OLD_GENERICS = False
-try:
- from typing import _type_vars, _next_in_mro, _type_check # noqa
-except ImportError:
- OLD_GENERICS = True
+from typing_extensions import get_type_hints, get_origin, get_args
# Flags used to mark tests that only apply after a specific
# version of the typing module.
-TYPING_3_6_1 = sys.version_info[:3] >= (3, 6, 1)
TYPING_3_8_0 = sys.version_info[:3] >= (3, 8, 0)
TYPING_3_10_0 = sys.version_info[:3] >= (3, 10, 0)
TYPING_3_11_0 = sys.version_info[:3] >= (3, 11, 0)
-# For typing versions where instantiating collection
-# types are allowed.
-#
-# See https://github.com/python/typing/issues/367
-CAN_INSTANTIATE_COLLECTIONS = TYPING_3_6_1
-
class BaseTestCase(TestCase):
def assertIsSubclass(self, cls, class_or_tuple, msg=None):
@@ -78,9 +60,7 @@ class BottomTypeTestsMixin:
self.assertIs(self.bottom_type, self.bottom_type)
self.assertNotEqual(self.bottom_type, None)
- @skipUnless(PEP_560, "Python 3.7+ required")
def test_get_origin(self):
- from typing_extensions import get_origin
self.assertIs(get_origin(self.bottom_type), None)
def test_instance_type_error(self):
@@ -621,11 +601,8 @@ class GetTypeHintTests(BaseTestCase):
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')
Ts = TypeVarTuple('Ts')
@@ -655,8 +632,6 @@ class GetUtilitiesTestCase(TestCase):
self.assertIs(get_origin(Unpack), None)
def test_get_args(self):
- from typing_extensions import get_args
-
T = TypeVar('T')
Ts = TypeVarTuple('Ts')
class C(Generic[T]): pass
@@ -767,7 +742,6 @@ class CollectionsAbcTests(BaseTestCase):
def test_counter(self):
self.assertIsSubclass(collections.Counter, typing_extensions.Counter)
- @skipUnless(CAN_INSTANTIATE_COLLECTIONS, "Behavior added in typing 3.6.1")
def test_defaultdict_instantiation(self):
self.assertIs(
type(typing_extensions.DefaultDict()),
@@ -790,7 +764,6 @@ class CollectionsAbcTests(BaseTestCase):
self.assertIsSubclass(MyDefDict, collections.defaultdict)
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()),
@@ -844,10 +817,7 @@ class CollectionsAbcTests(BaseTestCase):
self.assertIs(type(typing_extensions.Counter[int]()), collections.Counter)
class C(typing_extensions.Counter[T]): ...
self.assertIs(type(C[int]()), C)
- if not PEP_560:
- self.assertEqual(C.__bases__, (typing_extensions.Counter,))
- else:
- self.assertEqual(C.__bases__, (collections.Counter, typing.Generic))
+ self.assertEqual(C.__bases__, (collections.Counter, typing.Generic))
def test_counter_subclass_instantiation(self):
@@ -922,9 +892,8 @@ class OtherABCTests(BaseTestCase):
cm = manager()
self.assertNotIsInstance(cm, typing_extensions.AsyncContextManager)
self.assertEqual(typing_extensions.AsyncContextManager[int].__args__, (int,))
- if TYPING_3_6_1:
- with self.assertRaises(TypeError):
- isinstance(42, typing_extensions.AsyncContextManager[int])
+ with self.assertRaises(TypeError):
+ isinstance(42, typing_extensions.AsyncContextManager[int])
with self.assertRaises(TypeError):
typing_extensions.AsyncContextManager[int, str]
@@ -1189,10 +1158,6 @@ class ProtocolTests(BaseTestCase):
self.assertIsSubclass(C, P)
self.assertIsSubclass(C, PG)
self.assertIsSubclass(BadP, PG)
- if not PEP_560:
- self.assertIsSubclass(PG[int], PG)
- self.assertIsSubclass(BadPG[int], P)
- self.assertIsSubclass(BadPG[T], PG)
with self.assertRaises(TypeError):
issubclass(C, PG[T])
with self.assertRaises(TypeError):
@@ -1383,7 +1348,6 @@ class ProtocolTests(BaseTestCase):
with self.assertRaises(TypeError):
issubclass(C(), P)
- @skipUnless(not OLD_GENERICS, "New style generics required")
def test_defining_generic_protocols(self):
T = TypeVar('T')
S = TypeVar('S')
@@ -1392,16 +1356,19 @@ class ProtocolTests(BaseTestCase):
def meth(self): pass
class P(PR[int, T], Protocol[T]):
y = 1
- self.assertIsSubclass(PR[int, T], PR)
- self.assertIsSubclass(P[str], PR)
with self.assertRaises(TypeError):
- PR[int]
+ issubclass(PR[int, T], PR)
with self.assertRaises(TypeError):
- P[int, str]
+ issubclass(P[str], PR)
with self.assertRaises(TypeError):
- PR[int, 1]
+ PR[int]
with self.assertRaises(TypeError):
- PR[int, ClassVar]
+ P[int, str]
+ if not TYPING_3_10_0:
+ with self.assertRaises(TypeError):
+ PR[int, 1]
+ with self.assertRaises(TypeError):
+ PR[int, ClassVar]
class C(PR[int, T]): pass
self.assertIsInstance(C[str](), C)
@@ -1413,11 +1380,8 @@ class ProtocolTests(BaseTestCase):
def meth(self): pass
class P(PR[int, str], Protocol):
y = 1
- if not PEP_560:
+ with self.assertRaises(TypeError):
self.assertIsSubclass(PR[int, str], PR)
- else:
- with self.assertRaises(TypeError):
- self.assertIsSubclass(PR[int, str], PR)
self.assertIsSubclass(P, PR)
with self.assertRaises(TypeError):
PR[int]
@@ -1448,7 +1412,6 @@ class ProtocolTests(BaseTestCase):
self.test = 'OK'
self.assertEqual(C[int]().test, 'OK')
- @skipUnless(not OLD_GENERICS, "New style generics required")
def test_protocols_bad_subscripts(self):
T = TypeVar('T')
S = TypeVar('S')
@@ -1465,9 +1428,6 @@ class ProtocolTests(BaseTestCase):
T = TypeVar('T')
S = TypeVar('S')
class P(Protocol[T, S]): pass
- # After PEP 560 unsubscripted generics have a standard repr.
- if not PEP_560:
- self.assertTrue(repr(P).endswith('P'))
self.assertTrue(repr(P[T, S]).endswith('P[~T, ~S]'))
self.assertTrue(repr(P[int, str]).endswith('P[int, str]'))
@@ -1480,13 +1440,10 @@ class ProtocolTests(BaseTestCase):
self.assertEqual(P[T, T][Tuple[T, S]][int, str],
P[Tuple[int, str], Tuple[int, str]])
- @skipUnless(not OLD_GENERICS, "New style generics required")
def test_generic_protocols_special_from_generic(self):
T = TypeVar('T')
class P(Protocol[T]): pass
self.assertEqual(P.__parameters__, (T,))
- self.assertIs(P.__args__, None)
- self.assertIs(P.__origin__, None)
self.assertEqual(P[int].__parameters__, ())
self.assertEqual(P[int].__args__, (int,))
self.assertIs(P[int].__origin__, P)
@@ -1517,9 +1474,6 @@ class ProtocolTests(BaseTestCase):
self.assertEqual(typing_extensions._get_protocol_attrs(PR), {'x'})
self.assertEqual(frozenset(typing_extensions._get_protocol_attrs(PG)),
frozenset({'x', 'meth'}))
- if not PEP_560:
- self.assertEqual(frozenset(typing_extensions._get_protocol_attrs(PG[int])),
- frozenset({'x', 'meth'}))
def test_no_runtime_deco_on_nominal(self):
with self.assertRaises(TypeError):
@@ -1747,7 +1701,6 @@ class TypedDictTests(BaseTestCase):
assert Point2Dor3D.__required_keys__ == frozenset(['x', 'y'])
assert Point2Dor3D.__optional_keys__ == frozenset(['z'])
- @skipUnless(PEP_560, "runtime support for Required and NotRequired requires PEP 560")
def test_required_notrequired_keys(self):
assert NontotalMovie.__required_keys__ == frozenset({'title'})
assert NontotalMovie.__optional_keys__ == frozenset({'year'})
@@ -1821,16 +1774,14 @@ class AnnotatedTests(BaseTestCase):
A = Annotated[Annotated[int, 4], 5]
self.assertEqual(A, Annotated[int, 4, 5])
self.assertEqual(A.__metadata__, (4, 5))
- if PEP_560:
- self.assertEqual(A.__origin__, int)
+ self.assertEqual(A.__origin__, int)
def test_specialize(self):
L = Annotated[List[T], "my decoration"]
LI = Annotated[List[int], "my decoration"]
self.assertEqual(L[int], Annotated[List[int], "my decoration"])
self.assertEqual(L[int].__metadata__, ("my decoration",))
- if PEP_560:
- self.assertEqual(L[int].__origin__, List[int])
+ self.assertEqual(L[int].__origin__, List[int])
with self.assertRaises(TypeError):
LI[int]
with self.assertRaises(TypeError):
@@ -1934,7 +1885,6 @@ class AnnotatedTests(BaseTestCase):
with self.assertRaises(TypeError):
issubclass(int, Annotated[int, "positive"])
- @skipUnless(PEP_560, "pickle support was added with PEP 560")
def test_pickle(self):
samples = [typing.Any, typing.Union[int, str],
typing.Optional[str], Tuple[int, ...],
@@ -2000,7 +1950,6 @@ class AnnotatedTests(BaseTestCase):
self.assertEqual(X[int], List[Annotated[int, 5]])
-@skipUnless(PEP_560, "Python 3.7 required")
class GetTypeHintsTests(BaseTestCase):
def test_get_type_hints(self):
def foobar(x: List['X']): ...
@@ -2355,9 +2304,7 @@ class LiteralStringTests(BaseTestCase):
self.assertEqual(gth(Foo.bar), {'return': LiteralString})
self.assertEqual(gth(Foo.baz), {'return': LiteralString})
- @skipUnless(PEP_560, "Python 3.7+ required")
def test_get_origin(self):
- from typing_extensions import get_origin
self.assertIsNone(get_origin(LiteralString))
def test_repr(self):
@@ -2510,7 +2457,6 @@ class UnpackTests(BaseTestCase):
Union
)
- @skipUnless(PEP_560, "Unimplemented for 3.6")
def test_concatenation(self):
Xs = TypeVarTuple('Xs')
self.assertEqual(Tuple[int, Unpack[Xs]].__args__, (int, Unpack[Xs]))
@@ -2523,7 +2469,6 @@ class UnpackTests(BaseTestCase):
self.assertEqual(C[int, Unpack[Xs], str].__args__,
(int, Unpack[Xs], str))
- @skipUnless(PEP_560, "Unimplemented for 3.6")
def test_class(self):
Ts = TypeVarTuple('Ts')
@@ -2766,8 +2711,7 @@ class AllTests(BaseTestCase):
self.assertIn("Concatenate", a)
self.assertIn('Annotated', a)
- if PEP_560:
- self.assertIn('get_type_hints', a)
+ self.assertIn('get_type_hints', a)
self.assertIn('Awaitable', a)
self.assertIn('AsyncIterator', a)
diff --git a/typing_extensions/src/typing_extensions.py b/typing_extensions/src/typing_extensions.py
index 194731c..5c43354 100644
--- a/typing_extensions/src/typing_extensions.py
+++ b/typing_extensions/src/typing_extensions.py
@@ -6,17 +6,6 @@ import sys
import types as _types
import typing
-# After PEP 560, internal typing API was substantially reworked.
-# This is especially important for Protocol class which uses internal APIs
-# quite extensively.
-PEP_560 = sys.version_info[:3] >= (3, 7, 0)
-
-if PEP_560:
- GenericMeta = type
-else:
- # 3.6
- from typing import GenericMeta, _type_vars # noqa
-
# Please keep __all__ alphabetized within each category.
__all__ = [
@@ -56,6 +45,9 @@ __all__ = [
'assert_never',
'dataclass_transform',
'final',
+ 'get_args',
+ 'get_origin',
+ 'get_type_hints',
'IntVar',
'is_typeddict',
'Literal',
@@ -75,21 +67,13 @@ __all__ = [
'NotRequired',
]
-if PEP_560:
- __all__.extend(["get_args", "get_origin", "get_type_hints"])
+# for backward compatibility
+PEP_560 = True
+GenericMeta = type
# The functions below are modified copies of typing internal helpers.
# They are needed by _ProtocolMeta and they provide support for PEP 646.
-
-def _no_slots_copy(dct):
- dict_copy = dict(dct)
- if '__slots__' in dict_copy:
- for slot in dict_copy['__slots__']:
- dict_copy.pop(slot, None)
- return dict_copy
-
-
_marker = object()
@@ -148,32 +132,7 @@ def _collect_type_vars(types, typevar_types=None):
return tuple(tvars)
-# 3.6.2+
-if hasattr(typing, 'NoReturn'):
- NoReturn = typing.NoReturn
-# 3.6.0-3.6.1
-else:
- class _NoReturn(typing._FinalTypingBase, _root=True):
- """Special type indicating functions that never return.
- Example::
-
- from typing import NoReturn
-
- def stop() -> NoReturn:
- raise Exception('no way')
-
- This type is invalid in other positions, e.g., ``List[NoReturn]``
- will fail in static type checkers.
- """
- __slots__ = ()
-
- def __instancecheck__(self, obj):
- raise TypeError("NoReturn cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError("NoReturn cannot be used with issubclass().")
-
- NoReturn = _NoReturn(_root=True)
+NoReturn = typing.NoReturn
# Some unconstrained type variables. These are used by the container types.
# (These are not for export.)
@@ -190,7 +149,7 @@ ClassVar = typing.ClassVar
if hasattr(typing, 'Final') and sys.version_info[:2] >= (3, 7):
Final = typing.Final
# 3.7
-elif sys.version_info[:2] >= (3, 7):
+else:
class _FinalForm(typing._SpecialForm, _root=True):
def __repr__(self):
@@ -215,61 +174,6 @@ elif sys.version_info[:2] >= (3, 7):
TIMEOUT = 1 # Error reported by type checker
There is no runtime checking of these properties.""")
-# 3.6
-else:
- class _Final(typing._FinalTypingBase, _root=True):
- """A special typing construct to indicate that a name
- cannot be re-assigned or overridden in a subclass.
- For example:
-
- MAX_SIZE: Final = 9000
- MAX_SIZE += 1 # Error reported by type checker
-
- class Connection:
- TIMEOUT: Final[int] = 10
- class FastConnector(Connection):
- TIMEOUT = 1 # Error reported by type checker
-
- There is no runtime checking of these properties.
- """
-
- __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,
- f'{cls.__name__[1:]} accepts only single type.'),
- _root=True)
- raise TypeError(f'{cls.__name__[1:]} cannot be further subscripted')
-
- 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 += f'[{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, _Final):
- return NotImplemented
- if self.__type__ is not None:
- return self.__type__ == other.__type__
- return self is other
-
- Final = _Final(_root=True)
-
if sys.version_info >= (3, 11):
final = typing.final
@@ -317,7 +221,7 @@ def IntVar(name):
if hasattr(typing, 'Literal'):
Literal = typing.Literal
# 3.7:
-elif sys.version_info[:2] >= (3, 7):
+else:
class _LiteralForm(typing._SpecialForm, _root=True):
def __repr__(self):
@@ -339,55 +243,6 @@ elif sys.version_info[:2] >= (3, 7):
Literal[...] cannot be subclassed. There is no runtime
checking verifying that the parameter is actually a value
instead of a type.""")
-# 3.6:
-else:
- class _Literal(typing._FinalTypingBase, _root=True):
- """A type that can be used to indicate to type checkers that the
- corresponding value has a value literally equivalent to the
- provided parameter. For example:
-
- var: Literal[4] = 4
-
- The type checker understands that 'var' is literally equal to the
- value 4 and no other value.
-
- Literal[...] cannot be subclassed. There is no runtime checking
- verifying that the parameter is actually a value instead of a type.
- """
-
- __slots__ = ('__values__',)
-
- def __init__(self, values=None, **kwds):
- self.__values__ = values
-
- def __getitem__(self, values):
- cls = type(self)
- if self.__values__ is None:
- if not isinstance(values, tuple):
- values = (values,)
- return cls(values, _root=True)
- raise TypeError(f'{cls.__name__[1:]} cannot be further subscripted')
-
- def _eval_type(self, globalns, localns):
- return self
-
- def __repr__(self):
- r = super().__repr__()
- if self.__values__ is not None:
- r += f'[{", ".join(map(typing._type_repr, self.__values__))}]'
- return r
-
- def __hash__(self):
- return hash((type(self).__name__, self.__values__))
-
- def __eq__(self, other):
- if not isinstance(other, _Literal):
- return NotImplemented
- if self.__values__ is not None:
- return self.__values__ == other.__values__
- return self is other
-
- Literal = _Literal(_root=True)
_overload_dummy = typing._overload_dummy # noqa
@@ -401,154 +256,30 @@ Type = typing.Type
# A few are simply re-exported for completeness.
-class _ExtensionsGenericMeta(GenericMeta):
- def __subclasscheck__(self, subclass):
- """This mimics a more modern GenericMeta.__subclasscheck__() logic
- (that does not have problems with recursion) to work around interactions
- between collections, typing, and typing_extensions on older
- versions of Python, see https://github.com/python/typing/issues/501.
- """
- if self.__origin__ is not None:
- if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']:
- raise TypeError("Parameterized generics cannot be used with class "
- "or instance checks")
- return False
- if not self.__extra__:
- return super().__subclasscheck__(subclass)
- res = self.__extra__.__subclasshook__(subclass)
- if res is not NotImplemented:
- return res
- if self.__extra__ in subclass.__mro__:
- return True
- for scls in self.__extra__.__subclasses__():
- if isinstance(scls, GenericMeta):
- continue
- if issubclass(subclass, scls):
- return True
- return False
-
-
Awaitable = typing.Awaitable
Coroutine = typing.Coroutine
AsyncIterable = typing.AsyncIterable
AsyncIterator = typing.AsyncIterator
-
-# 3.6.1+
-if hasattr(typing, 'Deque'):
- Deque = typing.Deque
-# 3.6.0
-else:
- class Deque(collections.deque, typing.MutableSequence[T],
- metaclass=_ExtensionsGenericMeta,
- extra=collections.deque):
- __slots__ = ()
-
- def __new__(cls, *args, **kwds):
- if cls._gorg is Deque:
- return collections.deque(*args, **kwds)
- return typing._generic_new(collections.deque, cls, *args, **kwds)
-
+Deque = typing.Deque
ContextManager = typing.ContextManager
-# 3.6.2+
-if hasattr(typing, 'AsyncContextManager'):
- AsyncContextManager = typing.AsyncContextManager
-# 3.6.0-3.6.1
-else:
- from _collections_abc import _check_methods as _check_methods_in_mro # noqa
-
- class AsyncContextManager(typing.Generic[T_co]):
- __slots__ = ()
-
- async def __aenter__(self):
- return self
-
- @abc.abstractmethod
- async def __aexit__(self, exc_type, exc_value, traceback):
- return None
-
- @classmethod
- def __subclasshook__(cls, C):
- if cls is AsyncContextManager:
- return _check_methods_in_mro(C, "__aenter__", "__aexit__")
- return NotImplemented
-
+AsyncContextManager = typing.AsyncContextManager
DefaultDict = typing.DefaultDict
# 3.7.2+
if hasattr(typing, 'OrderedDict'):
OrderedDict = typing.OrderedDict
# 3.7.0-3.7.2
-elif (3, 7, 0) <= sys.version_info[:3] < (3, 7, 2):
- OrderedDict = typing._alias(collections.OrderedDict, (KT, VT))
-# 3.6
-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 typing._generic_new(collections.OrderedDict, cls, *args, **kwds)
-
-# 3.6.2+
-if hasattr(typing, 'Counter'):
- Counter = typing.Counter
-# 3.6.0-3.6.1
-else:
- class Counter(collections.Counter,
- typing.Dict[T, int],
- metaclass=_ExtensionsGenericMeta, extra=collections.Counter):
-
- __slots__ = ()
-
- def __new__(cls, *args, **kwds):
- if cls._gorg is Counter:
- return collections.Counter(*args, **kwds)
- return typing._generic_new(collections.Counter, cls, *args, **kwds)
-
-# 3.6.1+
-if hasattr(typing, 'ChainMap'):
- ChainMap = typing.ChainMap
-elif hasattr(collections, 'ChainMap'):
- class ChainMap(collections.ChainMap, typing.MutableMapping[KT, VT],
- metaclass=_ExtensionsGenericMeta,
- extra=collections.ChainMap):
-
- __slots__ = ()
-
- def __new__(cls, *args, **kwds):
- if cls._gorg is ChainMap:
- return collections.ChainMap(*args, **kwds)
- return typing._generic_new(collections.ChainMap, cls, *args, **kwds)
-
-# 3.6.1+
-if hasattr(typing, 'AsyncGenerator'):
- AsyncGenerator = typing.AsyncGenerator
-# 3.6.0
else:
- class AsyncGenerator(AsyncIterator[T_co], typing.Generic[T_co, T_contra],
- metaclass=_ExtensionsGenericMeta,
- extra=collections.abc.AsyncGenerator):
- __slots__ = ()
+ OrderedDict = typing._alias(collections.OrderedDict, (KT, VT))
+Counter = typing.Counter
+ChainMap = typing.ChainMap
+AsyncGenerator = typing.AsyncGenerator
NewType = typing.NewType
Text = typing.Text
TYPE_CHECKING = typing.TYPE_CHECKING
-def _gorg(cls):
- """This function exists for compatibility with old typing versions."""
- assert isinstance(cls, GenericMeta)
- if hasattr(cls, '_gorg'):
- return cls._gorg
- while cls.__origin__ is not None:
- cls = cls.__origin__
- return cls
-
-
_PROTO_WHITELIST = ['Callable', 'Awaitable',
'Iterable', 'Iterator', 'AsyncIterable', 'AsyncIterator',
'Hashable', 'Sized', 'Container', 'Collection', 'Reversible',
@@ -582,7 +313,7 @@ def _is_callable_members_only(cls):
if hasattr(typing, 'Protocol'):
Protocol = typing.Protocol
# 3.7
-elif PEP_560:
+else:
def _no_init(self, *args, **kwargs):
if type(self)._is_protocol:
@@ -764,250 +495,12 @@ elif PEP_560:
raise TypeError('Protocols can only inherit from other'
f' protocols, got {repr(base)}')
cls.__init__ = _no_init
-# 3.6
-else:
- from typing import _next_in_mro, _type_check # noqa
-
- def _no_init(self, *args, **kwargs):
- if type(self)._is_protocol:
- raise TypeError('Protocols cannot be instantiated')
-
- class _ProtocolMeta(GenericMeta):
- """Internal metaclass for Protocol.
-
- This exists so Protocol classes can be generic without deriving
- from Generic.
- """
- def __new__(cls, name, bases, namespace,
- tvars=None, args=None, origin=None, extra=None, orig_bases=None):
- # This is just a version copied from GenericMeta.__new__ that
- # includes "Protocol" special treatment. (Comments removed for brevity.)
- assert extra is None # Protocols should not have extra
- if tvars is not None:
- assert origin is not None
- assert all(isinstance(t, typing.TypeVar) for t in tvars), tvars
- else:
- tvars = _type_vars(bases)
- gvars = None
- for base in bases:
- if base is typing.Generic:
- raise TypeError("Cannot inherit from plain Generic")
- if (isinstance(base, GenericMeta) and
- base.__origin__ in (typing.Generic, Protocol)):
- if gvars is not None:
- raise TypeError(
- "Cannot inherit from Generic[...] or"
- " Protocol[...] multiple times.")
- gvars = base.__parameters__
- if gvars is None:
- gvars = tvars
- else:
- tvarset = set(tvars)
- gvarset = set(gvars)
- if not tvarset <= gvarset:
- s_vars = ", ".join(str(t) for t in tvars if t not in gvarset)
- s_args = ", ".join(str(g) for g in gvars)
- cls_name = "Generic" if any(b.__origin__ is typing.Generic
- for b in bases) else "Protocol"
- raise TypeError(f"Some type variables ({s_vars}) are"
- f" not listed in {cls_name}[{s_args}]")
- tvars = gvars
-
- initial_bases = bases
- if (extra is not None and type(extra) is abc.ABCMeta and
- extra not in bases):
- bases = (extra,) + bases
- bases = tuple(_gorg(b) if isinstance(b, GenericMeta) else b
- for b in bases)
- if any(isinstance(b, GenericMeta) and b is not typing.Generic for b in bases):
- bases = tuple(b for b in bases if b is not typing.Generic)
- namespace.update({'__origin__': origin, '__extra__': extra})
- self = super(GenericMeta, cls).__new__(cls, name, bases, namespace,
- _root=True)
- super(GenericMeta, self).__setattr__('_gorg',
- self if not origin else
- _gorg(origin))
- self.__parameters__ = tvars
- self.__args__ = tuple(... if a is typing._TypingEllipsis else
- () if a is typing._TypingEmpty else
- a for a in args) if args else None
- self.__next_in_mro__ = _next_in_mro(self)
- if orig_bases is None:
- self.__orig_bases__ = initial_bases
- elif origin is not None:
- self._abc_registry = origin._abc_registry
- self._abc_cache = origin._abc_cache
- if hasattr(self, '_subs_tree'):
- self.__tree_hash__ = (hash(self._subs_tree()) if origin else
- super(GenericMeta, self).__hash__())
- return self
-
- def __init__(cls, *args, **kwargs):
- super().__init__(*args, **kwargs)
- if not cls.__dict__.get('_is_protocol', None):
- cls._is_protocol = any(b is Protocol or
- isinstance(b, _ProtocolMeta) and
- b.__origin__ is Protocol
- for b in cls.__bases__)
- if cls._is_protocol:
- for base in cls.__mro__[1:]:
- if not (base in (object, typing.Generic) or
- base.__module__ == 'collections.abc' and
- base.__name__ in _PROTO_WHITELIST or
- isinstance(base, typing.TypingMeta) and base._is_protocol or
- isinstance(base, GenericMeta) and
- base.__origin__ is typing.Generic):
- raise TypeError(f'Protocols can only inherit from other'
- f' protocols, got {repr(base)}')
-
- cls.__init__ = _no_init
-
- def _proto_hook(other):
- if not cls.__dict__.get('_is_protocol', None):
- return NotImplemented
- if not isinstance(other, type):
- # Same error as for issubclass(1, int)
- raise TypeError('issubclass() arg 1 must be a class')
- for attr in _get_protocol_attrs(cls):
- for base in other.__mro__:
- if attr in base.__dict__:
- if base.__dict__[attr] is None:
- return NotImplemented
- break
- annotations = getattr(base, '__annotations__', {})
- if (isinstance(annotations, typing.Mapping) and
- attr in annotations and
- isinstance(other, _ProtocolMeta) and
- other._is_protocol):
- break
- else:
- return NotImplemented
- return True
- if '__subclasshook__' not in cls.__dict__:
- cls.__subclasshook__ = _proto_hook
-
- def __instancecheck__(self, instance):
- # We need this method for situations where attributes are
- # assigned in __init__.
- if ((not getattr(self, '_is_protocol', False) or
- _is_callable_members_only(self)) and
- issubclass(instance.__class__, self)):
- return True
- if self._is_protocol:
- if all(hasattr(instance, attr) and
- (not callable(getattr(self, attr, None)) or
- getattr(instance, attr) is not None)
- for attr in _get_protocol_attrs(self)):
- return True
- return super(GenericMeta, self).__instancecheck__(instance)
-
- def __subclasscheck__(self, cls):
- if self.__origin__ is not None:
- if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']:
- raise TypeError("Parameterized generics cannot be used with class "
- "or instance checks")
- return False
- if (self.__dict__.get('_is_protocol', None) and
- not self.__dict__.get('_is_runtime_protocol', None)):
- if sys._getframe(1).f_globals['__name__'] in ['abc',
- 'functools',
- 'typing']:
- return False
- raise TypeError("Instance and class checks can only be used with"
- " @runtime protocols")
- if (self.__dict__.get('_is_runtime_protocol', None) and
- not _is_callable_members_only(self)):
- if sys._getframe(1).f_globals['__name__'] in ['abc',
- 'functools',
- 'typing']:
- return super(GenericMeta, self).__subclasscheck__(cls)
- raise TypeError("Protocols with non-method members"
- " don't support issubclass()")
- return super(GenericMeta, self).__subclasscheck__(cls)
-
- @typing._tp_cache
- def __getitem__(self, params):
- # We also need to copy this from GenericMeta.__getitem__ to get
- # special treatment of "Protocol". (Comments removed for brevity.)
- if not isinstance(params, tuple):
- params = (params,)
- if not params and _gorg(self) is not typing.Tuple:
- raise TypeError(
- f"Parameter list to {self.__qualname__}[...] cannot be empty")
- msg = "Parameters to generic types must be types."
- params = tuple(_type_check(p, msg) for p in params)
- if self in (typing.Generic, Protocol):
- if not all(isinstance(p, typing.TypeVar) for p in params):
- raise TypeError(
- f"Parameters to {repr(self)}[...] must all be type variables")
- if len(set(params)) != len(params):
- raise TypeError(
- f"Parameters to {repr(self)}[...] must all be unique")
- tvars = params
- args = params
- elif self in (typing.Tuple, typing.Callable):
- tvars = _type_vars(params)
- args = params
- elif self.__origin__ in (typing.Generic, Protocol):
- raise TypeError(f"Cannot subscript already-subscripted {repr(self)}")
- else:
- _check_generic(self, params, len(self.__parameters__))
- tvars = _type_vars(params)
- args = params
-
- prepend = (self,) if self.__origin__ is None else ()
- return self.__class__(self.__name__,
- prepend + self.__bases__,
- _no_slots_copy(self.__dict__),
- tvars=tvars,
- args=args,
- origin=self,
- extra=self.__extra__,
- orig_bases=self.__orig_bases__)
-
- class Protocol(metaclass=_ProtocolMeta):
- """Base class for protocol classes. Protocol classes are defined as::
-
- class Proto(Protocol):
- def meth(self) -> int:
- ...
-
- Such classes are primarily used with static type checkers that recognize
- structural subtyping (static duck-typing), for example::
-
- class C:
- def meth(self) -> int:
- return 0
-
- def func(x: Proto) -> int:
- return x.meth()
-
- func(C()) # Passes static type check
-
- See PEP 544 for details. Protocol classes decorated with
- @typing_extensions.runtime act as simple-minded runtime protocol that checks
- only the presence of given attributes, ignoring their type signatures.
-
- Protocol classes can be generic, they are defined as::
-
- class GenProto(Protocol[T]):
- def meth(self) -> T:
- ...
- """
- __slots__ = ()
- _is_protocol = True
-
- def __new__(cls, *args, **kwds):
- if _gorg(cls) is Protocol:
- raise TypeError("Type Protocol cannot be instantiated; "
- "it can be used only as a base class")
- return typing._generic_new(cls.__next_in_mro__, cls, *args, **kwds)
# 3.8+
if hasattr(typing, 'runtime_checkable'):
runtime_checkable = typing.runtime_checkable
-# 3.6-3.7
+# 3.7
else:
def runtime_checkable(cls):
"""Mark a protocol class as a runtime protocol, so that it
@@ -1031,7 +524,7 @@ runtime = runtime_checkable
# 3.8+
if hasattr(typing, 'SupportsIndex'):
SupportsIndex = typing.SupportsIndex
-# 3.6-3.7
+# 3.7
else:
@runtime_checkable
class SupportsIndex(Protocol):
@@ -1148,29 +641,22 @@ else:
optional_keys.update(base.__dict__.get('__optional_keys__', ()))
annotations.update(own_annotations)
- if PEP_560:
- for annotation_key, annotation_type in own_annotations.items():
- annotation_origin = get_origin(annotation_type)
- if annotation_origin is Annotated:
- annotation_args = get_args(annotation_type)
- if annotation_args:
- annotation_type = annotation_args[0]
- annotation_origin = get_origin(annotation_type)
-
- if annotation_origin is Required:
- required_keys.add(annotation_key)
- elif annotation_origin is NotRequired:
- optional_keys.add(annotation_key)
- elif total:
- required_keys.add(annotation_key)
- else:
- optional_keys.add(annotation_key)
- else:
- own_annotation_keys = set(own_annotations.keys())
- if total:
- required_keys.update(own_annotation_keys)
+ for annotation_key, annotation_type in own_annotations.items():
+ annotation_origin = get_origin(annotation_type)
+ if annotation_origin is Annotated:
+ annotation_args = get_args(annotation_type)
+ if annotation_args:
+ annotation_type = annotation_args[0]
+ annotation_origin = get_origin(annotation_type)
+
+ if annotation_origin is Required:
+ required_keys.add(annotation_key)
+ elif annotation_origin is NotRequired:
+ optional_keys.add(annotation_key)
+ elif total:
+ required_keys.add(annotation_key)
else:
- optional_keys.update(own_annotation_keys)
+ optional_keys.add(annotation_key)
tp_dict.__annotations__ = annotations
tp_dict.__required_keys__ = frozenset(required_keys)
@@ -1233,7 +719,7 @@ else:
if hasattr(typing, "Required"):
get_type_hints = typing.get_type_hints
-elif PEP_560:
+else:
import functools
import types
@@ -1312,7 +798,7 @@ if hasattr(typing, 'Annotated'):
# to work.
_AnnotatedAlias = typing._AnnotatedAlias
# 3.7-3.8
-elif PEP_560:
+else:
class _AnnotatedAlias(typing._GenericAlias, _root=True):
"""Runtime representation of an annotated type.
@@ -1409,152 +895,6 @@ elif PEP_560:
raise TypeError(
f"Cannot subclass {cls.__module__}.Annotated"
)
-# 3.6
-else:
-
- def _is_dunder(name):
- """Returns True if name is a __dunder_variable_name__."""
- return len(name) > 4 and name.startswith('__') and name.endswith('__')
-
- # Prior to Python 3.7 types did not have `copy_with`. A lot of the equality
- # checks, argument expansion etc. are done on the _subs_tre. As a result we
- # can't provide a get_type_hints function that strips out annotations.
-
- class AnnotatedMeta(typing.GenericMeta):
- """Metaclass for Annotated"""
-
- def __new__(cls, name, bases, namespace, **kwargs):
- if any(b is not object for b in bases):
- raise TypeError("Cannot subclass " + str(Annotated))
- return super().__new__(cls, name, bases, namespace, **kwargs)
-
- @property
- def __metadata__(self):
- return self._subs_tree()[2]
-
- def _tree_repr(self, tree):
- cls, origin, metadata = tree
- if not isinstance(origin, tuple):
- tp_repr = typing._type_repr(origin)
- else:
- tp_repr = origin[0]._tree_repr(origin)
- metadata_reprs = ", ".join(repr(arg) for arg in metadata)
- return f'{cls}[{tp_repr}, {metadata_reprs}]'
-
- def _subs_tree(self, tvars=None, args=None): # noqa
- if self is Annotated:
- return Annotated
- res = super()._subs_tree(tvars=tvars, args=args)
- # Flatten nested Annotated
- if isinstance(res[1], tuple) and res[1][0] is Annotated:
- sub_tp = res[1][1]
- sub_annot = res[1][2]
- return (Annotated, sub_tp, sub_annot + res[2])
- return res
-
- def _get_cons(self):
- """Return the class used to create instance of this type."""
- if self.__origin__ is None:
- raise TypeError("Cannot get the underlying type of a "
- "non-specialized Annotated type.")
- tree = self._subs_tree()
- while isinstance(tree, tuple) and tree[0] is Annotated:
- tree = tree[1]
- if isinstance(tree, tuple):
- return tree[0]
- else:
- return tree
-
- @typing._tp_cache
- def __getitem__(self, params):
- if not isinstance(params, tuple):
- params = (params,)
- if self.__origin__ is not None: # specializing an instantiated type
- return super().__getitem__(params)
- elif not isinstance(params, tuple) or len(params) < 2:
- raise TypeError("Annotated[...] should be instantiated "
- "with at least two arguments (a type and an "
- "annotation).")
- else:
- if (
- isinstance(params[0], typing._TypingBase) and
- type(params[0]).__name__ == "_ClassVar"
- ):
- tp = params[0]
- else:
- msg = "Annotated[t, ...]: t must be a type."
- tp = typing._type_check(params[0], msg)
- metadata = tuple(params[1:])
- return self.__class__(
- self.__name__,
- self.__bases__,
- _no_slots_copy(self.__dict__),
- tvars=_type_vars((tp,)),
- # Metadata is a tuple so it won't be touched by _replace_args et al.
- args=(tp, metadata),
- origin=self,
- )
-
- def __call__(self, *args, **kwargs):
- cons = self._get_cons()
- result = cons(*args, **kwargs)
- try:
- result.__orig_class__ = self
- except AttributeError:
- pass
- return result
-
- def __getattr__(self, attr):
- # For simplicity we just don't relay all dunder names
- if self.__origin__ is not None and not _is_dunder(attr):
- return getattr(self._get_cons(), attr)
- raise AttributeError(attr)
-
- def __setattr__(self, attr, value):
- if _is_dunder(attr) or attr.startswith('_abc_'):
- super().__setattr__(attr, value)
- elif self.__origin__ is None:
- raise AttributeError(attr)
- else:
- setattr(self._get_cons(), attr, value)
-
- def __instancecheck__(self, obj):
- raise TypeError("Annotated cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError("Annotated cannot be used with issubclass().")
-
- class Annotated(metaclass=AnnotatedMeta):
- """Add context specific metadata to a type.
-
- Example: Annotated[int, runtime_check.Unsigned] indicates to the
- hypothetical runtime_check module that this type is an unsigned int.
- Every other consumer of this type can ignore this metadata and treat
- this type as int.
-
- The first argument to Annotated must be a valid type, the remaining
- arguments are kept as a tuple in the __metadata__ field.
-
- Details:
-
- - It's an error to call `Annotated` with less than two arguments.
- - Nested Annotated are flattened::
-
- Annotated[Annotated[T, Ann1, Ann2], Ann3] == Annotated[T, Ann1, Ann2, Ann3]
-
- - Instantiating an annotated type is equivalent to instantiating the
- underlying type::
-
- Annotated[C, Ann1](5) == C(5)
-
- - Annotated can be used as a generic type alias::
-
- Optimized = Annotated[T, runtime.Optimize()]
- Optimized[int] == Annotated[int, runtime.Optimize()]
-
- OptimizedList = Annotated[List[T], runtime.Optimize()]
- OptimizedList[int] == Annotated[List[int], runtime.Optimize()]
- """
# Python 3.8 has get_origin() and get_args() but those implementations aren't
# Annotated-aware, so we can't use those. Python 3.9's versions don't support
@@ -1563,7 +903,7 @@ if sys.version_info[:2] >= (3, 10):
get_origin = typing.get_origin
get_args = typing.get_args
# 3.7-3.9
-elif PEP_560:
+else:
try:
# 3.9+
from typing import _BaseGenericAlias
@@ -1645,7 +985,7 @@ elif sys.version_info[:2] >= (3, 9):
"""
raise TypeError(f"{self} is not subscriptable")
# 3.7-3.8
-elif sys.version_info[:2] >= (3, 7):
+else:
class _TypeAliasForm(typing._SpecialForm, _root=True):
def __repr__(self):
return 'typing_extensions.' + self._name
@@ -1661,44 +1001,13 @@ elif sys.version_info[:2] >= (3, 7):
It's invalid when used anywhere except as in the example
above.""")
-# 3.6
-else:
- class _TypeAliasMeta(typing.TypingMeta):
- """Metaclass for TypeAlias"""
-
- def __repr__(self):
- return 'typing_extensions.TypeAlias'
-
- class _TypeAliasBase(typing._FinalTypingBase, metaclass=_TypeAliasMeta, _root=True):
- """Special marker indicating that an assignment should
- be recognized as a proper type alias definition by type
- checkers.
-
- For example::
-
- Predicate: TypeAlias = Callable[..., bool]
-
- It's invalid when used anywhere except as in the example above.
- """
- __slots__ = ()
-
- 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 __repr__(self):
- return 'typing_extensions.TypeAlias'
-
- TypeAlias = _TypeAliasBase(_root=True)
# Python 3.10+ has PEP 612
if hasattr(typing, 'ParamSpecArgs'):
ParamSpecArgs = typing.ParamSpecArgs
ParamSpecKwargs = typing.ParamSpecKwargs
-# 3.6-3.9
+# 3.7-3.9
else:
class _Immutable:
"""Mixin to indicate that object should not be copied."""
@@ -1759,7 +1068,7 @@ else:
# 3.10+
if hasattr(typing, 'ParamSpec'):
ParamSpec = typing.ParamSpec
-# 3.6-3.9
+# 3.7-3.9
else:
# Inherits from list as a workaround for Callable checks in Python < 3.9.2.
@@ -1861,28 +1170,17 @@ else:
def __call__(self, *args, **kwargs):
pass
- if not PEP_560:
- # Only needed in 3.6.
- def _get_type_vars(self, tvars):
- if self not in tvars:
- tvars.append(self)
-
-# 3.6-3.9
+# 3.7-3.9
if not hasattr(typing, 'Concatenate'):
# 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
- else:
- __class__ = typing._TypingBase
+ __class__ = typing._GenericAlias
# Flag in 3.8.
_special = False
- # Attribute in 3.6 and earlier.
- _gorg = typing.Generic
def __init__(self, origin, args):
super().__init__(args)
@@ -1907,14 +1205,8 @@ if not hasattr(typing, 'Concatenate'):
tp for tp in self.__args__ if isinstance(tp, (typing.TypeVar, ParamSpec))
)
- if not PEP_560:
- # Only required in 3.6.
- def _get_type_vars(self, tvars):
- if self.__origin__ and self.__parameters__:
- typing._get_type_vars(self.__parameters__, tvars)
-
-# 3.6-3.9
+# 3.7-3.9
@typing._tp_cache
def _concatenate_getitem(self, parameters):
if parameters == ():
@@ -1949,7 +1241,7 @@ elif sys.version_info[:2] >= (3, 9):
"""
return _concatenate_getitem(self, parameters)
# 3.7-8
-elif sys.version_info[:2] >= (3, 7):
+else:
class _ConcatenateForm(typing._SpecialForm, _root=True):
def __repr__(self):
return 'typing_extensions.' + self._name
@@ -1969,42 +1261,6 @@ elif sys.version_info[:2] >= (3, 7):
See PEP 612 for detailed information.
""")
-# 3.6
-else:
- 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)
# 3.10+
if hasattr(typing, 'TypeGuard'):
@@ -2062,7 +1318,7 @@ elif sys.version_info[:2] >= (3, 9):
item = typing._type_check(parameters, f'{self} accepts only single type.')
return typing._GenericAlias(self, (item,))
# 3.7-3.8
-elif sys.version_info[:2] >= (3, 7):
+else:
class _TypeGuardForm(typing._SpecialForm, _root=True):
def __repr__(self):
@@ -2117,138 +1373,55 @@ elif sys.version_info[:2] >= (3, 7):
``TypeGuard`` also works with type variables. For more information, see
PEP 647 (User-Defined Type Guards).
""")
-# 3.6
-else:
- 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__',)
+# Vendored from cpython typing._SpecialFrom
+class _SpecialForm(typing._Final, _root=True):
+ __slots__ = ('_name', '__doc__', '_getitem')
- def __init__(self, tp=None, **kwds):
- self.__type__ = tp
+ def __init__(self, getitem):
+ self._getitem = getitem
+ self._name = getitem.__name__
+ self.__doc__ = getitem.__doc__
- def __getitem__(self, item):
- cls = type(self)
- if self.__type__ is None:
- return cls(typing._type_check(item,
- f'{cls.__name__[1:]} accepts only a single type.'),
- _root=True)
- raise TypeError(f'{cls.__name__[1:]} cannot be further subscripted')
-
- 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 += f'[{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)
-
-
-if sys.version_info[:2] >= (3, 7):
- # Vendored from cpython typing._SpecialFrom
- class _SpecialForm(typing._Final, _root=True):
- __slots__ = ('_name', '__doc__', '_getitem')
-
- def __init__(self, getitem):
- self._getitem = getitem
- self._name = getitem.__name__
- self.__doc__ = getitem.__doc__
-
- def __getattr__(self, item):
- if item in {'__name__', '__qualname__'}:
- return self._name
+ def __getattr__(self, item):
+ if item in {'__name__', '__qualname__'}:
+ return self._name
- raise AttributeError(item)
+ raise AttributeError(item)
- def __mro_entries__(self, bases):
- raise TypeError(f"Cannot subclass {self!r}")
+ def __mro_entries__(self, bases):
+ raise TypeError(f"Cannot subclass {self!r}")
- def __repr__(self):
- return f'typing_extensions.{self._name}'
+ def __repr__(self):
+ return f'typing_extensions.{self._name}'
- def __reduce__(self):
- return self._name
+ def __reduce__(self):
+ return self._name
- def __call__(self, *args, **kwds):
- raise TypeError(f"Cannot instantiate {self!r}")
+ def __call__(self, *args, **kwds):
+ raise TypeError(f"Cannot instantiate {self!r}")
- def __or__(self, other):
- return typing.Union[self, other]
+ def __or__(self, other):
+ return typing.Union[self, other]
- def __ror__(self, other):
- return typing.Union[other, self]
+ def __ror__(self, other):
+ return typing.Union[other, self]
- def __instancecheck__(self, obj):
- raise TypeError(f"{self} cannot be used with isinstance()")
+ def __instancecheck__(self, obj):
+ raise TypeError(f"{self} cannot be used with isinstance()")
- def __subclasscheck__(self, cls):
- raise TypeError(f"{self} cannot be used with issubclass()")
+ def __subclasscheck__(self, cls):
+ raise TypeError(f"{self} cannot be used with issubclass()")
- @typing._tp_cache
- def __getitem__(self, parameters):
- return self._getitem(self, parameters)
+ @typing._tp_cache
+ def __getitem__(self, parameters):
+ return self._getitem(self, parameters)
if hasattr(typing, "LiteralString"):
LiteralString = typing.LiteralString
-elif sys.version_info[:2] >= (3, 7):
+else:
@_SpecialForm
def LiteralString(self, params):
"""Represents an arbitrary literal string.
@@ -2267,38 +1440,11 @@ elif sys.version_info[:2] >= (3, 7):
"""
raise TypeError(f"{self} is not subscriptable")
-else:
- class _LiteralString(typing._FinalTypingBase, _root=True):
- """Represents an arbitrary literal string.
-
- Example::
-
- from typing_extensions import LiteralString
-
- def query(sql: LiteralString) -> ...:
- ...
-
- query("SELECT * FROM table") # ok
- query(f"SELECT * FROM {input()}") # not ok
-
- See PEP 675 for details.
-
- """
-
- __slots__ = ()
-
- def __instancecheck__(self, obj):
- raise TypeError(f"{self} cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError(f"{self} cannot be used with issubclass().")
-
- LiteralString = _LiteralString(_root=True)
if hasattr(typing, "Self"):
Self = typing.Self
-elif sys.version_info[:2] >= (3, 7):
+else:
@_SpecialForm
def Self(self, params):
"""Used to spell the type of "self" in classes.
@@ -2315,35 +1461,11 @@ elif sys.version_info[:2] >= (3, 7):
"""
raise TypeError(f"{self} is not subscriptable")
-else:
- class _Self(typing._FinalTypingBase, _root=True):
- """Used to spell the type of "self" in classes.
-
- Example::
-
- from typing import Self
-
- class ReturnsSelf:
- def parse(self, data: bytes) -> Self:
- ...
- return self
-
- """
-
- __slots__ = ()
-
- def __instancecheck__(self, obj):
- raise TypeError(f"{self} cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError(f"{self} cannot be used with issubclass().")
-
- Self = _Self(_root=True)
if hasattr(typing, "Never"):
Never = typing.Never
-elif sys.version_info[:2] >= (3, 7):
+else:
@_SpecialForm
def Never(self, params):
"""The bottom type, a type that has no members.
@@ -2369,39 +1491,6 @@ elif sys.version_info[:2] >= (3, 7):
"""
raise TypeError(f"{self} is not subscriptable")
-else:
- class _Never(typing._FinalTypingBase, _root=True):
- """The bottom type, a type that has no members.
-
- This can be used to define a function that should never be
- called, or a function that never returns::
-
- from typing_extensions import Never
-
- def never_call_me(arg: Never) -> None:
- pass
-
- def int_or_str(arg: int | str) -> None:
- never_call_me(arg) # type checker error
- match arg:
- case int():
- print("It's an int")
- case str():
- print("It's a str")
- case _:
- never_call_me(arg) # ok, arg is of type Never
-
- """
-
- __slots__ = ()
-
- def __instancecheck__(self, obj):
- raise TypeError(f"{self} cannot be used with isinstance().")
-
- def __subclasscheck__(self, cls):
- raise TypeError(f"{self} cannot be used with issubclass().")
-
- Never = _Never(_root=True)
if hasattr(typing, 'Required'):
@@ -2449,7 +1538,7 @@ elif sys.version_info[:2] >= (3, 9):
item = typing._type_check(parameters, f'{self._name} accepts only single type')
return typing._GenericAlias(self, (item,))
-elif sys.version_info[:2] >= (3, 7):
+else:
class _RequiredForm(typing._SpecialForm, _root=True):
def __repr__(self):
return 'typing_extensions.' + self._name
@@ -2490,78 +1579,6 @@ elif sys.version_info[:2] >= (3, 7):
year=1999,
)
""")
-else:
- # NOTE: Modeled after _Final's implementation when _FinalTypingBase available
- class _MaybeRequired(typing._FinalTypingBase, _root=True):
- __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 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, type(self)):
- return NotImplemented
- if self.__type__ is not None:
- return self.__type__ == other.__type__
- return self is other
-
- class _Required(_MaybeRequired, _root=True):
- """A special typing construct to mark a key of a total=False TypedDict
- as required. For example:
-
- class Movie(TypedDict, total=False):
- title: Required[str]
- year: int
-
- m = Movie(
- title='The Matrix', # typechecker error if key is omitted
- year=1999,
- )
-
- There is no runtime checking that a required key is actually provided
- when instantiating a related TypedDict.
- """
-
- class _NotRequired(_MaybeRequired, _root=True):
- """A special typing construct to mark a key of a TypedDict as
- potentially missing. For example:
-
- class Movie(TypedDict):
- title: str
- year: NotRequired[int]
-
- m = Movie(
- title='The Matrix', # typechecker error if key is omitted
- year=1999,
- )
- """
-
- Required = _Required(_root=True)
- NotRequired = _NotRequired(_root=True)
if sys.version_info[:2] >= (3, 9):
@@ -2590,7 +1607,7 @@ if sys.version_info[:2] >= (3, 9):
def _is_unpack(obj):
return isinstance(obj, _UnpackAlias)
-elif sys.version_info[:2] >= (3, 7):
+else:
class _UnpackAlias(typing._GenericAlias, _root=True):
__class__ = typing.TypeVar
@@ -2619,64 +1636,6 @@ elif sys.version_info[:2] >= (3, 7):
def _is_unpack(obj):
return isinstance(obj, _UnpackAlias)
-else:
- # NOTE: Modeled after _Final's implementation when _FinalTypingBase available
- class _Unpack(typing._FinalTypingBase, _root=True):
- """A special typing construct to unpack a variadic type. For example:
-
- Shape = TypeVarTuple('Shape')
- Batch = NewType('Batch', int)
-
- def add_batch_axis(
- x: Array[Unpack[Shape]]
- ) -> Array[Batch, Unpack[Shape]]: ...
-
- """
- __slots__ = ('__type__',)
- __class__ = typing.TypeVar
-
- 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,
- 'Unpack accepts only single type.'),
- _root=True)
- raise TypeError('Unpack cannot be further subscripted')
-
- 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, _Unpack):
- return NotImplemented
- if self.__type__ is not None:
- return self.__type__ == other.__type__
- return self is other
-
- # For 3.6 only
- def _get_type_vars(self, tvars):
- self.__type__._get_type_vars(tvars)
-
- Unpack = _Unpack(_root=True)
-
- def _is_unpack(obj):
- return isinstance(obj, _Unpack)
-
class TypeVarTuple:
"""Type variable tuple.
@@ -2757,12 +1716,6 @@ class TypeVarTuple:
if '_root' not in kwds:
raise TypeError("Cannot subclass special typing classes")
- if not PEP_560:
- # Only needed in 3.6.
- def _get_type_vars(self, tvars):
- if self not in tvars:
- tvars.append(self)
-
if hasattr(typing, "reveal_type"):
reveal_type = typing.reveal_type