Many changes from the upstream repo (https://github.com/python/typing).
This syncs to rev 7b43ada77821d23e55e3a4b35f6055a59b9e1ad7 there. Summary: - Add typing.DefaultDict (as a generic variant of collections.defaultdict). - Use collections.Reversible if it exists (only relevant for Python 3.6). - Revamped generic class behavior to conform to updated PEP 484. - Improve speed of Generic.__new__. - Make sure __init__ is called for new Generic instances. Fix issue #26391. - Refactor async support to be compatible with 3.2, 3.3, 3.4. - Remove 'io' and 're' from __all__ (they still exist, just not included by "import *"). Fix issue #26234. - Change @overload -- you can now use it outside stubs (you still cannot call the decorated function though).
This commit is contained in:
parent
0f7673943a
commit
bd5b9a0742
|
@ -1,8 +1,7 @@
|
||||||
import asyncio
|
|
||||||
import pickle
|
import pickle
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from unittest import TestCase, main
|
from unittest import TestCase, main, skipUnless
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import TypeVar, AnyStr
|
from typing import TypeVar, AnyStr
|
||||||
|
@ -133,6 +132,7 @@ class TypeVarTests(TestCase):
|
||||||
def test_constrained_error(self):
|
def test_constrained_error(self):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
X = TypeVar('X', int)
|
X = TypeVar('X', int)
|
||||||
|
X
|
||||||
|
|
||||||
def test_union_unique(self):
|
def test_union_unique(self):
|
||||||
X = TypeVar('X')
|
X = TypeVar('X')
|
||||||
|
@ -317,6 +317,7 @@ class UnionTests(TestCase):
|
||||||
def test_union_str_pattern(self):
|
def test_union_str_pattern(self):
|
||||||
# Shouldn't crash; see http://bugs.python.org/issue25390
|
# Shouldn't crash; see http://bugs.python.org/issue25390
|
||||||
A = Union[str, Pattern]
|
A = Union[str, Pattern]
|
||||||
|
A
|
||||||
|
|
||||||
|
|
||||||
class TypeVarUnionTests(TestCase):
|
class TypeVarUnionTests(TestCase):
|
||||||
|
@ -487,7 +488,7 @@ class SimpleMapping(Generic[XK, XV]):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
class MySimpleMapping(SimpleMapping):
|
class MySimpleMapping(SimpleMapping[XK, XV]):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.store = {}
|
self.store = {}
|
||||||
|
@ -541,6 +542,7 @@ class ProtocolTests(TestCase):
|
||||||
assert not issubclass(str, typing.SupportsAbs)
|
assert not issubclass(str, typing.SupportsAbs)
|
||||||
|
|
||||||
def test_supports_round(self):
|
def test_supports_round(self):
|
||||||
|
issubclass(float, typing.SupportsRound)
|
||||||
assert issubclass(float, typing.SupportsRound)
|
assert issubclass(float, typing.SupportsRound)
|
||||||
assert issubclass(int, typing.SupportsRound)
|
assert issubclass(int, typing.SupportsRound)
|
||||||
assert not issubclass(str, typing.SupportsRound)
|
assert not issubclass(str, typing.SupportsRound)
|
||||||
|
@ -551,20 +553,23 @@ class ProtocolTests(TestCase):
|
||||||
|
|
||||||
def test_protocol_instance_type_error(self):
|
def test_protocol_instance_type_error(self):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
isinstance([], typing.Reversible)
|
isinstance(0, typing.SupportsAbs)
|
||||||
|
|
||||||
|
|
||||||
class GenericTests(TestCase):
|
class GenericTests(TestCase):
|
||||||
|
|
||||||
def test_basics(self):
|
def test_basics(self):
|
||||||
X = SimpleMapping[str, Any]
|
X = SimpleMapping[str, Any]
|
||||||
|
assert X.__parameters__ == ()
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
X[str]
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
X[str, str]
|
||||||
Y = SimpleMapping[XK, str]
|
Y = SimpleMapping[XK, str]
|
||||||
X[str, str]
|
assert Y.__parameters__ == (XK,)
|
||||||
Y[str, str]
|
Y[str]
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
X[int, str]
|
Y[str, str]
|
||||||
with self.assertRaises(TypeError):
|
|
||||||
Y[str, bytes]
|
|
||||||
|
|
||||||
def test_init(self):
|
def test_init(self):
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
|
@ -576,30 +581,61 @@ class GenericTests(TestCase):
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
self.assertEqual(repr(SimpleMapping),
|
self.assertEqual(repr(SimpleMapping),
|
||||||
__name__ + '.' + 'SimpleMapping[~XK, ~XV]')
|
__name__ + '.' + 'SimpleMapping<~XK, ~XV>')
|
||||||
self.assertEqual(repr(MySimpleMapping),
|
self.assertEqual(repr(MySimpleMapping),
|
||||||
__name__ + '.' + 'MySimpleMapping[~XK, ~XV]')
|
__name__ + '.' + 'MySimpleMapping<~XK, ~XV>')
|
||||||
|
|
||||||
|
def test_chain_repr(self):
|
||||||
|
T = TypeVar('T')
|
||||||
|
S = TypeVar('S')
|
||||||
|
|
||||||
|
class C(Generic[T]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
X = C[Tuple[S, T]]
|
||||||
|
assert X == C[Tuple[S, T]]
|
||||||
|
assert X != C[Tuple[T, S]]
|
||||||
|
|
||||||
|
Y = X[T, int]
|
||||||
|
assert Y == X[T, int]
|
||||||
|
assert Y != X[S, int]
|
||||||
|
assert Y != X[T, str]
|
||||||
|
|
||||||
|
Z = Y[str]
|
||||||
|
assert Z == Y[str]
|
||||||
|
assert Z != Y[int]
|
||||||
|
assert Z != Y[T]
|
||||||
|
|
||||||
|
assert str(Z).endswith(
|
||||||
|
'.C<~T>[typing.Tuple[~S, ~T]]<~S, ~T>[~T, int]<~T>[str]')
|
||||||
|
|
||||||
def test_dict(self):
|
def test_dict(self):
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
|
|
||||||
class B(Generic[T]):
|
class B(Generic[T]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
b = B()
|
b = B()
|
||||||
b.foo = 42
|
b.foo = 42
|
||||||
self.assertEqual(b.__dict__, {'foo': 42})
|
self.assertEqual(b.__dict__, {'foo': 42})
|
||||||
|
|
||||||
class C(B[int]):
|
class C(B[int]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
c = C()
|
c = C()
|
||||||
c.bar = 'abc'
|
c.bar = 'abc'
|
||||||
self.assertEqual(c.__dict__, {'bar': 'abc'})
|
self.assertEqual(c.__dict__, {'bar': 'abc'})
|
||||||
|
|
||||||
def test_pickle(self):
|
def test_pickle(self):
|
||||||
|
global C # pickle wants to reference the class by name
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
|
|
||||||
class B(Generic[T]):
|
class B(Generic[T]):
|
||||||
pass
|
pass
|
||||||
global C # pickle wants to reference the class by name
|
|
||||||
class C(B[int]):
|
class C(B[int]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
c = C()
|
c = C()
|
||||||
c.foo = 42
|
c.foo = 42
|
||||||
c.bar = 'abc'
|
c.bar = 'abc'
|
||||||
|
@ -626,12 +662,12 @@ class GenericTests(TestCase):
|
||||||
assert C.__module__ == __name__
|
assert C.__module__ == __name__
|
||||||
if not PY32:
|
if not PY32:
|
||||||
assert C.__qualname__ == 'GenericTests.test_repr_2.<locals>.C'
|
assert C.__qualname__ == 'GenericTests.test_repr_2.<locals>.C'
|
||||||
assert repr(C).split('.')[-1] == 'C[~T]'
|
assert repr(C).split('.')[-1] == 'C<~T>'
|
||||||
X = C[int]
|
X = C[int]
|
||||||
assert X.__module__ == __name__
|
assert X.__module__ == __name__
|
||||||
if not PY32:
|
if not PY32:
|
||||||
assert X.__qualname__ == 'C'
|
assert X.__qualname__ == 'C'
|
||||||
assert repr(X).split('.')[-1] == 'C[int]'
|
assert repr(X).split('.')[-1] == 'C<~T>[int]'
|
||||||
|
|
||||||
class Y(C[int]):
|
class Y(C[int]):
|
||||||
pass
|
pass
|
||||||
|
@ -639,7 +675,7 @@ class GenericTests(TestCase):
|
||||||
assert Y.__module__ == __name__
|
assert Y.__module__ == __name__
|
||||||
if not PY32:
|
if not PY32:
|
||||||
assert Y.__qualname__ == 'GenericTests.test_repr_2.<locals>.Y'
|
assert Y.__qualname__ == 'GenericTests.test_repr_2.<locals>.Y'
|
||||||
assert repr(Y).split('.')[-1] == 'Y[int]'
|
assert repr(Y).split('.')[-1] == 'Y'
|
||||||
|
|
||||||
def test_eq_1(self):
|
def test_eq_1(self):
|
||||||
assert Generic == Generic
|
assert Generic == Generic
|
||||||
|
@ -667,15 +703,14 @@ class GenericTests(TestCase):
|
||||||
class B(Generic[KT, T]):
|
class B(Generic[KT, T]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class C(A, Generic[KT, VT], B):
|
class C(A[T, VT], Generic[VT, T, KT], B[KT, T]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
assert C.__parameters__ == (T, VT, KT)
|
assert C.__parameters__ == (VT, T, KT)
|
||||||
|
|
||||||
def test_nested(self):
|
def test_nested(self):
|
||||||
|
|
||||||
class G(Generic):
|
G = Generic
|
||||||
pass
|
|
||||||
|
|
||||||
class Visitor(G[T]):
|
class Visitor(G[T]):
|
||||||
|
|
||||||
|
@ -721,9 +756,30 @@ class GenericTests(TestCase):
|
||||||
assert type(a) is Node
|
assert type(a) is Node
|
||||||
assert type(b) is Node
|
assert type(b) is Node
|
||||||
assert type(c) is Node
|
assert type(c) is Node
|
||||||
|
assert a.label == x
|
||||||
|
assert b.label == x
|
||||||
|
assert c.label == x
|
||||||
|
|
||||||
foo(42)
|
foo(42)
|
||||||
|
|
||||||
|
def test_implicit_any(self):
|
||||||
|
T = TypeVar('T')
|
||||||
|
|
||||||
|
class C(Generic[T]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class D(C):
|
||||||
|
pass
|
||||||
|
|
||||||
|
assert D.__parameters__ == ()
|
||||||
|
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
D[int]
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
D[Any]
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
D[T]
|
||||||
|
|
||||||
|
|
||||||
class VarianceTests(TestCase):
|
class VarianceTests(TestCase):
|
||||||
|
|
||||||
|
@ -956,14 +1012,33 @@ class OverloadTests(TestCase):
|
||||||
from typing import overload
|
from typing import overload
|
||||||
|
|
||||||
with self.assertRaises(RuntimeError):
|
with self.assertRaises(RuntimeError):
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def blah():
|
def blah():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
blah()
|
||||||
|
|
||||||
|
def test_overload_succeeds(self):
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def blah():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def blah():
|
||||||
|
pass
|
||||||
|
|
||||||
|
blah()
|
||||||
|
|
||||||
|
|
||||||
|
PY35 = sys.version_info[:2] >= (3, 5)
|
||||||
|
|
||||||
|
PY35_TESTS = """
|
||||||
|
import asyncio
|
||||||
|
|
||||||
T_a = TypeVar('T')
|
T_a = TypeVar('T')
|
||||||
|
|
||||||
|
|
||||||
class AwaitableWrapper(typing.Awaitable[T_a]):
|
class AwaitableWrapper(typing.Awaitable[T_a]):
|
||||||
|
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
|
@ -973,7 +1048,6 @@ class AwaitableWrapper(typing.Awaitable[T_a]):
|
||||||
yield
|
yield
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
|
|
||||||
class AsyncIteratorWrapper(typing.AsyncIterator[T_a]):
|
class AsyncIteratorWrapper(typing.AsyncIterator[T_a]):
|
||||||
|
|
||||||
def __init__(self, value: typing.Iterable[T_a]):
|
def __init__(self, value: typing.Iterable[T_a]):
|
||||||
|
@ -989,6 +1063,10 @@ class AsyncIteratorWrapper(typing.AsyncIterator[T_a]):
|
||||||
return data
|
return data
|
||||||
else:
|
else:
|
||||||
raise StopAsyncIteration
|
raise StopAsyncIteration
|
||||||
|
"""
|
||||||
|
|
||||||
|
if PY35:
|
||||||
|
exec(PY35_TESTS)
|
||||||
|
|
||||||
|
|
||||||
class CollectionsAbcTests(TestCase):
|
class CollectionsAbcTests(TestCase):
|
||||||
|
@ -1015,9 +1093,14 @@ class CollectionsAbcTests(TestCase):
|
||||||
assert isinstance(it, typing.Iterator[int])
|
assert isinstance(it, typing.Iterator[int])
|
||||||
assert not isinstance(42, typing.Iterator)
|
assert not isinstance(42, typing.Iterator)
|
||||||
|
|
||||||
|
@skipUnless(PY35, 'Python 3.5 required')
|
||||||
def test_awaitable(self):
|
def test_awaitable(self):
|
||||||
async def foo() -> typing.Awaitable[int]:
|
ns = {}
|
||||||
return await AwaitableWrapper(42)
|
exec(
|
||||||
|
"async def foo() -> typing.Awaitable[int]:\n"
|
||||||
|
" return await AwaitableWrapper(42)\n",
|
||||||
|
globals(), ns)
|
||||||
|
foo = ns['foo']
|
||||||
g = foo()
|
g = foo()
|
||||||
assert issubclass(type(g), typing.Awaitable[int])
|
assert issubclass(type(g), typing.Awaitable[int])
|
||||||
assert isinstance(g, typing.Awaitable)
|
assert isinstance(g, typing.Awaitable)
|
||||||
|
@ -1028,6 +1111,7 @@ class CollectionsAbcTests(TestCase):
|
||||||
typing.Awaitable[Manager])
|
typing.Awaitable[Manager])
|
||||||
g.send(None) # Run foo() till completion, to avoid warning.
|
g.send(None) # Run foo() till completion, to avoid warning.
|
||||||
|
|
||||||
|
@skipUnless(PY35, 'Python 3.5 required')
|
||||||
def test_async_iterable(self):
|
def test_async_iterable(self):
|
||||||
base_it = range(10) # type: Iterator[int]
|
base_it = range(10) # type: Iterator[int]
|
||||||
it = AsyncIteratorWrapper(base_it)
|
it = AsyncIteratorWrapper(base_it)
|
||||||
|
@ -1037,6 +1121,7 @@ class CollectionsAbcTests(TestCase):
|
||||||
typing.AsyncIterable[Employee])
|
typing.AsyncIterable[Employee])
|
||||||
assert not isinstance(42, typing.AsyncIterable)
|
assert not isinstance(42, typing.AsyncIterable)
|
||||||
|
|
||||||
|
@skipUnless(PY35, 'Python 3.5 required')
|
||||||
def test_async_iterator(self):
|
def test_async_iterator(self):
|
||||||
base_it = range(10) # type: Iterator[int]
|
base_it = range(10) # type: Iterator[int]
|
||||||
it = AsyncIteratorWrapper(base_it)
|
it = AsyncIteratorWrapper(base_it)
|
||||||
|
@ -1127,6 +1212,22 @@ class CollectionsAbcTests(TestCase):
|
||||||
d = MyDict()
|
d = MyDict()
|
||||||
assert isinstance(d, MyDict)
|
assert isinstance(d, MyDict)
|
||||||
|
|
||||||
|
def test_no_defaultdict_instantiation(self):
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
typing.DefaultDict()
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
typing.DefaultDict[KT, VT]()
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
typing.DefaultDict[str, int]()
|
||||||
|
|
||||||
|
def test_defaultdict_subclass_instantiation(self):
|
||||||
|
|
||||||
|
class MyDefDict(typing.DefaultDict[str, int]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
dd = MyDefDict()
|
||||||
|
assert isinstance(dd, MyDefDict)
|
||||||
|
|
||||||
def test_no_set_instantiation(self):
|
def test_no_set_instantiation(self):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
typing.Set()
|
typing.Set()
|
||||||
|
@ -1251,7 +1352,7 @@ class IOTests(TestCase):
|
||||||
return a.readline()
|
return a.readline()
|
||||||
|
|
||||||
a = stuff.__annotations__['a']
|
a = stuff.__annotations__['a']
|
||||||
assert a.__parameters__ == (str,)
|
assert a.__parameters__ == ()
|
||||||
|
|
||||||
def test_binaryio(self):
|
def test_binaryio(self):
|
||||||
|
|
||||||
|
@ -1259,7 +1360,7 @@ class IOTests(TestCase):
|
||||||
return a.readline()
|
return a.readline()
|
||||||
|
|
||||||
a = stuff.__annotations__['a']
|
a = stuff.__annotations__['a']
|
||||||
assert a.__parameters__ == (bytes,)
|
assert a.__parameters__ == ()
|
||||||
|
|
||||||
def test_io_submodule(self):
|
def test_io_submodule(self):
|
||||||
from typing.io import IO, TextIO, BinaryIO, __all__, __name__
|
from typing.io import IO, TextIO, BinaryIO, __all__, __name__
|
||||||
|
@ -1346,8 +1447,9 @@ class AllTests(TestCase):
|
||||||
assert 'ValuesView' in a
|
assert 'ValuesView' in a
|
||||||
assert 'cast' in a
|
assert 'cast' in a
|
||||||
assert 'overload' in a
|
assert 'overload' in a
|
||||||
assert 'io' in a
|
# Check that io and re are not exported.
|
||||||
assert 're' in a
|
assert 'io' not in a
|
||||||
|
assert 're' not in a
|
||||||
# Spot-check that stdlib modules aren't exported.
|
# Spot-check that stdlib modules aren't exported.
|
||||||
assert 'os' not in a
|
assert 'os' not in a
|
||||||
assert 'sys' not in a
|
assert 'sys' not in a
|
||||||
|
|
396
Lib/typing.py
396
Lib/typing.py
|
@ -1,7 +1,3 @@
|
||||||
# TODO nits:
|
|
||||||
# Get rid of asserts that are the caller's fault.
|
|
||||||
# Docstrings (e.g. ABCs).
|
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
from abc import abstractmethod, abstractproperty
|
from abc import abstractmethod, abstractproperty
|
||||||
import collections
|
import collections
|
||||||
|
@ -56,6 +52,7 @@ __all__ = [
|
||||||
|
|
||||||
# Concrete collection types.
|
# Concrete collection types.
|
||||||
'Dict',
|
'Dict',
|
||||||
|
'DefaultDict',
|
||||||
'List',
|
'List',
|
||||||
'Set',
|
'Set',
|
||||||
'NamedTuple', # Not really a type.
|
'NamedTuple', # Not really a type.
|
||||||
|
@ -68,12 +65,12 @@ __all__ = [
|
||||||
'no_type_check',
|
'no_type_check',
|
||||||
'no_type_check_decorator',
|
'no_type_check_decorator',
|
||||||
'overload',
|
'overload',
|
||||||
|
|
||||||
# Submodules.
|
|
||||||
'io',
|
|
||||||
're',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# The pseudo-submodules 're' and 'io' are part of the public
|
||||||
|
# namespace, but excluded from __all__ because they might stomp on
|
||||||
|
# legitimate imports of those modules.
|
||||||
|
|
||||||
|
|
||||||
def _qualname(x):
|
def _qualname(x):
|
||||||
if sys.version_info[:2] >= (3, 3):
|
if sys.version_info[:2] >= (3, 3):
|
||||||
|
@ -117,8 +114,8 @@ class TypingMeta(type):
|
||||||
"""
|
"""
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _has_type_var(self):
|
def _get_type_vars(self, tvars):
|
||||||
return False
|
pass
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s.%s' % (self.__module__, _qualname(self))
|
return '%s.%s' % (self.__module__, _qualname(self))
|
||||||
|
@ -214,8 +211,8 @@ class _TypeAlias:
|
||||||
someone tries to subclass a type alias (not a good idea).
|
someone tries to subclass a type alias (not a good idea).
|
||||||
"""
|
"""
|
||||||
if (len(args) == 3 and
|
if (len(args) == 3 and
|
||||||
isinstance(args[0], str) and
|
isinstance(args[0], str) and
|
||||||
isinstance(args[1], tuple)):
|
isinstance(args[1], tuple)):
|
||||||
# Close enough.
|
# Close enough.
|
||||||
raise TypeError("A type alias cannot be subclassed")
|
raise TypeError("A type alias cannot be subclassed")
|
||||||
return object.__new__(cls)
|
return object.__new__(cls)
|
||||||
|
@ -271,8 +268,16 @@ class _TypeAlias:
|
||||||
return issubclass(cls, self.impl_type)
|
return issubclass(cls, self.impl_type)
|
||||||
|
|
||||||
|
|
||||||
def _has_type_var(t):
|
def _get_type_vars(types, tvars):
|
||||||
return t is not None and isinstance(t, TypingMeta) and t._has_type_var()
|
for t in types:
|
||||||
|
if isinstance(t, TypingMeta):
|
||||||
|
t._get_type_vars(tvars)
|
||||||
|
|
||||||
|
|
||||||
|
def _type_vars(types):
|
||||||
|
tvars = []
|
||||||
|
_get_type_vars(types, tvars)
|
||||||
|
return tuple(tvars)
|
||||||
|
|
||||||
|
|
||||||
def _eval_type(t, globalns, localns):
|
def _eval_type(t, globalns, localns):
|
||||||
|
@ -376,7 +381,7 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True):
|
||||||
At runtime, isinstance(x, T) will raise TypeError. However,
|
At runtime, isinstance(x, T) will raise TypeError. However,
|
||||||
issubclass(C, T) is true for any class C, and issubclass(str, A)
|
issubclass(C, T) is true for any class C, and issubclass(str, A)
|
||||||
and issubclass(bytes, A) are true, and issubclass(int, A) is
|
and issubclass(bytes, A) are true, and issubclass(int, A) is
|
||||||
false.
|
false. (TODO: Why is this needed? This may change. See #136.)
|
||||||
|
|
||||||
Type variables may be marked covariant or contravariant by passing
|
Type variables may be marked covariant or contravariant by passing
|
||||||
covariant=True or contravariant=True. See PEP 484 for more
|
covariant=True or contravariant=True. See PEP 484 for more
|
||||||
|
@ -410,8 +415,9 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True):
|
||||||
self.__bound__ = None
|
self.__bound__ = None
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _has_type_var(self):
|
def _get_type_vars(self, tvars):
|
||||||
return True
|
if self not in tvars:
|
||||||
|
tvars.append(self)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if self.__covariant__:
|
if self.__covariant__:
|
||||||
|
@ -448,7 +454,6 @@ VT_co = TypeVar('VT_co', covariant=True) # Value type covariant containers.
|
||||||
T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant.
|
T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant.
|
||||||
|
|
||||||
# A useful type variable with constraints. This represents string types.
|
# A useful type variable with constraints. This represents string types.
|
||||||
# TODO: What about bytearray, memoryview?
|
|
||||||
AnyStr = TypeVar('AnyStr', bytes, str)
|
AnyStr = TypeVar('AnyStr', bytes, str)
|
||||||
|
|
||||||
|
|
||||||
|
@ -514,12 +519,9 @@ class UnionMeta(TypingMeta):
|
||||||
return self.__class__(self.__name__, self.__bases__, {},
|
return self.__class__(self.__name__, self.__bases__, {},
|
||||||
p, _root=True)
|
p, _root=True)
|
||||||
|
|
||||||
def _has_type_var(self):
|
def _get_type_vars(self, tvars):
|
||||||
if self.__union_params__:
|
if self.__union_params__:
|
||||||
for t in self.__union_params__:
|
_get_type_vars(self.__union_params__, tvars)
|
||||||
if _has_type_var(t):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
r = super().__repr__()
|
r = super().__repr__()
|
||||||
|
@ -656,12 +658,9 @@ class TupleMeta(TypingMeta):
|
||||||
self.__tuple_use_ellipsis__ = use_ellipsis
|
self.__tuple_use_ellipsis__ = use_ellipsis
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _has_type_var(self):
|
def _get_type_vars(self, tvars):
|
||||||
if self.__tuple_params__:
|
if self.__tuple_params__:
|
||||||
for t in self.__tuple_params__:
|
_get_type_vars(self.__tuple_params__, tvars)
|
||||||
if _has_type_var(t):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _eval_type(self, globalns, localns):
|
def _eval_type(self, globalns, localns):
|
||||||
tp = self.__tuple_params__
|
tp = self.__tuple_params__
|
||||||
|
@ -769,12 +768,9 @@ class CallableMeta(TypingMeta):
|
||||||
self.__result__ = result
|
self.__result__ = result
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _has_type_var(self):
|
def _get_type_vars(self, tvars):
|
||||||
if self.__args__:
|
if self.__args__:
|
||||||
for t in self.__args__:
|
_get_type_vars(self.__args__, tvars)
|
||||||
if _has_type_var(t):
|
|
||||||
return True
|
|
||||||
return _has_type_var(self.__result__)
|
|
||||||
|
|
||||||
def _eval_type(self, globalns, localns):
|
def _eval_type(self, globalns, localns):
|
||||||
if self.__args__ is None and self.__result__ is None:
|
if self.__args__ is None and self.__result__ is None:
|
||||||
|
@ -878,76 +874,106 @@ def _geqv(a, b):
|
||||||
return _gorg(a) is _gorg(b)
|
return _gorg(a) is _gorg(b)
|
||||||
|
|
||||||
|
|
||||||
|
def _next_in_mro(cls):
|
||||||
|
"""Helper for Generic.__new__.
|
||||||
|
|
||||||
|
Returns the class after the last occurrence of Generic or
|
||||||
|
Generic[...] in cls.__mro__.
|
||||||
|
"""
|
||||||
|
next_in_mro = object
|
||||||
|
# Look for the last occurrence of Generic or Generic[...].
|
||||||
|
for i, c in enumerate(cls.__mro__[:-1]):
|
||||||
|
if isinstance(c, GenericMeta) and _gorg(c) is Generic:
|
||||||
|
next_in_mro = cls.__mro__[i+1]
|
||||||
|
return next_in_mro
|
||||||
|
|
||||||
|
|
||||||
class GenericMeta(TypingMeta, abc.ABCMeta):
|
class GenericMeta(TypingMeta, abc.ABCMeta):
|
||||||
"""Metaclass for generic types."""
|
"""Metaclass for generic types."""
|
||||||
|
|
||||||
# TODO: Constrain more how Generic is used; only a few
|
|
||||||
# standard patterns should be allowed.
|
|
||||||
|
|
||||||
# TODO: Use a more precise rule than matching __name__ to decide
|
|
||||||
# whether two classes are the same. Also, save the formal
|
|
||||||
# parameters. (These things are related! A solution lies in
|
|
||||||
# using origin.)
|
|
||||||
|
|
||||||
__extra__ = None
|
__extra__ = None
|
||||||
|
|
||||||
def __new__(cls, name, bases, namespace,
|
def __new__(cls, name, bases, namespace,
|
||||||
parameters=None, origin=None, extra=None):
|
tvars=None, args=None, origin=None, extra=None):
|
||||||
if parameters is None:
|
|
||||||
# Extract parameters from direct base classes. Only
|
|
||||||
# direct bases are considered and only those that are
|
|
||||||
# themselves generic, and parameterized with type
|
|
||||||
# variables. Don't use bases like Any, Union, Tuple,
|
|
||||||
# Callable or type variables.
|
|
||||||
params = None
|
|
||||||
for base in bases:
|
|
||||||
if isinstance(base, TypingMeta):
|
|
||||||
if not isinstance(base, GenericMeta):
|
|
||||||
raise TypeError(
|
|
||||||
"You cannot inherit from magic class %s" %
|
|
||||||
repr(base))
|
|
||||||
if base.__parameters__ is None:
|
|
||||||
continue # The base is unparameterized.
|
|
||||||
for bp in base.__parameters__:
|
|
||||||
if _has_type_var(bp) and not isinstance(bp, TypeVar):
|
|
||||||
raise TypeError(
|
|
||||||
"Cannot inherit from a generic class "
|
|
||||||
"parameterized with "
|
|
||||||
"non-type-variable %s" % bp)
|
|
||||||
if params is None:
|
|
||||||
params = []
|
|
||||||
if bp not in params:
|
|
||||||
params.append(bp)
|
|
||||||
if params is not None:
|
|
||||||
parameters = tuple(params)
|
|
||||||
self = super().__new__(cls, name, bases, namespace, _root=True)
|
self = super().__new__(cls, name, bases, namespace, _root=True)
|
||||||
self.__parameters__ = parameters
|
|
||||||
|
if tvars is not None:
|
||||||
|
# Called from __getitem__() below.
|
||||||
|
assert origin is not None
|
||||||
|
assert all(isinstance(t, TypeVar) for t in tvars), tvars
|
||||||
|
else:
|
||||||
|
# Called from class statement.
|
||||||
|
assert tvars is None, tvars
|
||||||
|
assert args is None, args
|
||||||
|
assert origin is None, origin
|
||||||
|
|
||||||
|
# Get the full set of tvars from the bases.
|
||||||
|
tvars = _type_vars(bases)
|
||||||
|
# Look for Generic[T1, ..., Tn].
|
||||||
|
# If found, tvars must be a subset of it.
|
||||||
|
# If not found, tvars is it.
|
||||||
|
# Also check for and reject plain Generic,
|
||||||
|
# and reject multiple Generic[...].
|
||||||
|
gvars = None
|
||||||
|
for base in bases:
|
||||||
|
if base is Generic:
|
||||||
|
raise TypeError("Cannot inherit from plain Generic")
|
||||||
|
if (isinstance(base, GenericMeta) and
|
||||||
|
base.__origin__ is Generic):
|
||||||
|
if gvars is not None:
|
||||||
|
raise TypeError(
|
||||||
|
"Cannot inherit from Generic[...] multiple types.")
|
||||||
|
gvars = base.__parameters__
|
||||||
|
if gvars is None:
|
||||||
|
gvars = tvars
|
||||||
|
else:
|
||||||
|
tvarset = set(tvars)
|
||||||
|
gvarset = set(gvars)
|
||||||
|
if not tvarset <= gvarset:
|
||||||
|
raise TypeError(
|
||||||
|
"Some type variables (%s) "
|
||||||
|
"are not listed in Generic[%s]" %
|
||||||
|
(", ".join(str(t) for t in tvars if t not in gvarset),
|
||||||
|
", ".join(str(g) for g in gvars)))
|
||||||
|
tvars = gvars
|
||||||
|
|
||||||
|
self.__parameters__ = tvars
|
||||||
|
self.__args__ = args
|
||||||
|
self.__origin__ = origin
|
||||||
if extra is not None:
|
if extra is not None:
|
||||||
self.__extra__ = extra
|
self.__extra__ = extra
|
||||||
# Else __extra__ is inherited, eventually from the
|
# Else __extra__ is inherited, eventually from the
|
||||||
# (meta-)class default above.
|
# (meta-)class default above.
|
||||||
self.__origin__ = origin
|
# Speed hack (https://github.com/python/typing/issues/196).
|
||||||
|
self.__next_in_mro__ = _next_in_mro(self)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _has_type_var(self):
|
def _get_type_vars(self, tvars):
|
||||||
if self.__parameters__:
|
if self.__origin__ and self.__parameters__:
|
||||||
for t in self.__parameters__:
|
_get_type_vars(self.__parameters__, tvars)
|
||||||
if _has_type_var(t):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
r = super().__repr__()
|
if self.__origin__ is not None:
|
||||||
if self.__parameters__ is not None:
|
r = repr(self.__origin__)
|
||||||
|
else:
|
||||||
|
r = super().__repr__()
|
||||||
|
if self.__args__:
|
||||||
r += '[%s]' % (
|
r += '[%s]' % (
|
||||||
|
', '.join(_type_repr(p) for p in self.__args__))
|
||||||
|
if self.__parameters__:
|
||||||
|
r += '<%s>' % (
|
||||||
', '.join(_type_repr(p) for p in self.__parameters__))
|
', '.join(_type_repr(p) for p in self.__parameters__))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, GenericMeta):
|
if not isinstance(other, GenericMeta):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
return (_geqv(self, other) and
|
if self.__origin__ is not None:
|
||||||
self.__parameters__ == other.__parameters__)
|
return (self.__origin__ is other.__origin__ and
|
||||||
|
self.__args__ == other.__args__ and
|
||||||
|
self.__parameters__ == other.__parameters__)
|
||||||
|
else:
|
||||||
|
return self is other
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash((self.__name__, self.__parameters__))
|
return hash((self.__name__, self.__parameters__))
|
||||||
|
@ -956,37 +982,45 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
|
||||||
if not isinstance(params, tuple):
|
if not isinstance(params, tuple):
|
||||||
params = (params,)
|
params = (params,)
|
||||||
if not params:
|
if not params:
|
||||||
raise TypeError("Cannot have empty parameter list")
|
raise TypeError(
|
||||||
|
"Parameter list to %s[...] cannot be empty" % _qualname(self))
|
||||||
msg = "Parameters to generic types must be types."
|
msg = "Parameters to generic types must be types."
|
||||||
params = tuple(_type_check(p, msg) for p in params)
|
params = tuple(_type_check(p, msg) for p in params)
|
||||||
if self.__parameters__ is None:
|
if self is Generic:
|
||||||
for p in params:
|
# Generic can only be subscripted with unique type variables.
|
||||||
if not isinstance(p, TypeVar):
|
if not all(isinstance(p, TypeVar) for p in params):
|
||||||
raise TypeError("Initial parameters must be "
|
raise TypeError(
|
||||||
"type variables; got %s" % p)
|
"Parameters to Generic[...] must all be type variables")
|
||||||
if len(set(params)) != len(params):
|
if len(set(params)) != len(params):
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"All type variables in Generic[...] must be distinct.")
|
"Parameters to Generic[...] must all be unique")
|
||||||
|
tvars = params
|
||||||
|
args = None
|
||||||
|
elif self is _Protocol:
|
||||||
|
# _Protocol is internal, don't check anything.
|
||||||
|
tvars = params
|
||||||
|
args = None
|
||||||
|
elif self.__origin__ in (Generic, _Protocol):
|
||||||
|
# Can't subscript Generic[...] or _Protocol[...].
|
||||||
|
raise TypeError("Cannot subscript already-subscripted %s" %
|
||||||
|
repr(self))
|
||||||
else:
|
else:
|
||||||
if len(params) != len(self.__parameters__):
|
# Subscripting a regular Generic subclass.
|
||||||
raise TypeError("Cannot change parameter count from %d to %d" %
|
if not self.__parameters__:
|
||||||
(len(self.__parameters__), len(params)))
|
raise TypeError("%s is not a generic class" % repr(self))
|
||||||
for new, old in zip(params, self.__parameters__):
|
alen = len(params)
|
||||||
if isinstance(old, TypeVar):
|
elen = len(self.__parameters__)
|
||||||
if not old.__constraints__:
|
if alen != elen:
|
||||||
# Substituting for an unconstrained TypeVar is OK.
|
raise TypeError(
|
||||||
continue
|
"Too %s parameters for %s; actual %s, expected %s" %
|
||||||
if issubclass(new, Union[old.__constraints__]):
|
("many" if alen > elen else "few", repr(self), alen, elen))
|
||||||
# Specializing a constrained type variable is OK.
|
tvars = _type_vars(params)
|
||||||
continue
|
args = params
|
||||||
if not issubclass(new, old):
|
return self.__class__(self.__name__,
|
||||||
raise TypeError(
|
(self,) + self.__bases__,
|
||||||
"Cannot substitute %s for %s in %s" %
|
|
||||||
(_type_repr(new), _type_repr(old), self))
|
|
||||||
|
|
||||||
return self.__class__(self.__name__, (self,) + self.__bases__,
|
|
||||||
dict(self.__dict__),
|
dict(self.__dict__),
|
||||||
parameters=params,
|
tvars=tvars,
|
||||||
|
args=args,
|
||||||
origin=self,
|
origin=self,
|
||||||
extra=self.__extra__)
|
extra=self.__extra__)
|
||||||
|
|
||||||
|
@ -1006,10 +1040,10 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
|
||||||
# C[X] is a subclass of C[Y] iff X is a subclass of Y.
|
# C[X] is a subclass of C[Y] iff X is a subclass of Y.
|
||||||
origin = self.__origin__
|
origin = self.__origin__
|
||||||
if origin is not None and origin is cls.__origin__:
|
if origin is not None and origin is cls.__origin__:
|
||||||
assert len(self.__parameters__) == len(origin.__parameters__)
|
assert len(self.__args__) == len(origin.__parameters__)
|
||||||
assert len(cls.__parameters__) == len(origin.__parameters__)
|
assert len(cls.__args__) == len(origin.__parameters__)
|
||||||
for p_self, p_cls, p_origin in zip(self.__parameters__,
|
for p_self, p_cls, p_origin in zip(self.__args__,
|
||||||
cls.__parameters__,
|
cls.__args__,
|
||||||
origin.__parameters__):
|
origin.__parameters__):
|
||||||
if isinstance(p_origin, TypeVar):
|
if isinstance(p_origin, TypeVar):
|
||||||
if p_origin.__covariant__:
|
if p_origin.__covariant__:
|
||||||
|
@ -1039,6 +1073,10 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
|
||||||
return issubclass(cls, self.__extra__)
|
return issubclass(cls, self.__extra__)
|
||||||
|
|
||||||
|
|
||||||
|
# Prevent checks for Generic to crash when defining Generic.
|
||||||
|
Generic = None
|
||||||
|
|
||||||
|
|
||||||
class Generic(metaclass=GenericMeta):
|
class Generic(metaclass=GenericMeta):
|
||||||
"""Abstract base class for generic types.
|
"""Abstract base class for generic types.
|
||||||
|
|
||||||
|
@ -1053,29 +1091,23 @@ class Generic(metaclass=GenericMeta):
|
||||||
|
|
||||||
This class can then be used as follows::
|
This class can then be used as follows::
|
||||||
|
|
||||||
def lookup_name(mapping: Mapping, key: KT, default: VT) -> VT:
|
def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
|
||||||
try:
|
try:
|
||||||
return mapping[key]
|
return mapping[key]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
For clarity the type variables may be redefined, e.g.::
|
|
||||||
|
|
||||||
X = TypeVar('X')
|
|
||||||
Y = TypeVar('Y')
|
|
||||||
def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y:
|
|
||||||
# Same body as above.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
def __new__(cls, *args, **kwds):
|
def __new__(cls, *args, **kwds):
|
||||||
next_in_mro = object
|
if cls.__origin__ is None:
|
||||||
# Look for the last occurrence of Generic or Generic[...].
|
return cls.__next_in_mro__.__new__(cls)
|
||||||
for i, c in enumerate(cls.__mro__[:-1]):
|
else:
|
||||||
if isinstance(c, GenericMeta) and _gorg(c) is Generic:
|
origin = _gorg(cls)
|
||||||
next_in_mro = cls.__mro__[i+1]
|
obj = cls.__next_in_mro__.__new__(origin)
|
||||||
return next_in_mro.__new__(_gorg(cls))
|
obj.__init__(*args, **kwds)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
def cast(typ, val):
|
def cast(typ, val):
|
||||||
|
@ -1093,9 +1125,7 @@ def _get_defaults(func):
|
||||||
"""Internal helper to extract the default arguments, by name."""
|
"""Internal helper to extract the default arguments, by name."""
|
||||||
code = func.__code__
|
code = func.__code__
|
||||||
pos_count = code.co_argcount
|
pos_count = code.co_argcount
|
||||||
kw_count = code.co_kwonlyargcount
|
|
||||||
arg_names = code.co_varnames
|
arg_names = code.co_varnames
|
||||||
kwarg_names = arg_names[pos_count:pos_count + kw_count]
|
|
||||||
arg_names = arg_names[:pos_count]
|
arg_names = arg_names[:pos_count]
|
||||||
defaults = func.__defaults__ or ()
|
defaults = func.__defaults__ or ()
|
||||||
kwdefaults = func.__kwdefaults__
|
kwdefaults = func.__kwdefaults__
|
||||||
|
@ -1148,7 +1178,6 @@ def get_type_hints(obj, globalns=None, localns=None):
|
||||||
return hints
|
return hints
|
||||||
|
|
||||||
|
|
||||||
# TODO: Also support this as a class decorator.
|
|
||||||
def no_type_check(arg):
|
def no_type_check(arg):
|
||||||
"""Decorator to indicate that annotations are not type hints.
|
"""Decorator to indicate that annotations are not type hints.
|
||||||
|
|
||||||
|
@ -1183,8 +1212,42 @@ def no_type_check_decorator(decorator):
|
||||||
return wrapped_decorator
|
return wrapped_decorator
|
||||||
|
|
||||||
|
|
||||||
|
def _overload_dummy(*args, **kwds):
|
||||||
|
"""Helper for @overload to raise when called."""
|
||||||
|
raise NotImplementedError(
|
||||||
|
"You should not call an overloaded function. "
|
||||||
|
"A series of @overload-decorated functions "
|
||||||
|
"outside a stub module should always be followed "
|
||||||
|
"by an implementation that is not @overload-ed.")
|
||||||
|
|
||||||
|
|
||||||
def overload(func):
|
def overload(func):
|
||||||
raise RuntimeError("Overloading is only supported in library stubs")
|
"""Decorator for overloaded functions/methods.
|
||||||
|
|
||||||
|
In a stub file, place two or more stub definitions for the same
|
||||||
|
function in a row, each decorated with @overload. For example:
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def utf8(value: None) -> None: ...
|
||||||
|
@overload
|
||||||
|
def utf8(value: bytes) -> bytes: ...
|
||||||
|
@overload
|
||||||
|
def utf8(value: str) -> bytes: ...
|
||||||
|
|
||||||
|
In a non-stub file (i.e. a regular .py file), do the same but
|
||||||
|
follow it with an implementation. The implementation should *not*
|
||||||
|
be decorated with @overload. For example:
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def utf8(value: None) -> None: ...
|
||||||
|
@overload
|
||||||
|
def utf8(value: bytes) -> bytes: ...
|
||||||
|
@overload
|
||||||
|
def utf8(value: str) -> bytes: ...
|
||||||
|
def utf8(value):
|
||||||
|
# implementation goes here
|
||||||
|
"""
|
||||||
|
return _overload_dummy
|
||||||
|
|
||||||
|
|
||||||
class _ProtocolMeta(GenericMeta):
|
class _ProtocolMeta(GenericMeta):
|
||||||
|
@ -1232,14 +1295,16 @@ class _ProtocolMeta(GenericMeta):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if (not attr.startswith('_abc_') and
|
if (not attr.startswith('_abc_') and
|
||||||
attr != '__abstractmethods__' and
|
attr != '__abstractmethods__' and
|
||||||
attr != '_is_protocol' and
|
attr != '_is_protocol' and
|
||||||
attr != '__dict__' and
|
attr != '__dict__' and
|
||||||
attr != '__slots__' and
|
attr != '__args__' and
|
||||||
attr != '_get_protocol_attrs' and
|
attr != '__slots__' and
|
||||||
attr != '__parameters__' and
|
attr != '_get_protocol_attrs' and
|
||||||
attr != '__origin__' and
|
attr != '__next_in_mro__' and
|
||||||
attr != '__module__'):
|
attr != '__parameters__' and
|
||||||
|
attr != '__origin__' and
|
||||||
|
attr != '__module__'):
|
||||||
attrs.add(attr)
|
attrs.add(attr)
|
||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
@ -1264,16 +1329,25 @@ class _Protocol(metaclass=_ProtocolMeta):
|
||||||
Hashable = collections_abc.Hashable # Not generic.
|
Hashable = collections_abc.Hashable # Not generic.
|
||||||
|
|
||||||
|
|
||||||
class Awaitable(Generic[T_co], extra=collections_abc.Awaitable):
|
if hasattr(collections_abc, 'Awaitable'):
|
||||||
__slots__ = ()
|
class Awaitable(Generic[T_co], extra=collections_abc.Awaitable):
|
||||||
|
__slots__ = ()
|
||||||
|
else:
|
||||||
|
Awaitable = None
|
||||||
|
|
||||||
|
|
||||||
class AsyncIterable(Generic[T_co], extra=collections_abc.AsyncIterable):
|
if hasattr(collections_abc, 'AsyncIterable'):
|
||||||
__slots__ = ()
|
|
||||||
|
|
||||||
|
class AsyncIterable(Generic[T_co], extra=collections_abc.AsyncIterable):
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
class AsyncIterator(AsyncIterable[T_co], extra=collections_abc.AsyncIterator):
|
class AsyncIterator(AsyncIterable[T_co],
|
||||||
__slots__ = ()
|
extra=collections_abc.AsyncIterator):
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
else:
|
||||||
|
AsyncIterable = None
|
||||||
|
AsyncIterator = None
|
||||||
|
|
||||||
|
|
||||||
class Iterable(Generic[T_co], extra=collections_abc.Iterable):
|
class Iterable(Generic[T_co], extra=collections_abc.Iterable):
|
||||||
|
@ -1332,12 +1406,16 @@ class SupportsRound(_Protocol[T_co]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Reversible(_Protocol[T_co]):
|
if hasattr(collections_abc, 'Reversible'):
|
||||||
__slots__ = ()
|
class Reversible(Iterable[T_co], extra=collections_abc.Reversible):
|
||||||
|
__slots__ = ()
|
||||||
|
else:
|
||||||
|
class Reversible(_Protocol[T_co]):
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __reversed__(self) -> 'Iterator[T_co]':
|
def __reversed__(self) -> 'Iterator[T_co]':
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
Sized = collections_abc.Sized # Not generic.
|
Sized = collections_abc.Sized # Not generic.
|
||||||
|
@ -1360,7 +1438,7 @@ class MutableSet(AbstractSet[T], extra=collections_abc.MutableSet):
|
||||||
|
|
||||||
|
|
||||||
# NOTE: Only the value type is covariant.
|
# NOTE: Only the value type is covariant.
|
||||||
class Mapping(Sized, Iterable[KT], Container[KT], Generic[VT_co],
|
class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co],
|
||||||
extra=collections_abc.Mapping):
|
extra=collections_abc.Mapping):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1368,10 +1446,14 @@ class Mapping(Sized, Iterable[KT], Container[KT], Generic[VT_co],
|
||||||
class MutableMapping(Mapping[KT, VT], extra=collections_abc.MutableMapping):
|
class MutableMapping(Mapping[KT, VT], extra=collections_abc.MutableMapping):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if hasattr(collections_abc, 'Reversible'):
|
||||||
class Sequence(Sized, Iterable[T_co], Container[T_co],
|
class Sequence(Sized, Reversible[T_co], Container[T_co],
|
||||||
extra=collections_abc.Sequence):
|
extra=collections_abc.Sequence):
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
class Sequence(Sized, Iterable[T_co], Container[T_co],
|
||||||
|
extra=collections_abc.Sequence):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MutableSequence(Sequence[T], extra=collections_abc.MutableSequence):
|
class MutableSequence(Sequence[T], extra=collections_abc.MutableSequence):
|
||||||
|
@ -1436,8 +1518,9 @@ class KeysView(MappingView[KT], AbstractSet[KT],
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# TODO: Enable Set[Tuple[KT, VT_co]] instead of Generic[KT, VT_co].
|
class ItemsView(MappingView[Tuple[KT, VT_co]],
|
||||||
class ItemsView(MappingView, Generic[KT, VT_co],
|
Set[Tuple[KT, VT_co]],
|
||||||
|
Generic[KT, VT_co],
|
||||||
extra=collections_abc.ItemsView):
|
extra=collections_abc.ItemsView):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1454,6 +1537,13 @@ class Dict(dict, MutableMapping[KT, VT]):
|
||||||
"use dict() instead")
|
"use dict() instead")
|
||||||
return dict.__new__(cls, *args, **kwds)
|
return dict.__new__(cls, *args, **kwds)
|
||||||
|
|
||||||
|
class DefaultDict(collections.defaultdict, MutableMapping[KT, VT]):
|
||||||
|
|
||||||
|
def __new__(cls, *args, **kwds):
|
||||||
|
if _geqv(cls, DefaultDict):
|
||||||
|
raise TypeError("Type DefaultDict cannot be instantiated; "
|
||||||
|
"use collections.defaultdict() instead")
|
||||||
|
return collections.defaultdict.__new__(cls, *args, **kwds)
|
||||||
|
|
||||||
# Determine what base class to use for Generator.
|
# Determine what base class to use for Generator.
|
||||||
if hasattr(collections_abc, 'Generator'):
|
if hasattr(collections_abc, 'Generator'):
|
||||||
|
|
Loading…
Reference in New Issue