from typing import TypeVar, AnyStr
from typing import T, KT, VT # Not in __all__.
from typing import Union, Optional
-from typing import Tuple, List
+from typing import Tuple, List, MutableMapping
from typing import Callable
from typing import Generic, ClassVar
from typing import cast
from typing import IO, TextIO, BinaryIO
from typing import Pattern, Match
import typing
+try:
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc # Fallback for PY3.2.
class BaseTestCase(TestCase):
with self.assertRaises(TypeError):
isinstance(42, Any)
- def test_any_subclass(self):
- self.assertTrue(issubclass(Employee, Any))
- self.assertTrue(issubclass(int, Any))
- self.assertTrue(issubclass(type(None), Any))
- self.assertTrue(issubclass(object, Any))
-
- 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_any_subclass_type_error(self):
+ with self.assertRaises(TypeError):
+ issubclass(Employee, Any)
+ with self.assertRaises(TypeError):
+ issubclass(Any, Employee)
def test_repr(self):
self.assertEqual(repr(Any), 'typing.Any')
with self.assertRaises(TypeError):
class A(Any):
pass
+ with self.assertRaises(TypeError):
+ class A(type(Any)):
+ pass
def test_cannot_instantiate(self):
with self.assertRaises(TypeError):
Any()
+ with self.assertRaises(TypeError):
+ type(Any)()
def test_cannot_subscript(self):
with self.assertRaises(TypeError):
Any[int]
- def test_any_is_subclass(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])
+ def test_any_works_with_alias(self):
# These expressions must simply not fail.
typing.Match[Any]
typing.Pattern[Any]
def test_basic_plain(self):
T = TypeVar('T')
- # Every class is a subclass of T.
- self.assertIsSubclass(int, T)
- self.assertIsSubclass(str, T)
# T equals itself.
self.assertEqual(T, T)
- # T is a subclass of itself.
- self.assertIsSubclass(T, T)
# T is an instance of TypeVar
self.assertIsInstance(T, TypeVar)
with self.assertRaises(TypeError):
isinstance(42, T)
- def test_basic_constrained(self):
- A = TypeVar('A', str, bytes)
- # Only str and bytes are subclasses of A.
- self.assertIsSubclass(str, A)
- self.assertIsSubclass(bytes, A)
- self.assertNotIsSubclass(int, A)
- # A equals itself.
- self.assertEqual(A, A)
- # A is a subclass of itself.
- self.assertIsSubclass(A, A)
+ def test_typevar_subclass_type_error(self):
+ T = TypeVar('T')
+ with self.assertRaises(TypeError):
+ issubclass(int, T)
+ with self.assertRaises(TypeError):
+ issubclass(T, int)
def test_constrained_error(self):
with self.assertRaises(TypeError):
self.assertNotEqual(TypeVar('T'), TypeVar('T'))
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):
with self.assertRaises(TypeError):
class V(TypeVar('T')):
with self.assertRaises(TypeError):
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):
with self.assertRaises(TypeError):
TypeVar('X', bound=42)
def test_basics(self):
u = Union[int, float]
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):
u = Union[Any]
u2 = Union[float, int]
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):
t = Union[Employee]
self.assertIs(t, Employee)
u = Union[Employee, Manager]
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):
u = Union[int, float]
v = Union[u, Employee]
with self.assertRaises(TypeError):
class C(Union):
pass
+ with self.assertRaises(TypeError):
+ class C(type(Union)):
+ pass
with self.assertRaises(TypeError):
class C(Union[int, str]):
pass
def test_cannot_instantiate(self):
with self.assertRaises(TypeError):
Union()
+ with self.assertRaises(TypeError):
+ type(Union)()
u = Union[int, float]
with self.assertRaises(TypeError):
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):
o = Optional[int]
with self.assertRaises(TypeError):
Union[()]
- def test_issubclass_union(self):
- self.assertIsSubclass(Union[int, str], Union)
- self.assertNotIsSubclass(int, Union)
-
def test_union_instance_type_error(self):
with self.assertRaises(TypeError):
isinstance(42, Union[int, str])
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):
def test_basics(self):
- self.assertTrue(issubclass(Tuple[int, str], Tuple))
- self.assertTrue(issubclass(Tuple[int, str], Tuple[int, str]))
- self.assertFalse(issubclass(int, Tuple))
- self.assertFalse(issubclass(Tuple[float, str], Tuple[int, str]))
- self.assertFalse(issubclass(Tuple[int, str, int], Tuple[int, str]))
- self.assertFalse(issubclass(Tuple[int, str], Tuple[int, str, int]))
+ with self.assertRaises(TypeError):
+ issubclass(Tuple[int, str], Tuple)
+ with self.assertRaises(TypeError):
+ issubclass(Tuple, Tuple[int, str])
+ with self.assertRaises(TypeError):
+ issubclass(tuple, Tuple[int, str])
+
+ class TP(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):
self.assertEqual(Tuple[int], Tuple[int])
def test_tuple_instance_type_error(self):
with self.assertRaises(TypeError):
isinstance((0, 0), Tuple[int, int])
- with self.assertRaises(TypeError):
- 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, ...])
+ self.assertIsInstance((0, 0), Tuple)
def test_repr(self):
self.assertEqual(repr(Tuple), 'typing.Tuple')
class CallableTests(BaseTestCase):
def test_self_subclass(self):
- self.assertTrue(issubclass(Callable[[int], int], Callable))
- self.assertFalse(issubclass(Callable, Callable[[int], int]))
- self.assertTrue(issubclass(Callable[[int], int], Callable[[int], int]))
- 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]))
+ with self.assertRaises(TypeError):
+ self.assertTrue(issubclass(type(lambda x: x), Callable[[int], int]))
+ self.assertTrue(issubclass(type(lambda x: x), Callable))
def test_eq_hash(self):
self.assertEqual(Callable[[int], int], Callable[[int], int])
class C(Callable):
pass
+ with self.assertRaises(TypeError):
+
+ class C(type(Callable)):
+ pass
+
with self.assertRaises(TypeError):
class C(Callable[[int], int]):
def test_cannot_instantiate(self):
with self.assertRaises(TypeError):
Callable()
+ with self.assertRaises(TypeError):
+ type(Callable)()
c = Callable[[int], str]
with self.assertRaises(TypeError):
c()
+ with self.assertRaises(TypeError):
+ type(c)()
def test_callable_instance_works(self):
def f():
with self.assertRaises(TypeError):
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):
T = TypeVar('T')
S = TypeVar('S')
c.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):
global C # pickle wants to reference the class by name
T = TypeVar('T')
pass
def test_cannot_init(self):
+ with self.assertRaises(TypeError):
+ ClassVar()
with self.assertRaises(TypeError):
type(ClassVar)()
with self.assertRaises(TypeError):
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):
def test_basics(self):
# path and could fail. So call this a few times.
self.assertIsInstance([], typing.Iterable)
self.assertIsInstance([], typing.Iterable)
- self.assertIsInstance([], typing.Iterable[int])
self.assertNotIsInstance(42, typing.Iterable)
# Just in case, also test issubclass() a few times.
self.assertIsSubclass(list, typing.Iterable)
def test_iterator(self):
it = iter([])
self.assertIsInstance(it, typing.Iterator)
- self.assertIsInstance(it, typing.Iterator[int])
self.assertNotIsInstance(42, typing.Iterator)
@skipUnless(PY35, 'Python 3.5 required')
globals(), ns)
foo = ns['foo']
g = foo()
- self.assertIsSubclass(type(g), typing.Awaitable[int])
self.assertIsInstance(g, 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.
@skipUnless(PY35, 'Python 3.5 required')
it = AsyncIteratorWrapper(base_it)
self.assertIsInstance(it, typing.AsyncIterable)
self.assertIsInstance(it, typing.AsyncIterable)
- self.assertIsSubclass(typing.AsyncIterable[Manager],
- typing.AsyncIterable[Employee])
self.assertNotIsInstance(42, typing.AsyncIterable)
@skipUnless(PY35, 'Python 3.5 required')
base_it = range(10) # type: Iterator[int]
it = AsyncIteratorWrapper(base_it)
self.assertIsInstance(it, typing.AsyncIterator)
- self.assertIsSubclass(typing.AsyncIterator[Manager],
- typing.AsyncIterator[Employee])
self.assertNotIsInstance(42, typing.AsyncIterator)
def test_sized(self):
yield 42
g = foo()
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):
with self.assertRaises(TypeError):
cm = manager()
self.assertIsInstance(cm, typing.ContextManager)
- self.assertIsInstance(cm, typing.ContextManager[int])
self.assertNotIsInstance(42, typing.ContextManager)
pat = re.compile('[a-z]+', re.I)
self.assertIsSubclass(pat.__class__, Pattern)
self.assertIsSubclass(type(pat), Pattern)
- self.assertIsSubclass(type(pat), Pattern[str])
+ self.assertIsInstance(pat, Pattern)
mat = pat.search('12345abcde.....')
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[str])
+ self.assertIsInstance(mat, Match)
+ # these should just work
p = Pattern[Union[str, bytes]]
- self.assertIsSubclass(Pattern[str], Pattern)
- self.assertIsSubclass(Pattern[str], p)
-
m = Match[Union[bytes, str]]
- self.assertIsSubclass(Match[bytes], Match)
- self.assertIsSubclass(Match[bytes], m)
def test_errors(self):
with self.assertRaises(TypeError):
with self.assertRaises(TypeError):
# Too complicated?
m[str]
- with self.assertRaises(TypeError):
- # We don't support isinstance().
- isinstance(42, Pattern)
with self.assertRaises(TypeError):
# We don't support isinstance().
isinstance(42, Pattern[str])
pass
self.assertEqual(str(ex.exception),
- "A type alias cannot be subclassed")
+ "Cannot subclass typing._TypeAlias")
class AllTests(BaseTestCase):
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):
"""Metaclass for every type defined below.
pass
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)
+
+ # 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 Final:
+
+class _FinalTypingBase(_TypingBase, _root=True):
"""Mix-in class to prevent instantiation."""
__slots__ = ()
- def __new__(self, *args, **kwds):
- raise TypeError("Cannot instantiate %r" % self.__class__)
+ def __new__(cls, *args, _root=False, **kwds):
+ 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."""
- 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):
raise TypeError('ForwardRef must be a string -- got %r' % (arg,))
try:
except SyntaxError:
raise SyntaxError('ForwardRef must be an expression -- got %r' %
(arg,))
- self = super().__new__(cls, arg, (), {}, _root=True)
self.__forward_arg__ = arg
self.__forward_code__ = code
self.__forward_evaluated__ = False
frame = frame.f_back
assert frame is not None
self.__forward_frame__ = frame
- return self
def _eval_type(self, globalns, localns):
if not self.__forward_evaluated__:
self.__forward_evaluated__ = True
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):
raise TypeError("Forward references cannot be used with isinstance().")
def __subclasscheck__(self, cls):
- if not self.__forward_evaluated__:
- 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__)
+ raise TypeError("Forward references cannot be used with issubclass().")
def __repr__(self):
return '_ForwardRef(%r)' % (self.__forward_arg__,)
-class _TypeAlias:
+class _TypeAlias(_TypingBase, _root=True):
"""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
- be used in instance and subclass checks, e.g. isinstance(m, Match)
- or issubclass(type(m), Match). However, it cannot be itself the
- target of an issubclass() call; e.g. issubclass(Match, C) (for
- some arbitrary class C) raises TypeError rather than returning
- False.
+ Note that this is not a type; let's call it a pseudo-type. It cannot
+ be used in instance and subclass checks in parameterized form, i.e.
+ ``isinstance(42, Match[str])`` raises ``TypeError`` instead of returning
+ ``False``.
"""
__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):
"""Initializer.
and returns a value that should be a type_var instance.
"""
assert isinstance(name, str), repr(name)
- assert isinstance(type_var, type), repr(type_var)
assert isinstance(impl_type, type), repr(impl_type)
assert not isinstance(impl_type, TypingMeta), repr(impl_type)
+ assert isinstance(type_var, (type, _TypingBase))
self.name = name
self.type_var = type_var
self.impl_type = impl_type
return "%s[%s]" % (self.name, _type_repr(self.type_var))
def __getitem__(self, parameter):
- assert isinstance(parameter, type), repr(parameter)
if not isinstance(self.type_var, TypeVar):
raise TypeError("%s cannot be further parameterized." % self)
- if self.type_var.__constraints__:
- if not issubclass(parameter, Union[self.type_var.__constraints__]):
+ if self.type_var.__constraints__ and isinstance(parameter, type):
+ if not issubclass(parameter, self.type_var.__constraints__):
raise TypeError("%s is not a valid substitution for %s." %
(parameter, self.type_var))
+ if isinstance(parameter, TypeVar):
+ raise TypeError("%s cannot be re-parameterized." % self.type_var)
return self.__class__(self.name, parameter,
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):
- 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):
- if cls is Any:
- return True
- if isinstance(cls, _TypeAlias):
- # 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)
+ if not isinstance(self.type_var, TypeVar):
+ raise TypeError("Parameterized type aliases cannot be used "
+ "with issubclass().")
+ return issubclass(cls, self.impl_type)
def _get_type_vars(types, tvars):
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)
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)
else:
return t
return type(None)
if isinstance(arg, str):
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,))
return arg
return repr(obj)
-class AnyMeta(TypingMeta):
- """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):
+class _Any(_FinalTypingBase, _root=True):
"""Special type indicating an unconstrained type.
- Any object is an instance of Any.
__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.
Usage::
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):
- 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:
raise ValueError("Bivariant types are not supported.")
self.__covariant__ = bool(covariant)
self.__bound__ = _type_check(bound, "Bound must be a type.")
else:
self.__bound__ = None
- return self
def _get_type_vars(self, tvars):
if self not in tvars:
raise TypeError("Type variables cannot be used with isinstance().")
def __subclasscheck__(self, cls):
- # TODO: Make this raise TypeError too?
- 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
+ raise TypeError("Type variables cannot be used with issubclass().")
# Some unconstrained type variables. These are used by the container types.
AnyStr = TypeVar('AnyStr', bytes, str)
-class UnionMeta(TypingMeta):
- """Metaclass for Union."""
+def _tp_cache(func):
+ 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]
+
+ - 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.::
- def __new__(cls, name, bases, namespace, parameters=None, _root=False):
+ 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:
- 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):
raise TypeError("Expected parameters=<tuple>")
# Flatten out Union[Union[...], ...] and type-check non-Union args.
params = []
msg = "Union[arg, ...]: each arg must be a type."
for p in parameters:
- if isinstance(p, UnionMeta):
+ if isinstance(p, _Union):
params.extend(p.__union_params__)
else:
params.append(_type_check(p, msg))
for t1 in params:
if t1 is Any:
return Any
- if isinstance(t1, TypeVar):
- continue
- if isinstance(t1, _TypeAlias):
- # _TypeAlias is not a real class.
- continue
if not isinstance(t1, type):
- assert callable(t1) # A callable might sneak through.
continue
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)
# It's not a union if there's only one type left.
if len(all_params) == 1:
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_set_params__ = frozenset(self.__union_params__)
return self
if p == self.__union_params__:
return self
else:
- return self.__class__(self.__name__, self.__bases__, {},
- p, _root=True)
+ return self.__class__(p, _root=True)
def _get_type_vars(self, tvars):
if self.__union_params__:
for t in self.__union_params__))
return r
+ @_tp_cache
def __getitem__(self, parameters):
if self.__union_params__ is not None:
raise TypeError(
raise TypeError("Cannot take a Union of no types.")
if not isinstance(parameters, tuple):
parameters = (parameters,)
- return self.__class__(self.__name__, self.__bases__,
- dict(self.__dict__), parameters, _root=True)
+ return self.__class__(parameters, _root=True)
def __eq__(self, other):
- if not isinstance(other, UnionMeta):
+ if not isinstance(other, _Union):
return NotImplemented
return self.__union_set_params__ == other.__union_set_params__
raise TypeError("Unions cannot be used with isinstance().")
def __subclasscheck__(self, cls):
- if cls is Any:
- 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__)
+ raise TypeError("Unions cannot be used with issubclass().")
-class Union(Final, metaclass=UnionMeta, _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]
-
- - 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
+Union = _Union(_root=True)
- - 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?).
+class _Optional(_FinalTypingBase, _root=True):
+ """Optional type.
- - 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.
- __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)
+ __slots__ = ()
+ @_tp_cache
def __getitem__(self, arg):
arg = _type_check(arg, "Optional[t] requires a single type.")
return Union[arg, type(None)]
-class Optional(Final, metaclass=OptionalMeta, _root=True):
- """Optional type.
+Optional = _Optional(_root=True)
- 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):
- """Metaclass for Tuple."""
+ __slots__ = ('__tuple_params__', '__tuple_use_ellipsis__')
- def __new__(cls, name, bases, namespace, parameters=None,
+ def __init__(self, parameters=None,
use_ellipsis=False, _root=False):
- self = super().__new__(cls, name, bases, namespace, _root=_root)
self.__tuple_params__ = parameters
self.__tuple_use_ellipsis__ = use_ellipsis
- return self
def _get_type_vars(self, tvars):
if self.__tuple_params__:
if p == self.__tuple_params__:
return self
else:
- return self.__class__(self.__name__, self.__bases__, {},
- p, _root=True)
+ return self.__class__(p, _root=True)
def __repr__(self):
r = super().__repr__()
', '.join(params))
return r
+ @_tp_cache
def __getitem__(self, parameters):
if self.__tuple_params__ is not None:
raise TypeError("Cannot re-parameterize %r" % (self,))
use_ellipsis = False
msg = "Tuple[t0, t1, ...]: each t must be a type."
parameters = tuple(_type_check(p, msg) for p in parameters)
- return self.__class__(self.__name__, self.__bases__,
- dict(self.__dict__), parameters,
+ return self.__class__(parameters,
use_ellipsis=use_ellipsis, _root=True)
def __eq__(self, other):
- if not isinstance(other, TupleMeta):
+ if not isinstance(other, _Tuple):
return NotImplemented
return (self.__tuple_params__ == other.__tuple_params__ and
self.__tuple_use_ellipsis__ == other.__tuple_use_ellipsis__)
def __hash__(self):
- return hash(self.__tuple_params__)
+ return hash((self.__tuple_params__, self.__tuple_use_ellipsis__))
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):
- if cls is Any:
- return True
- if not isinstance(cls, type):
- return super().__subclasscheck__(cls) # To TypeError.
- 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 type; Tuple[X, Y] is the cross-product type of X and Y.
+ if self.__tuple_params__ == None:
+ return issubclass(cls, tuple)
+ raise TypeError("Parameterized Tuple cannot be used "
+ "with issubclass().")
- 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].
- """
+Tuple = _Tuple(_root=True)
- __slots__ = ()
+class _Callable(_FinalTypingBase, _root=True):
+ """Callable type; Callable[[int], str] is a function of (int) -> str.
-class CallableMeta(TypingMeta):
- """Metaclass for Callable."""
+ 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.
- def __new__(cls, name, bases, namespace, _root=False,
- args=None, result=None):
+ There is no syntax to indicate optional or keyword arguments,
+ such function types are rarely used as callback types.
+ """
+
+ __slots__ = ('__args__', '__result__')
+
+ def __init__(self, args=None, result=None, _root=False):
if args is None and result is None:
- pass # Must be 'class Callable'.
+ pass
else:
if args is not Ellipsis:
if not isinstance(args, list):
args = tuple(_type_check(arg, msg) for arg in args)
msg = "Callable[args, result]: result must be a type."
result = _type_check(result, msg)
- self = super().__new__(cls, name, bases, namespace, _root=_root)
self.__args__ = args
self.__result__ = result
- return self
def _get_type_vars(self, tvars):
if self.__args__ and self.__args__ is not Ellipsis:
if args == self.__args__ and result == self.__result__:
return self
else:
- return self.__class__(self.__name__, self.__bases__, {},
- args=args, result=result, _root=True)
+ return self.__class__(args, result, _root=True)
def __repr__(self):
r = super().__repr__()
raise TypeError(
"Callable must be used as Callable[[arg, ...], result].")
args, result = parameters
- return self.__class__(self.__name__, self.__bases__,
- dict(self.__dict__), _root=True,
- args=args, result=result)
+ return self.__class__(args, result, _root=True)
def __eq__(self, other):
- if not isinstance(other, CallableMeta):
+ if not isinstance(other, _Callable):
return NotImplemented
return (self.__args__ == other.__args__ and
self.__result__ == other.__result__)
if self.__args__ is None and self.__result__ is None:
return isinstance(obj, collections_abc.Callable)
else:
- raise TypeError("Callable[] cannot be used with isinstance().")
+ raise TypeError("Parameterized Callable cannot be used "
+ "with isinstance().")
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:
- return True
- # We're not doing covariance or contravariance -- this is *invariance*.
- return self == cls
-
-
-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.
+ return issubclass(cls, collections_abc.Callable)
+ else:
+ raise TypeError("Parameterized Callable cannot be used "
+ "with issubclass().")
- 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 __hash__(self):
return hash((self.__name__, self.__parameters__))
+ @_tp_cache
def __getitem__(self, params):
if not isinstance(params, tuple):
params = (params,)
return self.__subclasscheck__(instance.__class__)
def __subclasscheck__(self, cls):
- if cls is Any:
- return True
- if isinstance(cls, GenericMeta):
- # For a covariant class C(Generic[T]),
- # C[X] is a subclass of C[Y] iff X is a subclass of Y.
- origin = self.__origin__
- if origin is not None and origin is cls.__origin__:
- 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 self is Generic:
+ raise TypeError("Class %r cannot be used with class "
+ "or instance checks" % self)
+ if (self.__origin__ is not None and
+ sys._getframe(1).f_globals['__name__'] != 'abc'):
+ raise TypeError("Parameterized generics cannot be used with class "
+ "or instance checks")
if super().__subclasscheck__(cls):
return True
- if self.__extra__ is None or isinstance(cls, GenericMeta):
- return False
- return issubclass(cls, self.__extra__)
+ if self.__extra__ is not None:
+ return issubclass(cls, self.__extra__)
+ return False
# Prevent checks for Generic to crash when defining Generic.
return obj
-class _ClassVar(metaclass=TypingMeta, _root=True):
+class _ClassVar(_FinalTypingBase, _root=True):
"""Special type construct to mark class variables.
An annotation wrapped in ClassVar indicates that a given
be used with isinstance() or issubclass().
"""
- def __init__(self, tp=None, _root=False):
- cls = type(self)
- if _root:
- self.__type__ = tp
- else:
- raise TypeError('Cannot initialize {}'.format(cls.__name__[1:]))
+ __slots__ = ('__type__',)
+
+ def __init__(self, tp=None, **kwds):
+ self.__type__ = tp
def __getitem__(self, item):
cls = type(self)
if self.__type__ is None:
return cls(_type_check(item,
- '{} accepts only types.'.format(cls.__name__[1:])),
+ '{} accepts only single type.'.format(cls.__name__[1:])),
_root=True)
raise TypeError('{} cannot be further subscripted'
.format(cls.__name__[1:]))
def _eval_type(self, globalns, localns):
- return type(self)(_eval_type(self.__type__, globalns, localns),
- _root=True)
+ new_tp = _eval_type(self.__type__, globalns, localns)
+ if new_tp == self.__type__:
+ return self
+ return type(self)(new_tp, _root=True)
def _get_type_vars(self, tvars):
if self.__type__:
_get_type_vars(self.__type__, tvars)
def __repr__(self):
- cls = type(self)
- if not self.__type__:
- return '{}.{}'.format(cls.__module__, cls.__name__[1:])
- return '{}.{}[{}]'.format(cls.__module__, cls.__name__[1:],
- _type_repr(self.__type__))
+ r = super().__repr__()
+ if self.__type__ is not None:
+ r += '[{}]'.format(_type_repr(self.__type__))
+ return r
def __hash__(self):
return hash((type(self).__name__, self.__type__))
if hasattr(collections_abc, 'Collection'):
class AbstractSet(Collection[T_co],
extra=collections_abc.Set):
- pass
+ __slots__ = ()
else:
class AbstractSet(Sized, Iterable[T_co], Container[T_co],
extra=collections_abc.Set):
- pass
+ __slots__ = ()
class MutableSet(AbstractSet[T], extra=collections_abc.MutableSet):
- pass
+ __slots__ = ()
# NOTE: It is only covariant in the value type.
if hasattr(collections_abc, 'Collection'):
class Mapping(Collection[KT], Generic[KT, VT_co],
extra=collections_abc.Mapping):
- pass
+ __slots__ = ()
else:
class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co],
extra=collections_abc.Mapping):
- pass
+ __slots__ = ()
class MutableMapping(Mapping[KT, VT], extra=collections_abc.MutableMapping):
- pass
+ __slots__ = ()
if hasattr(collections_abc, 'Reversible'):
if hasattr(collections_abc, 'Collection'):
class Sequence(Reversible[T_co], Collection[T_co],
extra=collections_abc.Sequence):
- pass
+ __slots__ = ()
else:
class Sequence(Sized, Reversible[T_co], Container[T_co],
extra=collections_abc.Sequence):
- pass
+ __slots__ = ()
else:
class Sequence(Sized, Iterable[T_co], Container[T_co],
extra=collections_abc.Sequence):
- pass
+ __slots__ = ()
class MutableSequence(Sequence[T], extra=collections_abc.MutableSequence):
- pass
+ __slots__ = ()
class ByteString(Sequence[int], extra=collections_abc.ByteString):
- pass
+ __slots__ = ()
ByteString.register(type(memoryview(b'')))
class List(list, MutableSequence[T], extra=list):
+ __slots__ = ()
+
def __new__(cls, *args, **kwds):
if _geqv(cls, List):
raise TypeError("Type List cannot be instantiated; "
class Set(set, MutableSet[T], extra=set):
+ __slots__ = ()
+
def __new__(cls, *args, **kwds):
if _geqv(cls, Set):
raise TypeError("Type Set cannot be instantiated; "
return set.__new__(cls, *args, **kwds)
-class _FrozenSetMeta(GenericMeta):
- """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):
+class FrozenSet(frozenset, AbstractSet[T_co], extra=frozenset):
__slots__ = ()
def __new__(cls, *args, **kwds):
class MappingView(Sized, Iterable[T_co], extra=collections_abc.MappingView):
- pass
+ __slots__ = ()
class KeysView(MappingView[KT], AbstractSet[KT],
extra=collections_abc.KeysView):
- pass
+ __slots__ = ()
class ItemsView(MappingView[Tuple[KT, VT_co]],
AbstractSet[Tuple[KT, VT_co]],
Generic[KT, VT_co],
extra=collections_abc.ItemsView):
- pass
+ __slots__ = ()
class ValuesView(MappingView[VT_co], extra=collections_abc.ValuesView):
- pass
+ __slots__ = ()
if hasattr(contextlib, 'AbstractContextManager'):
class Dict(dict, MutableMapping[KT, VT], extra=dict):
+ __slots__ = ()
+
def __new__(cls, *args, **kwds):
if _geqv(cls, Dict):
raise TypeError("Type Dict cannot be instantiated; "
class DefaultDict(collections.defaultdict, MutableMapping[KT, VT],
extra=collections.defaultdict):
+ __slots__ = ()
+
def __new__(cls, *args, **kwds):
if _geqv(cls, DefaultDict):
raise TypeError("Type DefaultDict cannot be instantiated; "
At this point the type checker knows that joe has type BasicUser.
"""
+ __slots__ = ()
+
def _make_nmtuple(name, types):
nm_tpl = collections.namedtuple(name, [n for n, t in types])