Commit 1dcfa018 authored by Guido van Rossum's avatar Guido van Rossum

Update typing.py and test_typing.py from upstream...

Update typing.py and test_typing.py from upstream (https://github.com/python/typing) (merge 3.5->3.6)
parents b6c89085 99a4f9b1
...@@ -9,7 +9,7 @@ from typing import Any ...@@ -9,7 +9,7 @@ from typing import Any
from typing import TypeVar, AnyStr from typing import TypeVar, AnyStr
from typing import T, KT, VT # Not in __all__. from typing import T, KT, VT # Not in __all__.
from typing import Union, Optional from typing import Union, Optional
from typing import Tuple, List from typing import Tuple, List, MutableMapping
from typing import Callable from typing import Callable
from typing import Generic, ClassVar from typing import Generic, ClassVar
from typing import cast from typing import cast
...@@ -21,6 +21,10 @@ from typing import NamedTuple ...@@ -21,6 +21,10 @@ from typing import NamedTuple
from typing import IO, TextIO, BinaryIO from typing import IO, TextIO, BinaryIO
from typing import Pattern, Match from typing import Pattern, Match
import typing import typing
try:
import collections.abc as collections_abc
except ImportError:
import collections as collections_abc # Fallback for PY3.2.
class BaseTestCase(TestCase): class BaseTestCase(TestCase):
...@@ -62,18 +66,11 @@ class AnyTests(BaseTestCase): ...@@ -62,18 +66,11 @@ class AnyTests(BaseTestCase):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
isinstance(42, Any) isinstance(42, Any)
def test_any_subclass(self): def test_any_subclass_type_error(self):
self.assertTrue(issubclass(Employee, Any)) with self.assertRaises(TypeError):
self.assertTrue(issubclass(int, Any)) issubclass(Employee, Any)
self.assertTrue(issubclass(type(None), Any)) with self.assertRaises(TypeError):
self.assertTrue(issubclass(object, Any)) issubclass(Any, Employee)
def test_others_any(self):
self.assertFalse(issubclass(Any, Employee))
self.assertFalse(issubclass(Any, int))
self.assertFalse(issubclass(Any, type(None)))
# However, Any is a subclass of object (this can't be helped).
self.assertTrue(issubclass(Any, object))
def test_repr(self): def test_repr(self):
self.assertEqual(repr(Any), 'typing.Any') self.assertEqual(repr(Any), 'typing.Any')
...@@ -88,32 +85,21 @@ class AnyTests(BaseTestCase): ...@@ -88,32 +85,21 @@ class AnyTests(BaseTestCase):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
class A(Any): class A(Any):
pass pass
with self.assertRaises(TypeError):
class A(type(Any)):
pass
def test_cannot_instantiate(self): def test_cannot_instantiate(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
Any() Any()
with self.assertRaises(TypeError):
type(Any)()
def test_cannot_subscript(self): def test_cannot_subscript(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
Any[int] Any[int]
def test_any_is_subclass(self): def test_any_works_with_alias(self):
# Any should be considered a subclass of everything.
self.assertIsSubclass(Any, Any)
self.assertIsSubclass(Any, typing.List)
self.assertIsSubclass(Any, typing.List[int])
self.assertIsSubclass(Any, typing.List[T])
self.assertIsSubclass(Any, typing.Mapping)
self.assertIsSubclass(Any, typing.Mapping[str, int])
self.assertIsSubclass(Any, typing.Mapping[KT, VT])
self.assertIsSubclass(Any, Generic)
self.assertIsSubclass(Any, Generic[T])
self.assertIsSubclass(Any, Generic[KT, VT])
self.assertIsSubclass(Any, AnyStr)
self.assertIsSubclass(Any, Union)
self.assertIsSubclass(Any, Union[int, str])
self.assertIsSubclass(Any, typing.Match)
self.assertIsSubclass(Any, typing.Match[str])
# These expressions must simply not fail. # These expressions must simply not fail.
typing.Match[Any] typing.Match[Any]
typing.Pattern[Any] typing.Pattern[Any]
...@@ -124,13 +110,8 @@ class TypeVarTests(BaseTestCase): ...@@ -124,13 +110,8 @@ class TypeVarTests(BaseTestCase):
def test_basic_plain(self): def test_basic_plain(self):
T = TypeVar('T') T = TypeVar('T')
# Every class is a subclass of T.
self.assertIsSubclass(int, T)
self.assertIsSubclass(str, T)
# T equals itself. # T equals itself.
self.assertEqual(T, T) self.assertEqual(T, T)
# T is a subclass of itself.
self.assertIsSubclass(T, T)
# T is an instance of TypeVar # T is an instance of TypeVar
self.assertIsInstance(T, TypeVar) self.assertIsInstance(T, TypeVar)
...@@ -139,16 +120,12 @@ class TypeVarTests(BaseTestCase): ...@@ -139,16 +120,12 @@ class TypeVarTests(BaseTestCase):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
isinstance(42, T) isinstance(42, T)
def test_basic_constrained(self): def test_typevar_subclass_type_error(self):
A = TypeVar('A', str, bytes) T = TypeVar('T')
# Only str and bytes are subclasses of A. with self.assertRaises(TypeError):
self.assertIsSubclass(str, A) issubclass(int, T)
self.assertIsSubclass(bytes, A) with self.assertRaises(TypeError):
self.assertNotIsSubclass(int, A) issubclass(T, int)
# A equals itself.
self.assertEqual(A, A)
# A is a subclass of itself.
self.assertIsSubclass(A, A)
def test_constrained_error(self): def test_constrained_error(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
...@@ -185,19 +162,6 @@ class TypeVarTests(BaseTestCase): ...@@ -185,19 +162,6 @@ class TypeVarTests(BaseTestCase):
self.assertNotEqual(TypeVar('T'), TypeVar('T')) self.assertNotEqual(TypeVar('T'), TypeVar('T'))
self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str)) self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str))
def test_subclass_as_unions(self):
# None of these are true -- each type var is its own world.
self.assertFalse(issubclass(TypeVar('T', int, str),
TypeVar('T', int, str)))
self.assertFalse(issubclass(TypeVar('T', int, float),
TypeVar('T', int, float, str)))
self.assertFalse(issubclass(TypeVar('T', int, str),
TypeVar('T', str, int)))
A = TypeVar('A', int, str)
B = TypeVar('B', int, str, float)
self.assertFalse(issubclass(A, B))
self.assertFalse(issubclass(B, A))
def test_cannot_subclass_vars(self): def test_cannot_subclass_vars(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
class V(TypeVar('T')): class V(TypeVar('T')):
...@@ -212,12 +176,6 @@ class TypeVarTests(BaseTestCase): ...@@ -212,12 +176,6 @@ class TypeVarTests(BaseTestCase):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
TypeVar('A')() TypeVar('A')()
def test_bound(self):
X = TypeVar('X', bound=Employee)
self.assertIsSubclass(Employee, X)
self.assertIsSubclass(Manager, X)
self.assertNotIsSubclass(int, X)
def test_bound_errors(self): def test_bound_errors(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
TypeVar('X', bound=42) TypeVar('X', bound=42)
...@@ -230,8 +188,16 @@ class UnionTests(BaseTestCase): ...@@ -230,8 +188,16 @@ class UnionTests(BaseTestCase):
def test_basics(self): def test_basics(self):
u = Union[int, float] u = Union[int, float]
self.assertNotEqual(u, Union) self.assertNotEqual(u, Union)
self.assertTrue(issubclass(int, u))
self.assertTrue(issubclass(float, u)) def test_subclass_error(self):
with self.assertRaises(TypeError):
issubclass(int, Union)
with self.assertRaises(TypeError):
issubclass(Union, int)
with self.assertRaises(TypeError):
issubclass(int, Union[int, str])
with self.assertRaises(TypeError):
issubclass(Union[int, str], int)
def test_union_any(self): def test_union_any(self):
u = Union[Any] u = Union[Any]
...@@ -260,18 +226,6 @@ class UnionTests(BaseTestCase): ...@@ -260,18 +226,6 @@ class UnionTests(BaseTestCase):
u2 = Union[float, int] u2 = Union[float, int]
self.assertEqual(u1, u2) self.assertEqual(u1, u2)
def test_subclass(self):
u = Union[int, Employee]
self.assertTrue(issubclass(Manager, u))
def test_self_subclass(self):
self.assertTrue(issubclass(Union[KT, VT], Union))
self.assertFalse(issubclass(Union, Union[KT, VT]))
def test_multiple_inheritance(self):
u = Union[int, Employee]
self.assertTrue(issubclass(ManagingFounder, u))
def test_single_class_disappears(self): def test_single_class_disappears(self):
t = Union[Employee] t = Union[Employee]
self.assertIs(t, Employee) self.assertIs(t, Employee)
...@@ -284,13 +238,6 @@ class UnionTests(BaseTestCase): ...@@ -284,13 +238,6 @@ class UnionTests(BaseTestCase):
u = Union[Employee, Manager] u = Union[Employee, Manager]
self.assertIs(u, Employee) self.assertIs(u, Employee)
def test_weird_subclasses(self):
u = Union[Employee, int, float]
v = Union[int, float]
self.assertTrue(issubclass(v, u))
w = Union[int, Manager]
self.assertTrue(issubclass(w, u))
def test_union_union(self): def test_union_union(self):
u = Union[int, float] u = Union[int, float]
v = Union[u, Employee] v = Union[u, Employee]
...@@ -307,6 +254,9 @@ class UnionTests(BaseTestCase): ...@@ -307,6 +254,9 @@ class UnionTests(BaseTestCase):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
class C(Union): class C(Union):
pass pass
with self.assertRaises(TypeError):
class C(type(Union)):
pass
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
class C(Union[int, str]): class C(Union[int, str]):
pass pass
...@@ -314,9 +264,18 @@ class UnionTests(BaseTestCase): ...@@ -314,9 +264,18 @@ class UnionTests(BaseTestCase):
def test_cannot_instantiate(self): def test_cannot_instantiate(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
Union() Union()
with self.assertRaises(TypeError):
type(Union)()
u = Union[int, float] u = Union[int, float]
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
u() u()
with self.assertRaises(TypeError):
type(u)()
def test_union_generalization(self):
self.assertFalse(Union[str, typing.Iterable[int]] == str)
self.assertFalse(Union[str, typing.Iterable[int]] == typing.Iterable[int])
self.assertTrue(Union[str, typing.Iterable] == typing.Iterable)
def test_optional(self): def test_optional(self):
o = Optional[int] o = Optional[int]
...@@ -327,10 +286,6 @@ class UnionTests(BaseTestCase): ...@@ -327,10 +286,6 @@ class UnionTests(BaseTestCase):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
Union[()] Union[()]
def test_issubclass_union(self):
self.assertIsSubclass(Union[int, str], Union)
self.assertNotIsSubclass(int, Union)
def test_union_instance_type_error(self): def test_union_instance_type_error(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
isinstance(42, Union[int, str]) isinstance(42, Union[int, str])
...@@ -355,43 +310,19 @@ class UnionTests(BaseTestCase): ...@@ -355,43 +310,19 @@ class UnionTests(BaseTestCase):
Union[Elem, str] # Nor should this Union[Elem, str] # Nor should this
class TypeVarUnionTests(BaseTestCase):
def test_simpler(self):
A = TypeVar('A', int, str, float)
B = TypeVar('B', int, str)
self.assertIsSubclass(A, A)
self.assertIsSubclass(B, B)
self.assertNotIsSubclass(B, A)
self.assertIsSubclass(A, Union[int, str, float])
self.assertNotIsSubclass(Union[int, str, float], A)
self.assertNotIsSubclass(Union[int, str], B)
self.assertIsSubclass(B, Union[int, str])
self.assertNotIsSubclass(A, B)
self.assertNotIsSubclass(Union[int, str, float], B)
self.assertNotIsSubclass(A, Union[int, str])
def test_var_union_subclass(self):
self.assertTrue(issubclass(T, Union[int, T]))
self.assertTrue(issubclass(KT, Union[KT, VT]))
def test_var_union(self):
TU = TypeVar('TU', Union[int, float], None)
self.assertIsSubclass(int, TU)
self.assertIsSubclass(float, TU)
class TupleTests(BaseTestCase): class TupleTests(BaseTestCase):
def test_basics(self): def test_basics(self):
self.assertTrue(issubclass(Tuple[int, str], Tuple)) with self.assertRaises(TypeError):
self.assertTrue(issubclass(Tuple[int, str], Tuple[int, str])) issubclass(Tuple[int, str], Tuple)
self.assertFalse(issubclass(int, Tuple)) with self.assertRaises(TypeError):
self.assertFalse(issubclass(Tuple[float, str], Tuple[int, str])) issubclass(Tuple, Tuple[int, str])
self.assertFalse(issubclass(Tuple[int, str, int], Tuple[int, str])) with self.assertRaises(TypeError):
self.assertFalse(issubclass(Tuple[int, str], Tuple[int, str, int])) issubclass(tuple, Tuple[int, str])
class TP(tuple): ...
self.assertTrue(issubclass(tuple, Tuple)) self.assertTrue(issubclass(tuple, Tuple))
self.assertFalse(issubclass(Tuple, tuple)) # Can't have it both ways. self.assertTrue(issubclass(TP, Tuple))
def test_equality(self): def test_equality(self):
self.assertEqual(Tuple[int], Tuple[int]) self.assertEqual(Tuple[int], Tuple[int])
...@@ -407,21 +338,7 @@ class TupleTests(BaseTestCase): ...@@ -407,21 +338,7 @@ class TupleTests(BaseTestCase):
def test_tuple_instance_type_error(self): def test_tuple_instance_type_error(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
isinstance((0, 0), Tuple[int, int]) isinstance((0, 0), Tuple[int, int])
with self.assertRaises(TypeError): self.assertIsInstance((0, 0), Tuple)
isinstance((0, 0), Tuple)
def test_tuple_ellipsis_subclass(self):
class B:
pass
class C(B):
pass
self.assertNotIsSubclass(Tuple[B], Tuple[B, ...])
self.assertIsSubclass(Tuple[C, ...], Tuple[B, ...])
self.assertNotIsSubclass(Tuple[C, ...], Tuple[B])
self.assertNotIsSubclass(Tuple[C], Tuple[B, ...])
def test_repr(self): def test_repr(self):
self.assertEqual(repr(Tuple), 'typing.Tuple') self.assertEqual(repr(Tuple), 'typing.Tuple')
...@@ -439,17 +356,9 @@ class TupleTests(BaseTestCase): ...@@ -439,17 +356,9 @@ class TupleTests(BaseTestCase):
class CallableTests(BaseTestCase): class CallableTests(BaseTestCase):
def test_self_subclass(self): def test_self_subclass(self):
self.assertTrue(issubclass(Callable[[int], int], Callable)) with self.assertRaises(TypeError):
self.assertFalse(issubclass(Callable, Callable[[int], int])) self.assertTrue(issubclass(type(lambda x: x), Callable[[int], int]))
self.assertTrue(issubclass(Callable[[int], int], Callable[[int], int])) self.assertTrue(issubclass(type(lambda x: x), Callable))
self.assertFalse(issubclass(Callable[[Employee], int],
Callable[[Manager], int]))
self.assertFalse(issubclass(Callable[[Manager], int],
Callable[[Employee], int]))
self.assertFalse(issubclass(Callable[[int], Employee],
Callable[[int], Manager]))
self.assertFalse(issubclass(Callable[[int], Manager],
Callable[[int], Employee]))
def test_eq_hash(self): def test_eq_hash(self):
self.assertEqual(Callable[[int], int], Callable[[int], int]) self.assertEqual(Callable[[int], int], Callable[[int], int])
...@@ -466,6 +375,11 @@ class CallableTests(BaseTestCase): ...@@ -466,6 +375,11 @@ class CallableTests(BaseTestCase):
class C(Callable): class C(Callable):
pass pass
with self.assertRaises(TypeError):
class C(type(Callable)):
pass
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
class C(Callable[[int], int]): class C(Callable[[int], int]):
...@@ -474,9 +388,13 @@ class CallableTests(BaseTestCase): ...@@ -474,9 +388,13 @@ class CallableTests(BaseTestCase):
def test_cannot_instantiate(self): def test_cannot_instantiate(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
Callable() Callable()
with self.assertRaises(TypeError):
type(Callable)()
c = Callable[[int], str] c = Callable[[int], str]
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
c() c()
with self.assertRaises(TypeError):
type(c)()
def test_callable_instance_works(self): def test_callable_instance_works(self):
def f(): def f():
...@@ -616,6 +534,12 @@ class GenericTests(BaseTestCase): ...@@ -616,6 +534,12 @@ class GenericTests(BaseTestCase):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
Y[str, str] Y[str, str]
def test_generic_errors(self):
with self.assertRaises(TypeError):
isinstance([], List[int])
with self.assertRaises(TypeError):
issubclass(list, List[int])
def test_init(self): def test_init(self):
T = TypeVar('T') T = TypeVar('T')
S = TypeVar('S') S = TypeVar('S')
...@@ -671,6 +595,42 @@ class GenericTests(BaseTestCase): ...@@ -671,6 +595,42 @@ class GenericTests(BaseTestCase):
c.bar = 'abc' c.bar = 'abc'
self.assertEqual(c.__dict__, {'bar': 'abc'}) self.assertEqual(c.__dict__, {'bar': 'abc'})
def test_false_subclasses(self):
class MyMapping(MutableMapping[str, str]): pass
self.assertNotIsInstance({}, MyMapping)
self.assertNotIsSubclass(dict, MyMapping)
def test_multiple_abc_bases(self):
class MM1(MutableMapping[str, str], collections_abc.MutableMapping):
def __getitem__(self, k):
return None
def __setitem__(self, k, v):
pass
def __delitem__(self, k):
pass
def __iter__(self):
return iter(())
def __len__(self):
return 0
class MM2(collections_abc.MutableMapping, MutableMapping[str, str]):
def __getitem__(self, k):
return None
def __setitem__(self, k, v):
pass
def __delitem__(self, k):
pass
def __iter__(self):
return iter(())
def __len__(self):
return 0
# these two should just work
MM1().update()
MM2().update()
self.assertIsInstance(MM1(), collections_abc.MutableMapping)
self.assertIsInstance(MM1(), MutableMapping)
self.assertIsInstance(MM2(), collections_abc.MutableMapping)
self.assertIsInstance(MM2(), MutableMapping)
def test_pickle(self): def test_pickle(self):
global C # pickle wants to reference the class by name global C # pickle wants to reference the class by name
T = TypeVar('T') T = TypeVar('T')
...@@ -853,6 +813,8 @@ class ClassVarTests(BaseTestCase): ...@@ -853,6 +813,8 @@ class ClassVarTests(BaseTestCase):
pass pass
def test_cannot_init(self): def test_cannot_init(self):
with self.assertRaises(TypeError):
ClassVar()
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
type(ClassVar)() type(ClassVar)()
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
...@@ -865,52 +827,6 @@ class ClassVarTests(BaseTestCase): ...@@ -865,52 +827,6 @@ class ClassVarTests(BaseTestCase):
issubclass(int, ClassVar) issubclass(int, ClassVar)
class VarianceTests(BaseTestCase):
def test_invariance(self):
# Because of invariance, List[subclass of X] is not a subclass
# of List[X], and ditto for MutableSequence.
self.assertNotIsSubclass(typing.List[Manager], typing.List[Employee])
self.assertNotIsSubclass(typing.MutableSequence[Manager],
typing.MutableSequence[Employee])
# It's still reflexive.
self.assertIsSubclass(typing.List[Employee], typing.List[Employee])
self.assertIsSubclass(typing.MutableSequence[Employee],
typing.MutableSequence[Employee])
def test_covariance_tuple(self):
# Check covariace for Tuple (which are really special cases).
self.assertIsSubclass(Tuple[Manager], Tuple[Employee])
self.assertNotIsSubclass(Tuple[Employee], Tuple[Manager])
# And pairwise.
self.assertIsSubclass(Tuple[Manager, Manager],
Tuple[Employee, Employee])
self.assertNotIsSubclass(Tuple[Employee, Employee],
Tuple[Manager, Employee])
# And using ellipsis.
self.assertIsSubclass(Tuple[Manager, ...], Tuple[Employee, ...])
self.assertNotIsSubclass(Tuple[Employee, ...], Tuple[Manager, ...])
def test_covariance_sequence(self):
# Check covariance for Sequence (which is just a generic class
# for this purpose, but using a type variable with covariant=True).
self.assertIsSubclass(typing.Sequence[Manager],
typing.Sequence[Employee])
self.assertNotIsSubclass(typing.Sequence[Employee],
typing.Sequence[Manager])
def test_covariance_mapping(self):
# Ditto for Mapping (covariant in the value, invariant in the key).
self.assertIsSubclass(typing.Mapping[Employee, Manager],
typing.Mapping[Employee, Employee])
self.assertNotIsSubclass(typing.Mapping[Manager, Employee],
typing.Mapping[Employee, Employee])
self.assertNotIsSubclass(typing.Mapping[Employee, Manager],
typing.Mapping[Manager, Manager])
self.assertNotIsSubclass(typing.Mapping[Manager, Employee],
typing.Mapping[Manager, Manager])
class CastTests(BaseTestCase): class CastTests(BaseTestCase):
def test_basics(self): def test_basics(self):
...@@ -1247,7 +1163,6 @@ class CollectionsAbcTests(BaseTestCase): ...@@ -1247,7 +1163,6 @@ class CollectionsAbcTests(BaseTestCase):
# path and could fail. So call this a few times. # path and could fail. So call this a few times.
self.assertIsInstance([], typing.Iterable) self.assertIsInstance([], typing.Iterable)
self.assertIsInstance([], typing.Iterable) self.assertIsInstance([], typing.Iterable)
self.assertIsInstance([], typing.Iterable[int])
self.assertNotIsInstance(42, typing.Iterable) self.assertNotIsInstance(42, typing.Iterable)
# Just in case, also test issubclass() a few times. # Just in case, also test issubclass() a few times.
self.assertIsSubclass(list, typing.Iterable) self.assertIsSubclass(list, typing.Iterable)
...@@ -1256,7 +1171,6 @@ class CollectionsAbcTests(BaseTestCase): ...@@ -1256,7 +1171,6 @@ class CollectionsAbcTests(BaseTestCase):
def test_iterator(self): def test_iterator(self):
it = iter([]) it = iter([])
self.assertIsInstance(it, typing.Iterator) self.assertIsInstance(it, typing.Iterator)
self.assertIsInstance(it, typing.Iterator[int])
self.assertNotIsInstance(42, typing.Iterator) self.assertNotIsInstance(42, typing.Iterator)
@skipUnless(PY35, 'Python 3.5 required') @skipUnless(PY35, 'Python 3.5 required')
...@@ -1268,13 +1182,8 @@ class CollectionsAbcTests(BaseTestCase): ...@@ -1268,13 +1182,8 @@ class CollectionsAbcTests(BaseTestCase):
globals(), ns) globals(), ns)
foo = ns['foo'] foo = ns['foo']
g = foo() g = foo()
self.assertIsSubclass(type(g), typing.Awaitable[int])
self.assertIsInstance(g, typing.Awaitable) self.assertIsInstance(g, typing.Awaitable)
self.assertNotIsInstance(foo, typing.Awaitable) self.assertNotIsInstance(foo, typing.Awaitable)
self.assertIsSubclass(typing.Awaitable[Manager],
typing.Awaitable[Employee])
self.assertNotIsSubclass(typing.Awaitable[Employee],
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') @skipUnless(PY35, 'Python 3.5 required')
...@@ -1283,8 +1192,6 @@ class CollectionsAbcTests(BaseTestCase): ...@@ -1283,8 +1192,6 @@ class CollectionsAbcTests(BaseTestCase):
it = AsyncIteratorWrapper(base_it) it = AsyncIteratorWrapper(base_it)
self.assertIsInstance(it, typing.AsyncIterable) self.assertIsInstance(it, typing.AsyncIterable)
self.assertIsInstance(it, typing.AsyncIterable) self.assertIsInstance(it, typing.AsyncIterable)
self.assertIsSubclass(typing.AsyncIterable[Manager],
typing.AsyncIterable[Employee])
self.assertNotIsInstance(42, typing.AsyncIterable) self.assertNotIsInstance(42, typing.AsyncIterable)
@skipUnless(PY35, 'Python 3.5 required') @skipUnless(PY35, 'Python 3.5 required')
...@@ -1292,8 +1199,6 @@ class CollectionsAbcTests(BaseTestCase): ...@@ -1292,8 +1199,6 @@ class CollectionsAbcTests(BaseTestCase):
base_it = range(10) # type: Iterator[int] base_it = range(10) # type: Iterator[int]
it = AsyncIteratorWrapper(base_it) it = AsyncIteratorWrapper(base_it)
self.assertIsInstance(it, typing.AsyncIterator) self.assertIsInstance(it, typing.AsyncIterator)
self.assertIsSubclass(typing.AsyncIterator[Manager],
typing.AsyncIterator[Employee])
self.assertNotIsInstance(42, typing.AsyncIterator) self.assertNotIsInstance(42, typing.AsyncIterator)
def test_sized(self): def test_sized(self):
...@@ -1457,10 +1362,6 @@ class CollectionsAbcTests(BaseTestCase): ...@@ -1457,10 +1362,6 @@ class CollectionsAbcTests(BaseTestCase):
yield 42 yield 42
g = foo() g = foo()
self.assertIsSubclass(type(g), typing.Generator) self.assertIsSubclass(type(g), typing.Generator)
self.assertIsSubclass(typing.Generator[Manager, Employee, Manager],
typing.Generator[Employee, Manager, Employee])
self.assertNotIsSubclass(typing.Generator[Manager, Manager, Manager],
typing.Generator[Employee, Employee, Employee])
def test_no_generator_instantiation(self): def test_no_generator_instantiation(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
...@@ -1511,7 +1412,6 @@ class OtherABCTests(BaseTestCase): ...@@ -1511,7 +1412,6 @@ class OtherABCTests(BaseTestCase):
cm = manager() cm = manager()
self.assertIsInstance(cm, typing.ContextManager) self.assertIsInstance(cm, typing.ContextManager)
self.assertIsInstance(cm, typing.ContextManager[int])
self.assertNotIsInstance(42, typing.ContextManager) self.assertNotIsInstance(42, typing.ContextManager)
...@@ -1653,22 +1553,16 @@ class RETests(BaseTestCase): ...@@ -1653,22 +1553,16 @@ class RETests(BaseTestCase):
pat = re.compile('[a-z]+', re.I) pat = re.compile('[a-z]+', re.I)
self.assertIsSubclass(pat.__class__, Pattern) self.assertIsSubclass(pat.__class__, Pattern)
self.assertIsSubclass(type(pat), Pattern) self.assertIsSubclass(type(pat), Pattern)
self.assertIsSubclass(type(pat), Pattern[str]) self.assertIsInstance(pat, Pattern)
mat = pat.search('12345abcde.....') mat = pat.search('12345abcde.....')
self.assertIsSubclass(mat.__class__, Match) self.assertIsSubclass(mat.__class__, Match)
self.assertIsSubclass(mat.__class__, Match[str])
self.assertIsSubclass(mat.__class__, Match[bytes]) # Sad but true.
self.assertIsSubclass(type(mat), Match) self.assertIsSubclass(type(mat), Match)
self.assertIsSubclass(type(mat), Match[str]) self.assertIsInstance(mat, Match)
# these should just work
p = Pattern[Union[str, bytes]] p = Pattern[Union[str, bytes]]
self.assertIsSubclass(Pattern[str], Pattern)
self.assertIsSubclass(Pattern[str], p)
m = Match[Union[bytes, str]] m = Match[Union[bytes, str]]
self.assertIsSubclass(Match[bytes], Match)
self.assertIsSubclass(Match[bytes], m)
def test_errors(self): def test_errors(self):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
...@@ -1681,9 +1575,6 @@ class RETests(BaseTestCase): ...@@ -1681,9 +1575,6 @@ class RETests(BaseTestCase):
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
# Too complicated? # Too complicated?
m[str] m[str]
with self.assertRaises(TypeError):
# We don't support isinstance().
isinstance(42, Pattern)
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
# We don't support isinstance(). # We don't support isinstance().
isinstance(42, Pattern[str]) isinstance(42, Pattern[str])
...@@ -1710,7 +1601,7 @@ class RETests(BaseTestCase): ...@@ -1710,7 +1601,7 @@ class RETests(BaseTestCase):
pass pass
self.assertEqual(str(ex.exception), self.assertEqual(str(ex.exception),
"A type alias cannot be subclassed") "Cannot subclass typing._TypeAlias")
class AllTests(BaseTestCase): class AllTests(BaseTestCase):
......
...@@ -89,6 +89,13 @@ def _qualname(x): ...@@ -89,6 +89,13 @@ def _qualname(x):
return x.__name__ return x.__name__
def _trim_name(nm):
if nm.startswith('_') and nm not in ('_TypeAlias',
'_ForwardRef', '_TypingBase', '_FinalTypingBase'):
nm = nm[1:]
return nm
class TypingMeta(type): class TypingMeta(type):
"""Metaclass for every type defined below. """Metaclass for every type defined below.
...@@ -127,22 +134,69 @@ class TypingMeta(type): ...@@ -127,22 +134,69 @@ class TypingMeta(type):
pass pass
def __repr__(self): def __repr__(self):
return '%s.%s' % (self.__module__, _qualname(self)) qname = _trim_name(_qualname(self))
return '%s.%s' % (self.__module__, qname)
class _TypingBase(metaclass=TypingMeta, _root=True):
"""Indicator of special typing constructs."""
__slots__ = ()
def __init__(self, *args, **kwds):
pass
def __new__(cls, *args, **kwds):
"""Constructor.
This only exists to give a better error message in case
someone tries to subclass a special typing object (not a good idea).
"""
if (len(args) == 3 and
isinstance(args[0], str) and
isinstance(args[1], tuple)):
# Close enough.
raise TypeError("Cannot subclass %r" % cls)
return object.__new__(cls)
class Final: # Things that are not classes also need these.
def _eval_type(self, globalns, localns):
return self
def _get_type_vars(self, tvars):
pass
def __repr__(self):
cls = type(self)
qname = _trim_name(_qualname(cls))
return '%s.%s' % (cls.__module__, qname)
def __call__(self, *args, **kwds):
raise TypeError("Cannot instantiate %r" % type(self))
class _FinalTypingBase(_TypingBase, _root=True):
"""Mix-in class to prevent instantiation.""" """Mix-in class to prevent instantiation."""
__slots__ = () __slots__ = ()
def __new__(self, *args, **kwds): def __new__(cls, *args, _root=False, **kwds):
raise TypeError("Cannot instantiate %r" % self.__class__) self = super().__new__(cls, *args, **kwds)
if _root is True:
return self
raise TypeError("Cannot instantiate %r" % cls)
class _ForwardRef(TypingMeta): class _ForwardRef(_TypingBase, _root=True):
"""Wrapper to hold a forward reference.""" """Wrapper to hold a forward reference."""
def __new__(cls, arg): __slots__ = ('__forward_arg__', '__forward_code__',
'__forward_evaluated__', '__forward_value__',
'__forward_frame__')
def __init__(self, arg):
super().__init__(arg)
if not isinstance(arg, str): if not isinstance(arg, str):
raise TypeError('ForwardRef must be a string -- got %r' % (arg,)) raise TypeError('ForwardRef must be a string -- got %r' % (arg,))
try: try:
...@@ -150,7 +204,6 @@ class _ForwardRef(TypingMeta): ...@@ -150,7 +204,6 @@ class _ForwardRef(TypingMeta):
except SyntaxError: except SyntaxError:
raise SyntaxError('ForwardRef must be an expression -- got %r' % raise SyntaxError('ForwardRef must be an expression -- got %r' %
(arg,)) (arg,))
self = super().__new__(cls, arg, (), {}, _root=True)
self.__forward_arg__ = arg self.__forward_arg__ = arg
self.__forward_code__ = code self.__forward_code__ = code
self.__forward_evaluated__ = False self.__forward_evaluated__ = False
...@@ -161,7 +214,6 @@ class _ForwardRef(TypingMeta): ...@@ -161,7 +214,6 @@ class _ForwardRef(TypingMeta):
frame = frame.f_back frame = frame.f_back
assert frame is not None assert frame is not None
self.__forward_frame__ = frame self.__forward_frame__ = frame
return self
def _eval_type(self, globalns, localns): def _eval_type(self, globalns, localns):
if not self.__forward_evaluated__: if not self.__forward_evaluated__:
...@@ -177,49 +229,36 @@ class _ForwardRef(TypingMeta): ...@@ -177,49 +229,36 @@ class _ForwardRef(TypingMeta):
self.__forward_evaluated__ = True self.__forward_evaluated__ = True
return self.__forward_value__ return self.__forward_value__
def __eq__(self, other):
if not isinstance(other, _ForwardRef):
return NotImplemented
return (self.__forward_arg__ == other.__forward_arg__ and
self.__forward_frame__ == other.__forward_frame__)
def __hash__(self):
return hash((self.__forward_arg__, self.__forward_frame__))
def __instancecheck__(self, obj): def __instancecheck__(self, obj):
raise TypeError("Forward references cannot be used with isinstance().") raise TypeError("Forward references cannot be used with isinstance().")
def __subclasscheck__(self, cls): def __subclasscheck__(self, cls):
if not self.__forward_evaluated__: raise TypeError("Forward references cannot be used with issubclass().")
globalns = self.__forward_frame__.f_globals
localns = self.__forward_frame__.f_locals
try:
self._eval_type(globalns, localns)
except NameError:
return False # Too early.
return issubclass(cls, self.__forward_value__)
def __repr__(self): def __repr__(self):
return '_ForwardRef(%r)' % (self.__forward_arg__,) return '_ForwardRef(%r)' % (self.__forward_arg__,)
class _TypeAlias: class _TypeAlias(_TypingBase, _root=True):
"""Internal helper class for defining generic variants of concrete types. """Internal helper class for defining generic variants of concrete types.
Note that this is not a type; let's call it a pseudo-type. It can Note that this is not a type; let's call it a pseudo-type. It cannot
be used in instance and subclass checks, e.g. isinstance(m, Match) be used in instance and subclass checks in parameterized form, i.e.
or issubclass(type(m), Match). However, it cannot be itself the ``isinstance(42, Match[str])`` raises ``TypeError`` instead of returning
target of an issubclass() call; e.g. issubclass(Match, C) (for ``False``.
some arbitrary class C) raises TypeError rather than returning
False.
""" """
__slots__ = ('name', 'type_var', 'impl_type', 'type_checker') __slots__ = ('name', 'type_var', 'impl_type', 'type_checker')
def __new__(cls, *args, **kwds):
"""Constructor.
This only exists to give a better error message in case
someone tries to subclass a type alias (not a good idea).
"""
if (len(args) == 3 and
isinstance(args[0], str) and
isinstance(args[1], tuple)):
# Close enough.
raise TypeError("A type alias cannot be subclassed")
return object.__new__(cls)
def __init__(self, name, type_var, impl_type, type_checker): def __init__(self, name, type_var, impl_type, type_checker):
"""Initializer. """Initializer.
...@@ -232,9 +271,9 @@ class _TypeAlias: ...@@ -232,9 +271,9 @@ class _TypeAlias:
and returns a value that should be a type_var instance. and returns a value that should be a type_var instance.
""" """
assert isinstance(name, str), repr(name) assert isinstance(name, str), repr(name)
assert isinstance(type_var, type), repr(type_var)
assert isinstance(impl_type, type), repr(impl_type) assert isinstance(impl_type, type), repr(impl_type)
assert not isinstance(impl_type, TypingMeta), repr(impl_type) assert not isinstance(impl_type, TypingMeta), repr(impl_type)
assert isinstance(type_var, (type, _TypingBase))
self.name = name self.name = name
self.type_var = type_var self.type_var = type_var
self.impl_type = impl_type self.impl_type = impl_type
...@@ -244,36 +283,41 @@ class _TypeAlias: ...@@ -244,36 +283,41 @@ class _TypeAlias:
return "%s[%s]" % (self.name, _type_repr(self.type_var)) return "%s[%s]" % (self.name, _type_repr(self.type_var))
def __getitem__(self, parameter): def __getitem__(self, parameter):
assert isinstance(parameter, type), repr(parameter)
if not isinstance(self.type_var, TypeVar): if not isinstance(self.type_var, TypeVar):
raise TypeError("%s cannot be further parameterized." % self) raise TypeError("%s cannot be further parameterized." % self)
if self.type_var.__constraints__: if self.type_var.__constraints__ and isinstance(parameter, type):
if not issubclass(parameter, Union[self.type_var.__constraints__]): if not issubclass(parameter, self.type_var.__constraints__):
raise TypeError("%s is not a valid substitution for %s." % raise TypeError("%s is not a valid substitution for %s." %
(parameter, self.type_var)) (parameter, self.type_var))
if isinstance(parameter, TypeVar):
raise TypeError("%s cannot be re-parameterized." % self.type_var)
return self.__class__(self.name, parameter, return self.__class__(self.name, parameter,
self.impl_type, self.type_checker) self.impl_type, self.type_checker)
def __eq__(self, other):
if not isinstance(other, _TypeAlias):
return NotImplemented
return self.name == other.name and self.type_var == other.type_var
def __hash__(self):
return hash((self.name, self.type_var))
def __instancecheck__(self, obj): def __instancecheck__(self, obj):
raise TypeError("Type aliases cannot be used with isinstance().") if not isinstance(self.type_var, TypeVar):
raise TypeError("Parameterized type aliases cannot be used "
"with isinstance().")
return isinstance(obj, self.impl_type)
def __subclasscheck__(self, cls): def __subclasscheck__(self, cls):
if cls is Any: if not isinstance(self.type_var, TypeVar):
return True raise TypeError("Parameterized type aliases cannot be used "
if isinstance(cls, _TypeAlias): "with issubclass().")
# Covariance. For now, we compare by name.
return (cls.name == self.name and
issubclass(cls.type_var, self.type_var))
else:
# Note that this is too lenient, because the
# implementation type doesn't carry information about
# whether it is about bytes or str (for example).
return issubclass(cls, self.impl_type) return issubclass(cls, self.impl_type)
def _get_type_vars(types, tvars): def _get_type_vars(types, tvars):
for t in types: for t in types:
if isinstance(t, TypingMeta) or isinstance(t, _ClassVar): if isinstance(t, TypingMeta) or isinstance(t, _TypingBase):
t._get_type_vars(tvars) t._get_type_vars(tvars)
...@@ -284,7 +328,7 @@ def _type_vars(types): ...@@ -284,7 +328,7 @@ def _type_vars(types):
def _eval_type(t, globalns, localns): def _eval_type(t, globalns, localns):
if isinstance(t, TypingMeta) or isinstance(t, _ClassVar): if isinstance(t, TypingMeta) or isinstance(t, _TypingBase):
return t._eval_type(globalns, localns) return t._eval_type(globalns, localns)
else: else:
return t return t
...@@ -306,7 +350,7 @@ def _type_check(arg, msg): ...@@ -306,7 +350,7 @@ def _type_check(arg, msg):
return type(None) return type(None)
if isinstance(arg, str): if isinstance(arg, str):
arg = _ForwardRef(arg) arg = _ForwardRef(arg)
if not isinstance(arg, (type, _TypeAlias)) and not callable(arg): if not isinstance(arg, (type, _TypingBase)) and not callable(arg):
raise TypeError(msg + " Got %.100r." % (arg,)) raise TypeError(msg + " Got %.100r." % (arg,))
return arg return arg
...@@ -328,23 +372,7 @@ def _type_repr(obj): ...@@ -328,23 +372,7 @@ def _type_repr(obj):
return repr(obj) return repr(obj)
class AnyMeta(TypingMeta): class _Any(_FinalTypingBase, _root=True):
"""Metaclass for Any."""
def __new__(cls, name, bases, namespace, _root=False):
self = super().__new__(cls, name, bases, namespace, _root=_root)
return self
def __instancecheck__(self, obj):
raise TypeError("Any cannot be used with isinstance().")
def __subclasscheck__(self, cls):
if not isinstance(cls, type):
return super().__subclasscheck__(cls) # To TypeError.
return True
class Any(Final, metaclass=AnyMeta, _root=True):
"""Special type indicating an unconstrained type. """Special type indicating an unconstrained type.
- Any object is an instance of Any. - Any object is an instance of Any.
...@@ -354,8 +382,17 @@ class Any(Final, metaclass=AnyMeta, _root=True): ...@@ -354,8 +382,17 @@ class Any(Final, metaclass=AnyMeta, _root=True):
__slots__ = () __slots__ = ()
def __instancecheck__(self, obj):
raise TypeError("Any cannot be used with isinstance().")
def __subclasscheck__(self, cls):
raise TypeError("Any cannot be used with issubclass().")
Any = _Any(_root=True)
class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True): class TypeVar(_TypingBase, _root=True):
"""Type variable. """Type variable.
Usage:: Usage::
...@@ -400,9 +437,14 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True): ...@@ -400,9 +437,14 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True):
A.__constraints__ == (str, bytes) A.__constraints__ == (str, bytes)
""" """
def __new__(cls, name, *constraints, bound=None, __slots__ = ('__name__', '__bound__', '__constraints__',
'__covariant__', '__contravariant__')
def __init__(self, name, *constraints, bound=None,
covariant=False, contravariant=False): covariant=False, contravariant=False):
self = super().__new__(cls, name, (Final,), {}, _root=True) super().__init__(name, *constraints, bound=bound,
covariant=covariant, contravariant=contravariant)
self.__name__ = name
if covariant and contravariant: if covariant and contravariant:
raise ValueError("Bivariant types are not supported.") raise ValueError("Bivariant types are not supported.")
self.__covariant__ = bool(covariant) self.__covariant__ = bool(covariant)
...@@ -417,7 +459,6 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True): ...@@ -417,7 +459,6 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True):
self.__bound__ = _type_check(bound, "Bound must be a type.") self.__bound__ = _type_check(bound, "Bound must be a type.")
else: else:
self.__bound__ = None self.__bound__ = None
return self
def _get_type_vars(self, tvars): def _get_type_vars(self, tvars):
if self not in tvars: if self not in tvars:
...@@ -436,16 +477,7 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True): ...@@ -436,16 +477,7 @@ class TypeVar(TypingMeta, metaclass=TypingMeta, _root=True):
raise TypeError("Type variables cannot be used with isinstance().") raise TypeError("Type variables cannot be used with isinstance().")
def __subclasscheck__(self, cls): def __subclasscheck__(self, cls):
# TODO: Make this raise TypeError too? raise TypeError("Type variables cannot be used with issubclass().")
if cls is self:
return True
if cls is Any:
return True
if self.__bound__ is not None:
return issubclass(cls, self.__bound__)
if self.__constraints__:
return any(issubclass(cls, c) for c in self.__constraints__)
return True
# Some unconstrained type variables. These are used by the container types. # Some unconstrained type variables. These are used by the container types.
...@@ -463,19 +495,85 @@ T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant. ...@@ -463,19 +495,85 @@ T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant.
AnyStr = TypeVar('AnyStr', bytes, str) AnyStr = TypeVar('AnyStr', bytes, str)
class UnionMeta(TypingMeta): def _tp_cache(func):
"""Metaclass for Union.""" cached = functools.lru_cache()(func)
@functools.wraps(func)
def inner(*args, **kwds):
try:
return cached(*args, **kwds)
except TypeError:
pass # Do not duplicate real errors.
return func(*args, **kwds)
return inner
class _Union(_FinalTypingBase, _root=True):
"""Union type; Union[X, Y] means either X or Y.
To define a union, use e.g. Union[int, str]. Details:
- The arguments must be types and there must be at least one.
- None as an argument is a special case and is replaced by
type(None).
- Unions of unions are flattened, e.g.::
Union[Union[int, str], float] == Union[int, str, float]
def __new__(cls, name, bases, namespace, parameters=None, _root=False): - Unions of a single argument vanish, e.g.::
Union[int] == int # The constructor actually returns int
- Redundant arguments are skipped, e.g.::
Union[int, str, int] == Union[int, str]
- When comparing unions, the argument order is ignored, e.g.::
Union[int, str] == Union[str, int]
- When two arguments have a subclass relationship, the least
derived argument is kept, e.g.::
class Employee: pass
class Manager(Employee): pass
Union[int, Employee, Manager] == Union[int, Employee]
Union[Manager, int, Employee] == Union[int, Employee]
Union[Employee, Manager] == Employee
- Corollary: if Any is present it is the sole survivor, e.g.::
Union[int, Any] == Any
- Similar for object::
Union[int, object] == object
- To cut a tie: Union[object, Any] == Union[Any, object] == Any.
- You cannot subclass or instantiate a union.
- You cannot write Union[X][Y] (what would it mean?).
- You can use Optional[X] as a shorthand for Union[X, None].
"""
__slots__ = ('__union_params__', '__union_set_params__')
def __new__(cls, parameters=None, *args, _root=False):
self = super().__new__(cls, parameters, *args, _root=_root)
if parameters is None: if parameters is None:
return super().__new__(cls, name, bases, namespace, _root=_root) self.__union_params__ = None
self.__union_set_params__ = None
return self
if not isinstance(parameters, tuple): if not isinstance(parameters, tuple):
raise TypeError("Expected parameters=<tuple>") raise TypeError("Expected parameters=<tuple>")
# Flatten out Union[Union[...], ...] and type-check non-Union args. # Flatten out Union[Union[...], ...] and type-check non-Union args.
params = [] params = []
msg = "Union[arg, ...]: each arg must be a type." msg = "Union[arg, ...]: each arg must be a type."
for p in parameters: for p in parameters:
if isinstance(p, UnionMeta): if isinstance(p, _Union):
params.extend(p.__union_params__) params.extend(p.__union_params__)
else: else:
params.append(_type_check(p, msg)) params.append(_type_check(p, msg))
...@@ -499,22 +597,16 @@ class UnionMeta(TypingMeta): ...@@ -499,22 +597,16 @@ class UnionMeta(TypingMeta):
for t1 in params: for t1 in params:
if t1 is Any: if t1 is Any:
return Any return Any
if isinstance(t1, TypeVar):
continue
if isinstance(t1, _TypeAlias):
# _TypeAlias is not a real class.
continue
if not isinstance(t1, type): if not isinstance(t1, type):
assert callable(t1) # A callable might sneak through.
continue continue
if any(isinstance(t2, type) and issubclass(t1, t2) if any(isinstance(t2, type) and issubclass(t1, t2)
for t2 in all_params - {t1} if not isinstance(t2, TypeVar)): for t2 in all_params - {t1}
if not (isinstance(t2, GenericMeta) and
t2.__origin__ is not None)):
all_params.remove(t1) all_params.remove(t1)
# It's not a union if there's only one type left. # It's not a union if there's only one type left.
if len(all_params) == 1: if len(all_params) == 1:
return all_params.pop() return all_params.pop()
# Create a new class with these params.
self = super().__new__(cls, name, bases, {}, _root=True)
self.__union_params__ = tuple(t for t in params if t in all_params) self.__union_params__ = tuple(t for t in params if t in all_params)
self.__union_set_params__ = frozenset(self.__union_params__) self.__union_set_params__ = frozenset(self.__union_params__)
return self return self
...@@ -525,8 +617,7 @@ class UnionMeta(TypingMeta): ...@@ -525,8 +617,7 @@ class UnionMeta(TypingMeta):
if p == self.__union_params__: if p == self.__union_params__:
return self return self
else: else:
return self.__class__(self.__name__, self.__bases__, {}, return self.__class__(p, _root=True)
p, _root=True)
def _get_type_vars(self, tvars): def _get_type_vars(self, tvars):
if self.__union_params__: if self.__union_params__:
...@@ -539,6 +630,7 @@ class UnionMeta(TypingMeta): ...@@ -539,6 +630,7 @@ class UnionMeta(TypingMeta):
for t in self.__union_params__)) for t in self.__union_params__))
return r return r
@_tp_cache
def __getitem__(self, parameters): def __getitem__(self, parameters):
if self.__union_params__ is not None: if self.__union_params__ is not None:
raise TypeError( raise TypeError(
...@@ -547,11 +639,10 @@ class UnionMeta(TypingMeta): ...@@ -547,11 +639,10 @@ class UnionMeta(TypingMeta):
raise TypeError("Cannot take a Union of no types.") raise TypeError("Cannot take a Union of no types.")
if not isinstance(parameters, tuple): if not isinstance(parameters, tuple):
parameters = (parameters,) parameters = (parameters,)
return self.__class__(self.__name__, self.__bases__, return self.__class__(parameters, _root=True)
dict(self.__dict__), parameters, _root=True)
def __eq__(self, other): def __eq__(self, other):
if not isinstance(other, UnionMeta): if not isinstance(other, _Union):
return NotImplemented return NotImplemented
return self.__union_set_params__ == other.__union_set_params__ return self.__union_set_params__ == other.__union_set_params__
...@@ -562,110 +653,45 @@ class UnionMeta(TypingMeta): ...@@ -562,110 +653,45 @@ class UnionMeta(TypingMeta):
raise TypeError("Unions cannot be used with isinstance().") raise TypeError("Unions cannot be used with isinstance().")
def __subclasscheck__(self, cls): def __subclasscheck__(self, cls):
if cls is Any: raise TypeError("Unions cannot be used with issubclass().")
return True
if self.__union_params__ is None:
return isinstance(cls, UnionMeta)
elif isinstance(cls, UnionMeta):
if cls.__union_params__ is None:
return False
return all(issubclass(c, self) for c in (cls.__union_params__))
elif isinstance(cls, TypeVar):
if cls in self.__union_params__:
return True
if cls.__constraints__:
return issubclass(Union[cls.__constraints__], self)
return False
else:
return any(issubclass(cls, t) for t in self.__union_params__)
class Union(Final, metaclass=UnionMeta, _root=True): Union = _Union(_root=True)
"""Union type; Union[X, Y] means either X or Y.
To define a union, use e.g. Union[int, str]. Details:
- The arguments must be types and there must be at least one.
- None as an argument is a special case and is replaced by class _Optional(_FinalTypingBase, _root=True):
type(None). """Optional type.
- Unions of unions are flattened, e.g.::
Union[Union[int, str], float] == Union[int, str, float]
- Unions of a single argument vanish, e.g.::
Union[int] == int # The constructor actually returns int
- Redundant arguments are skipped, e.g.::
Union[int, str, int] == Union[int, str]
- When comparing unions, the argument order is ignored, e.g.::
Union[int, str] == Union[str, int]
- When two arguments have a subclass relationship, the least
derived argument is kept, e.g.::
class Employee: pass
class Manager(Employee): pass
Union[int, Employee, Manager] == Union[int, Employee]
Union[Manager, int, Employee] == Union[int, Employee]
Union[Employee, Manager] == Employee
- Corollary: if Any is present it is the sole survivor, e.g.::
Union[int, Any] == Any
- Similar for object::
Union[int, object] == object
- To cut a tie: Union[object, Any] == Union[Any, object] == Any.
- You cannot subclass or instantiate a union.
- You cannot write Union[X][Y] (what would it mean?).
- You can use Optional[X] as a shorthand for Union[X, None]. Optional[X] is equivalent to Union[X, type(None)].
""" """
# Unsubscripted Union type has params set to None. __slots__ = ()
__union_params__ = None
__union_set_params__ = None
class OptionalMeta(TypingMeta):
"""Metaclass for Optional."""
def __new__(cls, name, bases, namespace, _root=False):
return super().__new__(cls, name, bases, namespace, _root=_root)
@_tp_cache
def __getitem__(self, arg): def __getitem__(self, arg):
arg = _type_check(arg, "Optional[t] requires a single type.") arg = _type_check(arg, "Optional[t] requires a single type.")
return Union[arg, type(None)] return Union[arg, type(None)]
class Optional(Final, metaclass=OptionalMeta, _root=True): Optional = _Optional(_root=True)
"""Optional type.
Optional[X] is equivalent to Union[X, type(None)].
"""
__slots__ = () class _Tuple(_FinalTypingBase, _root=True):
"""Tuple type; Tuple[X, Y] is the cross-product type of X and Y.
Example: Tuple[T1, T2] is a tuple of two elements corresponding
to type variables T1 and T2. Tuple[int, float, str] is a tuple
of an int, a float and a string.
To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].
"""
class TupleMeta(TypingMeta): __slots__ = ('__tuple_params__', '__tuple_use_ellipsis__')
"""Metaclass for Tuple."""
def __new__(cls, name, bases, namespace, parameters=None, def __init__(self, parameters=None,
use_ellipsis=False, _root=False): use_ellipsis=False, _root=False):
self = super().__new__(cls, name, bases, namespace, _root=_root)
self.__tuple_params__ = parameters self.__tuple_params__ = parameters
self.__tuple_use_ellipsis__ = use_ellipsis self.__tuple_use_ellipsis__ = use_ellipsis
return self
def _get_type_vars(self, tvars): def _get_type_vars(self, tvars):
if self.__tuple_params__: if self.__tuple_params__:
...@@ -679,8 +705,7 @@ class TupleMeta(TypingMeta): ...@@ -679,8 +705,7 @@ class TupleMeta(TypingMeta):
if p == self.__tuple_params__: if p == self.__tuple_params__:
return self return self
else: else:
return self.__class__(self.__name__, self.__bases__, {}, return self.__class__(p, _root=True)
p, _root=True)
def __repr__(self): def __repr__(self):
r = super().__repr__() r = super().__repr__()
...@@ -694,6 +719,7 @@ class TupleMeta(TypingMeta): ...@@ -694,6 +719,7 @@ class TupleMeta(TypingMeta):
', '.join(params)) ', '.join(params))
return r return r
@_tp_cache
def __getitem__(self, parameters): def __getitem__(self, parameters):
if self.__tuple_params__ is not None: if self.__tuple_params__ is not None:
raise TypeError("Cannot re-parameterize %r" % (self,)) raise TypeError("Cannot re-parameterize %r" % (self,))
...@@ -707,64 +733,50 @@ class TupleMeta(TypingMeta): ...@@ -707,64 +733,50 @@ class TupleMeta(TypingMeta):
use_ellipsis = False use_ellipsis = False
msg = "Tuple[t0, t1, ...]: each t must be a type." msg = "Tuple[t0, t1, ...]: each t must be a type."
parameters = tuple(_type_check(p, msg) for p in parameters) parameters = tuple(_type_check(p, msg) for p in parameters)
return self.__class__(self.__name__, self.__bases__, return self.__class__(parameters,
dict(self.__dict__), parameters,
use_ellipsis=use_ellipsis, _root=True) use_ellipsis=use_ellipsis, _root=True)
def __eq__(self, other): def __eq__(self, other):
if not isinstance(other, TupleMeta): if not isinstance(other, _Tuple):
return NotImplemented return NotImplemented
return (self.__tuple_params__ == other.__tuple_params__ and return (self.__tuple_params__ == other.__tuple_params__ and
self.__tuple_use_ellipsis__ == other.__tuple_use_ellipsis__) self.__tuple_use_ellipsis__ == other.__tuple_use_ellipsis__)
def __hash__(self): def __hash__(self):
return hash(self.__tuple_params__) return hash((self.__tuple_params__, self.__tuple_use_ellipsis__))
def __instancecheck__(self, obj): def __instancecheck__(self, obj):
raise TypeError("Tuples cannot be used with isinstance().") if self.__tuple_params__ == None:
return isinstance(obj, tuple)
raise TypeError("Parameterized Tuple cannot be used "
"with isinstance().")
def __subclasscheck__(self, cls): def __subclasscheck__(self, cls):
if cls is Any: if self.__tuple_params__ == None:
return True return issubclass(cls, tuple)
if not isinstance(cls, type): raise TypeError("Parameterized Tuple cannot be used "
return super().__subclasscheck__(cls) # To TypeError. "with issubclass().")
if issubclass(cls, tuple):
return True # Special case.
if not isinstance(cls, TupleMeta):
return super().__subclasscheck__(cls) # False.
if self.__tuple_params__ is None:
return True
if cls.__tuple_params__ is None:
return False # ???
if cls.__tuple_use_ellipsis__ != self.__tuple_use_ellipsis__:
return False
# Covariance.
return (len(self.__tuple_params__) == len(cls.__tuple_params__) and
all(issubclass(x, p)
for x, p in zip(cls.__tuple_params__,
self.__tuple_params__)))
class Tuple(Final, metaclass=TupleMeta, _root=True): Tuple = _Tuple(_root=True)
"""Tuple type; Tuple[X, Y] is the cross-product type of X and Y.
Example: Tuple[T1, T2] is a tuple of two elements corresponding
to type variables T1 and T2. Tuple[int, float, str] is a tuple
of an int, a float and a string.
To specify a variable-length tuple of homogeneous type, use Sequence[T]. class _Callable(_FinalTypingBase, _root=True):
""" """Callable type; Callable[[int], str] is a function of (int) -> str.
__slots__ = () The subscription syntax must always be used with exactly two
values: the argument list and the return type. The argument list
must be a list of types; the return type must be a single type.
There is no syntax to indicate optional or keyword arguments,
such function types are rarely used as callback types.
"""
class CallableMeta(TypingMeta): __slots__ = ('__args__', '__result__')
"""Metaclass for Callable."""
def __new__(cls, name, bases, namespace, _root=False, def __init__(self, args=None, result=None, _root=False):
args=None, result=None):
if args is None and result is None: if args is None and result is None:
pass # Must be 'class Callable'. pass
else: else:
if args is not Ellipsis: if args is not Ellipsis:
if not isinstance(args, list): if not isinstance(args, list):
...@@ -775,10 +787,8 @@ class CallableMeta(TypingMeta): ...@@ -775,10 +787,8 @@ class CallableMeta(TypingMeta):
args = tuple(_type_check(arg, msg) for arg in args) args = tuple(_type_check(arg, msg) for arg in args)
msg = "Callable[args, result]: result must be a type." msg = "Callable[args, result]: result must be a type."
result = _type_check(result, msg) result = _type_check(result, msg)
self = super().__new__(cls, name, bases, namespace, _root=_root)
self.__args__ = args self.__args__ = args
self.__result__ = result self.__result__ = result
return self
def _get_type_vars(self, tvars): def _get_type_vars(self, tvars):
if self.__args__ and self.__args__ is not Ellipsis: if self.__args__ and self.__args__ is not Ellipsis:
...@@ -795,8 +805,7 @@ class CallableMeta(TypingMeta): ...@@ -795,8 +805,7 @@ class CallableMeta(TypingMeta):
if args == self.__args__ and result == self.__result__: if args == self.__args__ and result == self.__result__:
return self return self
else: else:
return self.__class__(self.__name__, self.__bases__, {}, return self.__class__(args, result, _root=True)
args=args, result=result, _root=True)
def __repr__(self): def __repr__(self):
r = super().__repr__() r = super().__repr__()
...@@ -816,12 +825,10 @@ class CallableMeta(TypingMeta): ...@@ -816,12 +825,10 @@ class CallableMeta(TypingMeta):
raise TypeError( raise TypeError(
"Callable must be used as Callable[[arg, ...], result].") "Callable must be used as Callable[[arg, ...], result].")
args, result = parameters args, result = parameters
return self.__class__(self.__name__, self.__bases__, return self.__class__(args, result, _root=True)
dict(self.__dict__), _root=True,
args=args, result=result)
def __eq__(self, other): def __eq__(self, other):
if not isinstance(other, CallableMeta): if not isinstance(other, _Callable):
return NotImplemented return NotImplemented
return (self.__args__ == other.__args__ and return (self.__args__ == other.__args__ and
self.__result__ == other.__result__) self.__result__ == other.__result__)
...@@ -836,31 +843,18 @@ class CallableMeta(TypingMeta): ...@@ -836,31 +843,18 @@ class CallableMeta(TypingMeta):
if self.__args__ is None and self.__result__ is None: if self.__args__ is None and self.__result__ is None:
return isinstance(obj, collections_abc.Callable) return isinstance(obj, collections_abc.Callable)
else: else:
raise TypeError("Callable[] cannot be used with isinstance().") raise TypeError("Parameterized Callable cannot be used "
"with isinstance().")
def __subclasscheck__(self, cls): def __subclasscheck__(self, cls):
if cls is Any:
return True
if not isinstance(cls, CallableMeta):
return super().__subclasscheck__(cls)
if self.__args__ is None and self.__result__ is None: if self.__args__ is None and self.__result__ is None:
return True return issubclass(cls, collections_abc.Callable)
# We're not doing covariance or contravariance -- this is *invariance*. else:
return self == cls raise TypeError("Parameterized Callable cannot be used "
"with issubclass().")
class Callable(Final, metaclass=CallableMeta, _root=True):
"""Callable type; Callable[[int], str] is a function of (int) -> str.
The subscription syntax must always be used with exactly two
values: the argument list and the return type. The argument list
must be a list of types; the return type must be a single type.
There is no syntax to indicate optional or keyword arguments,
such function types are rarely used as callback types.
"""
__slots__ = () Callable = _Callable(_root=True)
def _gorg(a): def _gorg(a):
...@@ -985,6 +979,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta): ...@@ -985,6 +979,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
def __hash__(self): def __hash__(self):
return hash((self.__name__, self.__parameters__)) return hash((self.__name__, self.__parameters__))
@_tp_cache
def __getitem__(self, params): def __getitem__(self, params):
if not isinstance(params, tuple): if not isinstance(params, tuple):
params = (params,) params = (params,)
...@@ -1040,44 +1035,18 @@ class GenericMeta(TypingMeta, abc.ABCMeta): ...@@ -1040,44 +1035,18 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
return self.__subclasscheck__(instance.__class__) return self.__subclasscheck__(instance.__class__)
def __subclasscheck__(self, cls): def __subclasscheck__(self, cls):
if cls is Any: if self is Generic:
return True raise TypeError("Class %r cannot be used with class "
if isinstance(cls, GenericMeta): "or instance checks" % self)
# For a covariant class C(Generic[T]), if (self.__origin__ is not None and
# C[X] is a subclass of C[Y] iff X is a subclass of Y. sys._getframe(1).f_globals['__name__'] != 'abc'):
origin = self.__origin__ raise TypeError("Parameterized generics cannot be used with class "
if origin is not None and origin is cls.__origin__: "or instance checks")
assert len(self.__args__) == len(origin.__parameters__)
assert len(cls.__args__) == len(origin.__parameters__)
for p_self, p_cls, p_origin in zip(self.__args__,
cls.__args__,
origin.__parameters__):
if isinstance(p_origin, TypeVar):
if p_origin.__covariant__:
# Covariant -- p_cls must be a subclass of p_self.
if not issubclass(p_cls, p_self):
break
elif p_origin.__contravariant__:
# Contravariant. I think it's the opposite. :-)
if not issubclass(p_self, p_cls):
break
else:
# Invariant -- p_cls and p_self must equal.
if p_self != p_cls:
break
else:
# If the origin's parameter is not a typevar,
# insist on invariance.
if p_self != p_cls:
break
else:
return True
# If we break out of the loop, the superclass gets a chance.
if super().__subclasscheck__(cls): if super().__subclasscheck__(cls):
return True return True
if self.__extra__ is None or isinstance(cls, GenericMeta): if self.__extra__ is not None:
return False
return issubclass(cls, self.__extra__) return issubclass(cls, self.__extra__)
return False
# Prevent checks for Generic to crash when defining Generic. # Prevent checks for Generic to crash when defining Generic.
...@@ -1117,7 +1086,7 @@ class Generic(metaclass=GenericMeta): ...@@ -1117,7 +1086,7 @@ class Generic(metaclass=GenericMeta):
return obj return obj
class _ClassVar(metaclass=TypingMeta, _root=True): class _ClassVar(_FinalTypingBase, _root=True):
"""Special type construct to mark class variables. """Special type construct to mark class variables.
An annotation wrapped in ClassVar indicates that a given An annotation wrapped in ClassVar indicates that a given
...@@ -1134,36 +1103,35 @@ class _ClassVar(metaclass=TypingMeta, _root=True): ...@@ -1134,36 +1103,35 @@ class _ClassVar(metaclass=TypingMeta, _root=True):
be used with isinstance() or issubclass(). be used with isinstance() or issubclass().
""" """
def __init__(self, tp=None, _root=False): __slots__ = ('__type__',)
cls = type(self)
if _root: def __init__(self, tp=None, **kwds):
self.__type__ = tp self.__type__ = tp
else:
raise TypeError('Cannot initialize {}'.format(cls.__name__[1:]))
def __getitem__(self, item): def __getitem__(self, item):
cls = type(self) cls = type(self)
if self.__type__ is None: if self.__type__ is None:
return cls(_type_check(item, return cls(_type_check(item,
'{} accepts only types.'.format(cls.__name__[1:])), '{} accepts only single type.'.format(cls.__name__[1:])),
_root=True) _root=True)
raise TypeError('{} cannot be further subscripted' raise TypeError('{} cannot be further subscripted'
.format(cls.__name__[1:])) .format(cls.__name__[1:]))
def _eval_type(self, globalns, localns): def _eval_type(self, globalns, localns):
return type(self)(_eval_type(self.__type__, globalns, localns), new_tp = _eval_type(self.__type__, globalns, localns)
_root=True) if new_tp == self.__type__:
return self
return type(self)(new_tp, _root=True)
def _get_type_vars(self, tvars): def _get_type_vars(self, tvars):
if self.__type__: if self.__type__:
_get_type_vars(self.__type__, tvars) _get_type_vars(self.__type__, tvars)
def __repr__(self): def __repr__(self):
cls = type(self) r = super().__repr__()
if not self.__type__: if self.__type__ is not None:
return '{}.{}'.format(cls.__module__, cls.__name__[1:]) r += '[{}]'.format(_type_repr(self.__type__))
return '{}.{}[{}]'.format(cls.__module__, cls.__name__[1:], return r
_type_repr(self.__type__))
def __hash__(self): def __hash__(self):
return hash((type(self).__name__, self.__type__)) return hash((type(self).__name__, self.__type__))
...@@ -1614,52 +1582,52 @@ if hasattr(collections_abc, 'Collection'): ...@@ -1614,52 +1582,52 @@ if hasattr(collections_abc, 'Collection'):
if hasattr(collections_abc, 'Collection'): if hasattr(collections_abc, 'Collection'):
class AbstractSet(Collection[T_co], class AbstractSet(Collection[T_co],
extra=collections_abc.Set): extra=collections_abc.Set):
pass __slots__ = ()
else: else:
class AbstractSet(Sized, Iterable[T_co], Container[T_co], class AbstractSet(Sized, Iterable[T_co], Container[T_co],
extra=collections_abc.Set): extra=collections_abc.Set):
pass __slots__ = ()
class MutableSet(AbstractSet[T], extra=collections_abc.MutableSet): class MutableSet(AbstractSet[T], extra=collections_abc.MutableSet):
pass __slots__ = ()
# NOTE: It is only covariant in the value type. # NOTE: It is only covariant in the value type.
if hasattr(collections_abc, 'Collection'): if hasattr(collections_abc, 'Collection'):
class Mapping(Collection[KT], Generic[KT, VT_co], class Mapping(Collection[KT], Generic[KT, VT_co],
extra=collections_abc.Mapping): extra=collections_abc.Mapping):
pass __slots__ = ()
else: else:
class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co], class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co],
extra=collections_abc.Mapping): extra=collections_abc.Mapping):
pass __slots__ = ()
class MutableMapping(Mapping[KT, VT], extra=collections_abc.MutableMapping): class MutableMapping(Mapping[KT, VT], extra=collections_abc.MutableMapping):
pass __slots__ = ()
if hasattr(collections_abc, 'Reversible'): if hasattr(collections_abc, 'Reversible'):
if hasattr(collections_abc, 'Collection'): if hasattr(collections_abc, 'Collection'):
class Sequence(Reversible[T_co], Collection[T_co], class Sequence(Reversible[T_co], Collection[T_co],
extra=collections_abc.Sequence): extra=collections_abc.Sequence):
pass __slots__ = ()
else: else:
class Sequence(Sized, Reversible[T_co], Container[T_co], class Sequence(Sized, Reversible[T_co], Container[T_co],
extra=collections_abc.Sequence): extra=collections_abc.Sequence):
pass __slots__ = ()
else: else:
class Sequence(Sized, Iterable[T_co], Container[T_co], class Sequence(Sized, Iterable[T_co], Container[T_co],
extra=collections_abc.Sequence): extra=collections_abc.Sequence):
pass __slots__ = ()
class MutableSequence(Sequence[T], extra=collections_abc.MutableSequence): class MutableSequence(Sequence[T], extra=collections_abc.MutableSequence):
pass __slots__ = ()
class ByteString(Sequence[int], extra=collections_abc.ByteString): class ByteString(Sequence[int], extra=collections_abc.ByteString):
pass __slots__ = ()
ByteString.register(type(memoryview(b''))) ByteString.register(type(memoryview(b'')))
...@@ -1667,6 +1635,8 @@ ByteString.register(type(memoryview(b''))) ...@@ -1667,6 +1635,8 @@ ByteString.register(type(memoryview(b'')))
class List(list, MutableSequence[T], extra=list): class List(list, MutableSequence[T], extra=list):
__slots__ = ()
def __new__(cls, *args, **kwds): def __new__(cls, *args, **kwds):
if _geqv(cls, List): if _geqv(cls, List):
raise TypeError("Type List cannot be instantiated; " raise TypeError("Type List cannot be instantiated; "
...@@ -1676,6 +1646,8 @@ class List(list, MutableSequence[T], extra=list): ...@@ -1676,6 +1646,8 @@ class List(list, MutableSequence[T], extra=list):
class Set(set, MutableSet[T], extra=set): class Set(set, MutableSet[T], extra=set):
__slots__ = ()
def __new__(cls, *args, **kwds): def __new__(cls, *args, **kwds):
if _geqv(cls, Set): if _geqv(cls, Set):
raise TypeError("Type Set cannot be instantiated; " raise TypeError("Type Set cannot be instantiated; "
...@@ -1683,22 +1655,7 @@ class Set(set, MutableSet[T], extra=set): ...@@ -1683,22 +1655,7 @@ class Set(set, MutableSet[T], extra=set):
return set.__new__(cls, *args, **kwds) return set.__new__(cls, *args, **kwds)
class _FrozenSetMeta(GenericMeta): class FrozenSet(frozenset, AbstractSet[T_co], extra=frozenset):
"""This metaclass ensures set is not a subclass of FrozenSet.
Without this metaclass, set would be considered a subclass of
FrozenSet, because FrozenSet.__extra__ is collections.abc.Set, and
set is a subclass of that.
"""
def __subclasscheck__(self, cls):
if issubclass(cls, Set):
return False
return super().__subclasscheck__(cls)
class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta,
extra=frozenset):
__slots__ = () __slots__ = ()
def __new__(cls, *args, **kwds): def __new__(cls, *args, **kwds):
...@@ -1709,23 +1666,23 @@ class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta, ...@@ -1709,23 +1666,23 @@ class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta,
class MappingView(Sized, Iterable[T_co], extra=collections_abc.MappingView): class MappingView(Sized, Iterable[T_co], extra=collections_abc.MappingView):
pass __slots__ = ()
class KeysView(MappingView[KT], AbstractSet[KT], class KeysView(MappingView[KT], AbstractSet[KT],
extra=collections_abc.KeysView): extra=collections_abc.KeysView):
pass __slots__ = ()
class ItemsView(MappingView[Tuple[KT, VT_co]], class ItemsView(MappingView[Tuple[KT, VT_co]],
AbstractSet[Tuple[KT, VT_co]], AbstractSet[Tuple[KT, VT_co]],
Generic[KT, VT_co], Generic[KT, VT_co],
extra=collections_abc.ItemsView): extra=collections_abc.ItemsView):
pass __slots__ = ()
class ValuesView(MappingView[VT_co], extra=collections_abc.ValuesView): class ValuesView(MappingView[VT_co], extra=collections_abc.ValuesView):
pass __slots__ = ()
if hasattr(contextlib, 'AbstractContextManager'): if hasattr(contextlib, 'AbstractContextManager'):
...@@ -1736,6 +1693,8 @@ if hasattr(contextlib, 'AbstractContextManager'): ...@@ -1736,6 +1693,8 @@ if hasattr(contextlib, 'AbstractContextManager'):
class Dict(dict, MutableMapping[KT, VT], extra=dict): class Dict(dict, MutableMapping[KT, VT], extra=dict):
__slots__ = ()
def __new__(cls, *args, **kwds): def __new__(cls, *args, **kwds):
if _geqv(cls, Dict): if _geqv(cls, Dict):
raise TypeError("Type Dict cannot be instantiated; " raise TypeError("Type Dict cannot be instantiated; "
...@@ -1745,6 +1704,8 @@ class Dict(dict, MutableMapping[KT, VT], extra=dict): ...@@ -1745,6 +1704,8 @@ class Dict(dict, MutableMapping[KT, VT], extra=dict):
class DefaultDict(collections.defaultdict, MutableMapping[KT, VT], class DefaultDict(collections.defaultdict, MutableMapping[KT, VT],
extra=collections.defaultdict): extra=collections.defaultdict):
__slots__ = ()
def __new__(cls, *args, **kwds): def __new__(cls, *args, **kwds):
if _geqv(cls, DefaultDict): if _geqv(cls, DefaultDict):
raise TypeError("Type DefaultDict cannot be instantiated; " raise TypeError("Type DefaultDict cannot be instantiated; "
...@@ -1800,6 +1761,8 @@ class Type(Generic[CT_co], extra=type): ...@@ -1800,6 +1761,8 @@ class Type(Generic[CT_co], extra=type):
At this point the type checker knows that joe has type BasicUser. At this point the type checker knows that joe has type BasicUser.
""" """
__slots__ = ()
def _make_nmtuple(name, types): def _make_nmtuple(name, types):
nm_tpl = collections.namedtuple(name, [n for n, t in types]) nm_tpl = collections.namedtuple(name, [n for n, t in types])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment