aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/deprecated/python/typing/test/test_typing.py
diff options
context:
space:
mode:
authornkozlovskiy <nmk@ydb.tech>2023-10-02 18:57:38 +0300
committernkozlovskiy <nmk@ydb.tech>2023-10-02 19:39:06 +0300
commit6295ef4d23465c11296e898b9dc4524ad9592b5d (patch)
treefc0c852877b2c52f365a1f6ed0710955844338c2 /contrib/deprecated/python/typing/test/test_typing.py
parentde63c80b75948ecc13894854514d147840ff8430 (diff)
downloadydb-6295ef4d23465c11296e898b9dc4524ad9592b5d.tar.gz
oss ydb: fix dstool building and test run
Diffstat (limited to 'contrib/deprecated/python/typing/test/test_typing.py')
-rw-r--r--contrib/deprecated/python/typing/test/test_typing.py2706
1 files changed, 2706 insertions, 0 deletions
diff --git a/contrib/deprecated/python/typing/test/test_typing.py b/contrib/deprecated/python/typing/test/test_typing.py
new file mode 100644
index 0000000000..2f260bac42
--- /dev/null
+++ b/contrib/deprecated/python/typing/test/test_typing.py
@@ -0,0 +1,2706 @@
+from __future__ import absolute_import, unicode_literals
+
+import collections
+import contextlib
+import os
+import pickle
+import re
+import subprocess
+import sys
+import abc
+import types
+from unittest import TestCase, main, SkipTest
+from copy import copy, deepcopy
+
+from typing import Any, NoReturn
+from typing import TypeVar, AnyStr
+from typing import T, KT, VT # Not in __all__.
+from typing import Union, Optional
+from typing import Tuple, List, MutableMapping
+from typing import Callable
+from typing import Generic, ClassVar, GenericMeta, Final, Literal
+from typing import cast
+from typing import Type, Protocol, runtime_checkable
+from typing import NewType
+from typing import NamedTuple, TypedDict
+from typing import Pattern, Match
+import typing
+import weakref
+import collections
+
+
+class BaseTestCase(TestCase):
+
+ def assertIsSubclass(self, cls, class_or_tuple, msg=None):
+ if not issubclass(cls, class_or_tuple):
+ message = '%r is not a subclass of %r' % (cls, class_or_tuple)
+ if msg is not None:
+ message += ' : %s' % msg
+ raise self.failureException(message)
+
+ def assertNotIsSubclass(self, cls, class_or_tuple, msg=None):
+ if issubclass(cls, class_or_tuple):
+ message = '%r is a subclass of %r' % (cls, class_or_tuple)
+ if msg is not None:
+ message += ' : %s' % msg
+ raise self.failureException(message)
+
+ def clear_caches(self):
+ for f in typing._cleanups:
+ f()
+
+
+class Employee(object):
+ pass
+
+
+class Manager(Employee):
+ pass
+
+
+class Founder(Employee):
+ pass
+
+
+class ManagingFounder(Manager, Founder):
+ pass
+
+
+class AnyTests(BaseTestCase):
+
+ def test_any_instance_type_error(self):
+ with self.assertRaises(TypeError):
+ isinstance(42, Any)
+
+ 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')
+
+ def test_errors(self):
+ with self.assertRaises(TypeError):
+ issubclass(42, Any)
+ with self.assertRaises(TypeError):
+ Any[int] # Any is not a generic type.
+
+ def test_cannot_subclass(self):
+ 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_any_is_subclass(self):
+ # These expressions must simply not fail.
+ typing.Match[Any]
+ typing.Pattern[Any]
+ typing.IO[Any]
+
+
+class NoReturnTests(BaseTestCase):
+
+ def test_noreturn_instance_type_error(self):
+ with self.assertRaises(TypeError):
+ isinstance(42, NoReturn)
+
+ def test_noreturn_subclass_type_error(self):
+ with self.assertRaises(TypeError):
+ issubclass(Employee, NoReturn)
+ with self.assertRaises(TypeError):
+ issubclass(NoReturn, Employee)
+
+ def test_repr(self):
+ self.assertEqual(repr(NoReturn), 'typing.NoReturn')
+
+ def test_not_generic(self):
+ with self.assertRaises(TypeError):
+ NoReturn[int]
+
+ def test_cannot_subclass(self):
+ with self.assertRaises(TypeError):
+ class A(NoReturn):
+ pass
+ with self.assertRaises(TypeError):
+ class A(type(NoReturn)):
+ pass
+
+ def test_cannot_instantiate(self):
+ with self.assertRaises(TypeError):
+ NoReturn()
+ with self.assertRaises(TypeError):
+ type(NoReturn)()
+
+
+class TypeVarTests(BaseTestCase):
+
+ def test_basic_plain(self):
+ T = TypeVar('T')
+ # T equals itself.
+ self.assertEqual(T, T)
+ # T is an instance of TypeVar
+ self.assertIsInstance(T, TypeVar)
+
+ def test_typevar_instance_type_error(self):
+ T = TypeVar('T')
+ with self.assertRaises(TypeError):
+ isinstance(42, T)
+
+ 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):
+ X = TypeVar('X', int)
+ X
+
+ def test_union_unique(self):
+ X = TypeVar('X')
+ Y = TypeVar('Y')
+ self.assertNotEqual(X, Y)
+ self.assertEqual(Union[X], X)
+ self.assertNotEqual(Union[X], Union[X, Y])
+ self.assertEqual(Union[X, X], X)
+ self.assertNotEqual(Union[X, int], Union[X])
+ self.assertNotEqual(Union[X, int], Union[int])
+ self.assertEqual(Union[X, int].__args__, (X, int))
+ self.assertEqual(Union[X, int].__parameters__, (X,))
+ self.assertIs(Union[X, int].__origin__, Union)
+
+ def test_union_constrained(self):
+ A = TypeVar('A', str, bytes)
+ self.assertNotEqual(Union[A, str], Union[A])
+
+ def test_repr(self):
+ self.assertEqual(repr(T), '~T')
+ self.assertEqual(repr(KT), '~KT')
+ self.assertEqual(repr(VT), '~VT')
+ self.assertEqual(repr(AnyStr), '~AnyStr')
+ T_co = TypeVar('T_co', covariant=True)
+ self.assertEqual(repr(T_co), '+T_co')
+ T_contra = TypeVar('T_contra', contravariant=True)
+ self.assertEqual(repr(T_contra), '-T_contra')
+
+ def test_no_redefinition(self):
+ self.assertNotEqual(TypeVar('T'), TypeVar('T'))
+ self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str))
+
+ def test_cannot_subclass_vars(self):
+ with self.assertRaises(TypeError):
+ class V(TypeVar('T')):
+ pass
+
+ def test_cannot_subclass_var_itself(self):
+ with self.assertRaises(TypeError):
+ class V(TypeVar):
+ pass
+
+ def test_cannot_instantiate_vars(self):
+ with self.assertRaises(TypeError):
+ TypeVar('A')()
+
+ def test_bound_errors(self):
+ with self.assertRaises(TypeError):
+ TypeVar('X', bound=42)
+ with self.assertRaises(TypeError):
+ TypeVar('X', str, float, bound=Employee)
+
+ def test_no_bivariant(self):
+ with self.assertRaises(ValueError):
+ TypeVar('T', covariant=True, contravariant=True)
+
+
+class UnionTests(BaseTestCase):
+
+ def test_basics(self):
+ u = Union[int, float]
+ self.assertNotEqual(u, Union)
+
+ 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]
+ self.assertEqual(u, Any)
+ u1 = Union[int, Any]
+ u2 = Union[Any, int]
+ u3 = Union[Any, object]
+ self.assertEqual(u1, u2)
+ self.assertNotEqual(u1, Any)
+ self.assertNotEqual(u2, Any)
+ self.assertNotEqual(u3, Any)
+
+ def test_union_object(self):
+ u = Union[object]
+ self.assertEqual(u, object)
+ u = Union[int, object]
+ self.assertEqual(u, object)
+ u = Union[object, int]
+ self.assertEqual(u, object)
+
+ def test_unordered(self):
+ u1 = Union[int, float]
+ u2 = Union[float, int]
+ self.assertEqual(u1, u2)
+
+ def test_single_class_disappears(self):
+ t = Union[Employee]
+ self.assertIs(t, Employee)
+
+ def test_base_class_disappears(self):
+ u = Union[Employee, Manager, int]
+ self.assertEqual(u, Union[int, Employee])
+ u = Union[Manager, int, Employee]
+ self.assertEqual(u, Union[int, Employee])
+ u = Union[Employee, Manager]
+ self.assertIs(u, Employee)
+
+ def test_union_union(self):
+ u = Union[int, float]
+ v = Union[u, Employee]
+ self.assertEqual(v, Union[int, float, Employee])
+
+ def test_repr(self):
+ self.assertEqual(repr(Union), 'typing.Union')
+ u = Union[Employee, int]
+ self.assertEqual(repr(u), 'typing.Union[%s.Employee, int]' % __name__)
+ u = Union[int, Employee]
+ self.assertEqual(repr(u), 'typing.Union[int, %s.Employee]' % __name__)
+ T = TypeVar('T')
+ u = Union[T, int][int]
+ self.assertEqual(repr(u), repr(int))
+ u = Union[List[int], int]
+ self.assertEqual(repr(u), 'typing.Union[typing.List[int], int]')
+
+ def test_cannot_subclass(self):
+ 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()
+ 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_union_compare_other(self):
+ self.assertNotEqual(Union, object)
+ self.assertNotEqual(Union, Any)
+ self.assertNotEqual(ClassVar, Union)
+ self.assertNotEqual(Optional, Union)
+ self.assertNotEqual([None], Optional)
+ self.assertNotEqual(Optional, typing.Mapping)
+ self.assertNotEqual(Optional[typing.MutableMapping], Union)
+
+ def test_optional(self):
+ o = Optional[int]
+ u = Union[int, None]
+ self.assertEqual(o, u)
+
+ def test_empty(self):
+ with self.assertRaises(TypeError):
+ Union[()]
+
+ def test_union_instance_type_error(self):
+ with self.assertRaises(TypeError):
+ isinstance(42, Union[int, str])
+
+ def test_no_eval_union(self):
+ u = Union[int, str]
+ self.assertIs(u._eval_type({}, {}), u)
+
+ def test_function_repr_union(self):
+ def fun(): pass
+ self.assertEqual(repr(Union[fun, int]), 'typing.Union[fun, int]')
+
+ def test_union_str_pattern(self):
+ # Shouldn't crash; see http://bugs.python.org/issue25390
+ A = Union[str, Pattern]
+ A
+
+ def test_etree(self):
+ # See https://github.com/python/typing/issues/229
+ # (Only relevant for Python 2.)
+ try:
+ from xml.etree.cElementTree import Element
+ except ImportError:
+ raise SkipTest("cElementTree not found")
+ Union[Element, str] # Shouldn't crash
+
+ def Elem(*args):
+ return Element(*args)
+
+ Union[Elem, str] # Nor should this
+
+
+class TupleTests(BaseTestCase):
+
+ def test_basics(self):
+ with self.assertRaises(TypeError):
+ issubclass(Tuple, Tuple[int, str])
+ with self.assertRaises(TypeError):
+ issubclass(tuple, Tuple[int, str])
+
+ class TP(tuple): pass
+ self.assertTrue(issubclass(tuple, Tuple))
+ self.assertTrue(issubclass(TP, Tuple))
+
+ def test_equality(self):
+ self.assertEqual(Tuple[int], Tuple[int])
+ self.assertEqual(Tuple[int, ...], Tuple[int, ...])
+ self.assertNotEqual(Tuple[int], Tuple[int, int])
+ self.assertNotEqual(Tuple[int], Tuple[int, ...])
+
+ def test_tuple_subclass(self):
+ class MyTuple(tuple):
+ pass
+ self.assertTrue(issubclass(MyTuple, Tuple))
+
+ def test_tuple_instance_type_error(self):
+ with self.assertRaises(TypeError):
+ isinstance((0, 0), Tuple[int, int])
+ isinstance((0, 0), Tuple)
+
+ def test_repr(self):
+ self.assertEqual(repr(Tuple), 'typing.Tuple')
+ self.assertEqual(repr(Tuple[()]), 'typing.Tuple[()]')
+ self.assertEqual(repr(Tuple[int, float]), 'typing.Tuple[int, float]')
+ self.assertEqual(repr(Tuple[int, ...]), 'typing.Tuple[int, ...]')
+
+ def test_errors(self):
+ with self.assertRaises(TypeError):
+ issubclass(42, Tuple)
+ with self.assertRaises(TypeError):
+ issubclass(42, Tuple[int])
+
+
+class CallableTests(BaseTestCase):
+
+ def test_self_subclass(self):
+ 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])
+ self.assertEqual(len({Callable[[int], int], Callable[[int], int]}), 1)
+ self.assertNotEqual(Callable[[int], int], Callable[[int], str])
+ self.assertNotEqual(Callable[[int], int], Callable[[str], int])
+ self.assertNotEqual(Callable[[int], int], Callable[[int, int], int])
+ self.assertNotEqual(Callable[[int], int], Callable[[], int])
+ self.assertNotEqual(Callable[[int], int], Callable)
+
+ 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_wrong_forms(self):
+ with self.assertRaises(TypeError):
+ Callable[(), int]
+ with self.assertRaises(TypeError):
+ Callable[[()], int]
+ with self.assertRaises(TypeError):
+ Callable[[int, 1], 2]
+ with self.assertRaises(TypeError):
+ Callable[int]
+
+ def test_callable_instance_works(self):
+ def f():
+ pass
+ self.assertIsInstance(f, Callable)
+ self.assertNotIsInstance(None, Callable)
+
+ def test_callable_instance_type_error(self):
+ def f():
+ pass
+ with self.assertRaises(TypeError):
+ self.assertIsInstance(f, Callable[[], None])
+ with self.assertRaises(TypeError):
+ self.assertIsInstance(f, Callable[[], Any])
+ with self.assertRaises(TypeError):
+ self.assertNotIsInstance(None, Callable[[], None])
+ with self.assertRaises(TypeError):
+ self.assertNotIsInstance(None, Callable[[], Any])
+
+ def test_repr(self):
+ ct0 = Callable[[], bool]
+ self.assertEqual(repr(ct0), 'typing.Callable[[], bool]')
+ ct2 = Callable[[str, float], int]
+ self.assertEqual(repr(ct2), 'typing.Callable[[str, float], int]')
+ ctv = Callable[..., str]
+ self.assertEqual(repr(ctv), 'typing.Callable[..., str]')
+
+ def test_ellipsis_in_generic(self):
+ # Shouldn't crash; see https://github.com/python/typing/issues/259
+ typing.List[Callable[..., str]]
+
+
+XK = TypeVar('XK', unicode, bytes)
+XV = TypeVar('XV')
+
+
+class SimpleMapping(Generic[XK, XV]):
+
+ def __getitem__(self, key):
+ pass
+
+ def __setitem__(self, key, value):
+ pass
+
+ def get(self, key, default=None):
+ pass
+
+
+class MySimpleMapping(SimpleMapping[XK, XV]):
+
+ def __init__(self):
+ self.store = {}
+
+ def __getitem__(self, key):
+ return self.store[key]
+
+ def __setitem__(self, key, value):
+ self.store[key] = value
+
+ def get(self, key, default=None):
+ try:
+ return self.store[key]
+ except KeyError:
+ return default
+
+
+class ProtocolTests(BaseTestCase):
+
+ def test_basic_protocol(self):
+ @runtime_checkable
+ class P(Protocol):
+ def meth(self):
+ pass
+ class C(object): pass
+ class D(object):
+ def meth(self):
+ pass
+ def f():
+ pass
+ self.assertIsSubclass(D, P)
+ self.assertIsInstance(D(), P)
+ self.assertNotIsSubclass(C, P)
+ self.assertNotIsInstance(C(), P)
+ self.assertNotIsSubclass(types.FunctionType, P)
+ self.assertNotIsInstance(f, P)
+
+ def test_everything_implements_empty_protocol(self):
+ @runtime_checkable
+ class Empty(Protocol): pass
+ class C(object): pass
+ def f():
+ pass
+ for thing in (object, type, tuple, C, types.FunctionType):
+ self.assertIsSubclass(thing, Empty)
+ for thing in (object(), 1, (), typing, f):
+ self.assertIsInstance(thing, Empty)
+
+ def test_function_implements_protocol(self):
+ @runtime_checkable
+ class Function(Protocol):
+ def __call__(self, *args, **kwargs):
+ pass
+ def f():
+ pass
+ self.assertIsInstance(f, Function)
+
+ def test_no_inheritance_from_nominal(self):
+ class C(object): pass
+ class BP(Protocol): pass
+ with self.assertRaises(TypeError):
+ class P(C, Protocol):
+ pass
+ with self.assertRaises(TypeError):
+ class P(Protocol, C):
+ pass
+ with self.assertRaises(TypeError):
+ class P(BP, C, Protocol):
+ pass
+ class D(BP, C): pass
+ class E(C, BP): pass
+ self.assertNotIsInstance(D(), E)
+ self.assertNotIsInstance(E(), D)
+
+ def test_no_instantiation(self):
+ class P(Protocol): pass
+ with self.assertRaises(TypeError):
+ P()
+ class C(P): pass
+ self.assertIsInstance(C(), C)
+ T = typing.TypeVar('T')
+ class PG(Protocol[T]): pass
+ with self.assertRaises(TypeError):
+ PG()
+ with self.assertRaises(TypeError):
+ PG[int]()
+ with self.assertRaises(TypeError):
+ PG[T]()
+ class CG(PG[T]): pass
+ self.assertIsInstance(CG[int](), CG)
+
+ def test_cannot_instantiate_abstract(self):
+ @runtime_checkable
+ class P(Protocol):
+ @abc.abstractmethod
+ def ameth(self):
+ raise NotImplementedError
+ class B(P):
+ pass
+ class C(B):
+ def ameth(self):
+ return 26
+ with self.assertRaises(TypeError):
+ B()
+ self.assertIsInstance(C(), P)
+
+ def test_subprotocols_extending(self):
+ class P1(Protocol):
+ def meth1(self):
+ pass
+ @runtime_checkable
+ class P2(P1, Protocol):
+ def meth2(self):
+ pass
+ class C(object):
+ def meth1(self):
+ pass
+ def meth2(self):
+ pass
+ class C1(object):
+ def meth1(self):
+ pass
+ class C2(object):
+ def meth2(self):
+ pass
+ self.assertNotIsInstance(C1(), P2)
+ self.assertNotIsInstance(C2(), P2)
+ self.assertNotIsSubclass(C1, P2)
+ self.assertNotIsSubclass(C2, P2)
+ self.assertIsInstance(C(), P2)
+ self.assertIsSubclass(C, P2)
+
+ def test_subprotocols_merging(self):
+ class P1(Protocol):
+ def meth1(self):
+ pass
+ class P2(Protocol):
+ def meth2(self):
+ pass
+ @runtime_checkable
+ class P(P1, P2, Protocol):
+ pass
+ class C(object):
+ def meth1(self):
+ pass
+ def meth2(self):
+ pass
+ class C1(object):
+ def meth1(self):
+ pass
+ class C2(object):
+ def meth2(self):
+ pass
+ self.assertNotIsInstance(C1(), P)
+ self.assertNotIsInstance(C2(), P)
+ self.assertNotIsSubclass(C1, P)
+ self.assertNotIsSubclass(C2, P)
+ self.assertIsInstance(C(), P)
+ self.assertIsSubclass(C, P)
+
+ def test_protocols_issubclass(self):
+ T = typing.TypeVar('T')
+ @runtime_checkable
+ class P(Protocol):
+ def x(self): pass
+ @runtime_checkable
+ class PG(Protocol[T]):
+ def x(self): pass
+ class BadP(Protocol):
+ def x(self): pass
+ class BadPG(Protocol[T]):
+ def x(self): pass
+ class C(object):
+ def x(self): pass
+ self.assertIsSubclass(C, P)
+ self.assertIsSubclass(C, PG)
+ self.assertIsSubclass(BadP, PG)
+ self.assertIsSubclass(PG[int], PG)
+ self.assertIsSubclass(BadPG[int], P)
+ self.assertIsSubclass(BadPG[T], PG)
+ with self.assertRaises(TypeError):
+ issubclass(C, PG[T])
+ with self.assertRaises(TypeError):
+ issubclass(C, PG[C])
+ with self.assertRaises(TypeError):
+ issubclass(C, BadP)
+ with self.assertRaises(TypeError):
+ issubclass(C, BadPG)
+ with self.assertRaises(TypeError):
+ issubclass(P, PG[T])
+ with self.assertRaises(TypeError):
+ issubclass(PG, PG[int])
+
+ def test_protocols_issubclass_non_callable(self):
+ class C(object):
+ x = 1
+ @runtime_checkable
+ class PNonCall(Protocol):
+ x = 1
+ with self.assertRaises(TypeError):
+ issubclass(C, PNonCall)
+ self.assertIsInstance(C(), PNonCall)
+ PNonCall.register(C)
+ with self.assertRaises(TypeError):
+ issubclass(C, PNonCall)
+ self.assertIsInstance(C(), PNonCall)
+ # check that non-protocol subclasses are not affected
+ class D(PNonCall): pass
+ self.assertNotIsSubclass(C, D)
+ self.assertNotIsInstance(C(), D)
+ D.register(C)
+ self.assertIsSubclass(C, D)
+ self.assertIsInstance(C(), D)
+ with self.assertRaises(TypeError):
+ issubclass(D, PNonCall)
+
+ def test_protocols_isinstance(self):
+ T = typing.TypeVar('T')
+ @runtime_checkable
+ class P(Protocol):
+ def meth(x): pass
+ @runtime_checkable
+ class PG(Protocol[T]):
+ def meth(x): pass
+ class BadP(Protocol):
+ def meth(x): pass
+ class BadPG(Protocol[T]):
+ def meth(x): pass
+ class C(object):
+ def meth(x): pass
+ self.assertIsInstance(C(), P)
+ self.assertIsInstance(C(), PG)
+ with self.assertRaises(TypeError):
+ isinstance(C(), PG[T])
+ with self.assertRaises(TypeError):
+ isinstance(C(), PG[C])
+ with self.assertRaises(TypeError):
+ isinstance(C(), BadP)
+ with self.assertRaises(TypeError):
+ isinstance(C(), BadPG)
+
+ def test_protocols_isinstance_init(self):
+ T = typing.TypeVar('T')
+ @runtime_checkable
+ class P(Protocol):
+ x = 1
+ @runtime_checkable
+ class PG(Protocol[T]):
+ x = 1
+ class C(object):
+ def __init__(self, x):
+ self.x = x
+ self.assertIsInstance(C(1), P)
+ self.assertIsInstance(C(1), PG)
+
+ def test_protocol_checks_after_subscript(self):
+ class P(Protocol[T]): pass
+ class C(P[T]): pass
+ class Old1: pass
+ class New1(object): pass
+ class Old2: pass
+ class New2(object): pass
+ CA = C[Any] # noqa
+
+ self.assertNotIsInstance(Old1(), C)
+ self.assertNotIsInstance(New1(), C)
+ self.assertNotIsSubclass(Old2, C)
+ self.assertNotIsSubclass(New2, C)
+
+ class D1(C[Any]): pass
+ class D2(C[Any]): pass
+ CI = C[int] # noqa
+
+ self.assertIsInstance(D1(), C)
+ self.assertIsSubclass(D2, C)
+
+ def test_protocols_support_register(self):
+ @runtime_checkable
+ class P(Protocol):
+ x = 1
+ class PM(Protocol):
+ def meth(self): pass
+ class D(PM): pass
+ class C(object): pass
+ D.register(C)
+ P.register(C)
+ self.assertIsInstance(C(), P)
+ self.assertIsInstance(C(), D)
+
+ def test_none_on_non_callable_doesnt_block_implementation(self):
+ @runtime_checkable
+ class P(Protocol):
+ x = 1
+ class A(object):
+ x = 1
+ class B(A):
+ x = None
+ class C(object):
+ def __init__(self):
+ self.x = None
+ self.assertIsInstance(B(), P)
+ self.assertIsInstance(C(), P)
+
+ def test_none_on_callable_blocks_implementation(self):
+ @runtime_checkable
+ class P(Protocol):
+ def x(self): pass
+ class A(object):
+ def x(self): pass
+ class B(A):
+ x = None
+ class C(object):
+ def __init__(self):
+ self.x = None
+ self.assertNotIsInstance(B(), P)
+ self.assertNotIsInstance(C(), P)
+
+ def test_non_protocol_subclasses(self):
+ class P(Protocol):
+ x = 1
+ @runtime_checkable
+ class PR(Protocol):
+ def meth(self): pass
+ class NonP(P):
+ x = 1
+ class NonPR(PR): pass
+ class C(object):
+ x = 1
+ class D(object):
+ def meth(self): pass
+ self.assertNotIsInstance(C(), NonP)
+ self.assertNotIsInstance(D(), NonPR)
+ self.assertNotIsSubclass(C, NonP)
+ self.assertNotIsSubclass(D, NonPR)
+ self.assertIsInstance(NonPR(), PR)
+ self.assertIsSubclass(NonPR, PR)
+
+ def test_custom_subclasshook(self):
+ class P(Protocol):
+ x = 1
+ class OKClass(object): pass
+ class BadClass(object):
+ x = 1
+ class C(P):
+ @classmethod
+ def __subclasshook__(cls, other):
+ return other.__name__.startswith("OK")
+ self.assertIsInstance(OKClass(), C)
+ self.assertNotIsInstance(BadClass(), C)
+ self.assertIsSubclass(OKClass, C)
+ self.assertNotIsSubclass(BadClass, C)
+
+ def test_issubclass_fails_correctly(self):
+ @runtime_checkable
+ class P(Protocol):
+ x = 1
+ class C: pass
+ with self.assertRaises(TypeError):
+ issubclass(C(), P)
+
+ def test_defining_generic_protocols(self):
+ T = typing.TypeVar('T')
+ S = typing.TypeVar('S')
+ @runtime_checkable
+ class PR(Protocol[T, S]):
+ def meth(self): pass
+ class P(PR[int, T], Protocol[T]):
+ y = 1
+ self.assertIsSubclass(PR[int, T], PR)
+ self.assertIsSubclass(P[str], PR)
+ with self.assertRaises(TypeError):
+ PR[int]
+ with self.assertRaises(TypeError):
+ P[int, str]
+ with self.assertRaises(TypeError):
+ PR[int, 1]
+ with self.assertRaises(TypeError):
+ PR[int, ClassVar]
+ class C(PR[int, T]): pass
+ self.assertIsInstance(C[str](), C)
+
+ def test_defining_generic_protocols_old_style(self):
+ T = typing.TypeVar('T')
+ S = typing.TypeVar('S')
+ @runtime_checkable
+ class PR(Protocol, typing.Generic[T, S]):
+ def meth(self): pass
+ class P(PR[int, str], Protocol):
+ y = 1
+ self.assertIsSubclass(PR[int, str], PR)
+ self.assertIsSubclass(P, PR)
+ with self.assertRaises(TypeError):
+ PR[int]
+ with self.assertRaises(TypeError):
+ PR[int, 1]
+ class P1(Protocol, typing.Generic[T]):
+ def bar(self, x): pass
+ class P2(typing.Generic[T], Protocol):
+ def bar(self, x): pass
+ @runtime_checkable
+ class PSub(P1[str], Protocol):
+ x = 1
+ class Test(object):
+ x = 1
+ def bar(self, x):
+ return x
+ self.assertIsInstance(Test(), PSub)
+ with self.assertRaises(TypeError):
+ PR[int, ClassVar]
+
+ def test_init_called(self):
+ T = typing.TypeVar('T')
+ class P(Protocol[T]): pass
+ class C(P[T]):
+ def __init__(self):
+ self.test = 'OK'
+ self.assertEqual(C[int]().test, 'OK')
+
+ def test_protocols_bad_subscripts(self):
+ T = typing.TypeVar('T')
+ S = typing.TypeVar('S')
+ with self.assertRaises(TypeError):
+ class P(Protocol[T, T]): pass
+ with self.assertRaises(TypeError):
+ class P(Protocol[int]): pass
+ with self.assertRaises(TypeError):
+ class P(Protocol[T], Protocol[S]): pass
+ with self.assertRaises(TypeError):
+ class P(Protocol[T], typing.Mapping[T, S]): pass
+
+ def test_generic_protocols_repr(self):
+ T = typing.TypeVar('T')
+ S = typing.TypeVar('S')
+ class P(Protocol[T, S]): pass
+ self.assertTrue(repr(P).endswith('P'))
+ self.assertTrue(repr(P[T, S]).endswith('P[~T, ~S]'))
+ self.assertTrue(repr(P[int, str]).endswith('P[int, str]'))
+
+ def test_generic_protocols_eq(self):
+ T = typing.TypeVar('T')
+ S = typing.TypeVar('S')
+ class P(Protocol[T, S]): pass
+ self.assertEqual(P, P)
+ self.assertEqual(P[int, T], P[int, T])
+ self.assertEqual(P[T, T][typing.Tuple[T, S]][int, str],
+ P[typing.Tuple[int, str], typing.Tuple[int, str]])
+
+ def test_generic_protocols_special_from_generic(self):
+ T = typing.TypeVar('T')
+ class P(Protocol[T]): pass
+ self.assertEqual(P.__parameters__, (T,))
+ self.assertIs(P.__args__, None)
+ self.assertIs(P.__origin__, None)
+ self.assertEqual(P[int].__parameters__, ())
+ self.assertEqual(P[int].__args__, (int,))
+ self.assertIs(P[int].__origin__, P)
+
+ def test_generic_protocols_special_from_protocol(self):
+ @runtime_checkable
+ class PR(Protocol):
+ x = 1
+ class P(Protocol):
+ def meth(self):
+ pass
+ T = typing.TypeVar('T')
+ class PG(Protocol[T]):
+ x = 1
+ def meth(self):
+ pass
+ self.assertTrue(P._is_protocol)
+ self.assertTrue(PR._is_protocol)
+ self.assertTrue(PG._is_protocol)
+ with self.assertRaises(AttributeError):
+ self.assertFalse(P._is_runtime_protocol)
+ self.assertTrue(PR._is_runtime_protocol)
+ self.assertTrue(PG[int]._is_protocol)
+ self.assertEqual(P._get_protocol_attrs(), {'meth'})
+ self.assertEqual(PR._get_protocol_attrs(), {'x'})
+ self.assertEqual(frozenset(PG._get_protocol_attrs()),
+ frozenset({'x', 'meth'}))
+ self.assertEqual(frozenset(PG[int]._get_protocol_attrs()),
+ frozenset({'x', 'meth'}))
+
+ def test_no_runtime_deco_on_nominal(self):
+ with self.assertRaises(TypeError):
+ @runtime_checkable
+ class C(object): pass
+ class Proto(Protocol):
+ x = 1
+ with self.assertRaises(TypeError):
+ @runtime_checkable
+ class Concrete(Proto):
+ pass
+
+ def test_none_treated_correctly(self):
+ @runtime_checkable
+ class P(Protocol):
+ x = None # type: int
+ class B(object): pass
+ self.assertNotIsInstance(B(), P)
+ class C(object):
+ x = 1
+ class D(object):
+ x = None
+ self.assertIsInstance(C(), P)
+ self.assertIsInstance(D(), P)
+ class CI(object):
+ def __init__(self):
+ self.x = 1
+ class DI(object):
+ def __init__(self):
+ self.x = None
+ self.assertIsInstance(C(), P)
+ self.assertIsInstance(D(), P)
+
+ def test_protocols_in_unions(self):
+ class P(Protocol):
+ x = None # type: int
+ Alias = typing.Union[typing.Iterable, P]
+ Alias2 = typing.Union[P, typing.Iterable]
+ self.assertEqual(Alias, Alias2)
+
+ def test_protocols_pickleable(self):
+ global P, CP # pickle wants to reference the class by name
+ T = typing.TypeVar('T')
+
+ @runtime_checkable
+ class P(Protocol[T]):
+ x = 1
+ class CP(P[int]):
+ pass
+
+ c = CP()
+ c.foo = 42
+ c.bar = 'abc'
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ z = pickle.dumps(c, proto)
+ x = pickle.loads(z)
+ self.assertEqual(x.foo, 42)
+ self.assertEqual(x.bar, 'abc')
+ self.assertEqual(x.x, 1)
+ self.assertEqual(x.__dict__, {'foo': 42, 'bar': 'abc'})
+ s = pickle.dumps(P)
+ D = pickle.loads(s)
+ class E(object):
+ x = 1
+ self.assertIsInstance(E(), D)
+
+ def test_supports_int(self):
+ self.assertIsSubclass(int, typing.SupportsInt)
+ self.assertNotIsSubclass(str, typing.SupportsInt)
+
+ def test_supports_float(self):
+ self.assertIsSubclass(float, typing.SupportsFloat)
+ self.assertNotIsSubclass(str, typing.SupportsFloat)
+
+ def test_supports_complex(self):
+
+ # Note: complex itself doesn't have __complex__.
+ class C(object):
+ def __complex__(self):
+ return 0j
+
+ self.assertIsSubclass(C, typing.SupportsComplex)
+ self.assertNotIsSubclass(str, typing.SupportsComplex)
+
+ def test_supports_abs(self):
+ self.assertIsSubclass(float, typing.SupportsAbs)
+ self.assertIsSubclass(int, typing.SupportsAbs)
+ self.assertNotIsSubclass(str, typing.SupportsAbs)
+
+ def test_reversible(self):
+ self.assertIsSubclass(list, typing.Reversible)
+ self.assertNotIsSubclass(int, typing.Reversible)
+
+ def test_supports_index(self):
+ self.assertIsSubclass(int, typing.SupportsIndex)
+ self.assertNotIsSubclass(str, typing.SupportsIndex)
+
+ def test_protocol_instance_works(self):
+ self.assertIsInstance(0, typing.SupportsAbs)
+ self.assertNotIsInstance('no', typing.SupportsAbs)
+ class C1(typing.SupportsInt):
+ def __int__(self):
+ return 42
+ class C2(C1):
+ pass
+ c = C2()
+ self.assertIsInstance(c, C1)
+
+ def test_collections_protocols_allowed(self):
+ @runtime_checkable
+ class Custom(collections.Iterable, Protocol):
+ def close(self): pass
+
+ class A(object): pass
+ class B(object):
+ def __iter__(self):
+ return []
+ def close(self):
+ return 0
+
+ self.assertIsSubclass(B, Custom)
+ self.assertNotIsSubclass(A, Custom)
+
+
+class GenericTests(BaseTestCase):
+
+ def test_basics(self):
+ X = SimpleMapping[str, Any]
+ self.assertEqual(X.__parameters__, ())
+ with self.assertRaises(TypeError):
+ X[unicode]
+ with self.assertRaises(TypeError):
+ X[unicode, unicode]
+ Y = SimpleMapping[XK, unicode]
+ self.assertEqual(Y.__parameters__, (XK,))
+ Y[unicode]
+ with self.assertRaises(TypeError):
+ Y[unicode, unicode]
+ self.assertIsSubclass(SimpleMapping[str, int], SimpleMapping)
+
+ def test_generic_errors(self):
+ T = TypeVar('T')
+ S = TypeVar('S')
+ with self.assertRaises(TypeError):
+ Generic[T]()
+ with self.assertRaises(TypeError):
+ Generic[T][T]
+ with self.assertRaises(TypeError):
+ Generic[T][S]
+ with self.assertRaises(TypeError):
+ isinstance([], List[int])
+ with self.assertRaises(TypeError):
+ issubclass(list, List[int])
+ with self.assertRaises(TypeError):
+ class NewGeneric(Generic): pass
+ with self.assertRaises(TypeError):
+ class MyGeneric(Generic[T], Generic[S]): pass
+ with self.assertRaises(TypeError):
+ class MyGeneric(List[T], Generic[S]): pass
+
+ def test_init(self):
+ T = TypeVar('T')
+ S = TypeVar('S')
+ with self.assertRaises(TypeError):
+ Generic[T, T]
+ with self.assertRaises(TypeError):
+ Generic[T, S, T]
+
+ def test_repr(self):
+ self.assertEqual(repr(SimpleMapping),
+ __name__ + '.' + 'SimpleMapping')
+ self.assertEqual(repr(MySimpleMapping),
+ __name__ + '.' + 'MySimpleMapping')
+
+ def test_chain_repr(self):
+ T = TypeVar('T')
+ S = TypeVar('S')
+
+ class C(Generic[T]):
+ pass
+
+ X = C[Tuple[S, T]]
+ self.assertEqual(X, C[Tuple[S, T]])
+ self.assertNotEqual(X, C[Tuple[T, S]])
+
+ Y = X[T, int]
+ self.assertEqual(Y, X[T, int])
+ self.assertNotEqual(Y, X[S, int])
+ self.assertNotEqual(Y, X[T, str])
+
+ Z = Y[str]
+ self.assertEqual(Z, Y[str])
+ self.assertNotEqual(Z, Y[int])
+ self.assertNotEqual(Z, Y[T])
+
+ self.assertTrue(str(Z).endswith(
+ '.C[typing.Tuple[str, int]]'))
+
+ def test_new_repr(self):
+ T = TypeVar('T')
+ U = TypeVar('U', covariant=True)
+ S = TypeVar('S')
+
+ self.assertEqual(repr(List), 'typing.List')
+ self.assertEqual(repr(List[T]), 'typing.List[~T]')
+ self.assertEqual(repr(List[U]), 'typing.List[+U]')
+ self.assertEqual(repr(List[S][T][int]), 'typing.List[int]')
+ self.assertEqual(repr(List[int]), 'typing.List[int]')
+
+ def test_new_repr_complex(self):
+ T = TypeVar('T')
+ TS = TypeVar('TS')
+
+ self.assertEqual(repr(typing.Mapping[T, TS][TS, T]), 'typing.Mapping[~TS, ~T]')
+ self.assertEqual(repr(List[Tuple[T, TS]][int, T]),
+ 'typing.List[typing.Tuple[int, ~T]]')
+ self.assertEqual(
+ repr(List[Tuple[T, T]][List[int]]),
+ 'typing.List[typing.Tuple[typing.List[int], typing.List[int]]]'
+ )
+
+ def test_new_repr_bare(self):
+ T = TypeVar('T')
+ self.assertEqual(repr(Generic[T]), 'typing.Generic[~T]')
+ self.assertEqual(repr(typing.Protocol[T]), 'typing.Protocol[~T]')
+ class C(typing.Dict[Any, Any]): pass
+ # this line should just work
+ repr(C.__mro__)
+
+ def test_dict(self):
+ T = TypeVar('T')
+
+ class B(Generic[T]):
+ pass
+
+ b = B()
+ b.foo = 42
+ self.assertEqual(b.__dict__, {'foo': 42})
+
+ class C(B[int]):
+ pass
+
+ c = C()
+ c.bar = 'abc'
+ self.assertEqual(c.__dict__, {'bar': 'abc'})
+
+ def test_subscripted_generics_as_proxies(self):
+ T = TypeVar('T')
+ class C(Generic[T]):
+ x = 'def'
+ self.assertEqual(C[int].x, 'def')
+ self.assertEqual(C[C[int]].x, 'def')
+ C[C[int]].x = 'changed'
+ self.assertEqual(C.x, 'changed')
+ self.assertEqual(C[str].x, 'changed')
+ C[List[str]].z = 'new'
+ self.assertEqual(C.z, 'new')
+ self.assertEqual(C[Tuple[int]].z, 'new')
+
+ self.assertEqual(C().x, 'changed')
+ self.assertEqual(C[Tuple[str]]().z, 'new')
+
+ class D(C[T]):
+ pass
+ self.assertEqual(D[int].x, 'changed')
+ self.assertEqual(D.z, 'new')
+ D.z = 'from derived z'
+ D[int].x = 'from derived x'
+ self.assertEqual(C.x, 'changed')
+ self.assertEqual(C[int].z, 'new')
+ self.assertEqual(D.x, 'from derived x')
+ self.assertEqual(D[str].z, 'from derived z')
+
+ def test_abc_registry_kept(self):
+ T = TypeVar('T')
+ class C(Generic[T]): pass
+ C.register(int)
+ self.assertIsInstance(1, C)
+ C[int]
+ self.assertIsInstance(1, C)
+
+ def test_false_subclasses(self):
+ class MyMapping(MutableMapping[str, str]): pass
+ self.assertNotIsInstance({}, MyMapping)
+ self.assertNotIsSubclass(dict, MyMapping)
+
+ def test_abc_bases(self):
+ class MM(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
+ # this should just work
+ MM().update()
+ self.assertIsInstance(MM(), collections.MutableMapping)
+ self.assertIsInstance(MM(), MutableMapping)
+ self.assertNotIsInstance(MM(), List)
+ self.assertNotIsInstance({}, MM)
+
+ def test_multiple_bases(self):
+ class MM1(MutableMapping[str, str], collections.MutableMapping):
+ pass
+ with self.assertRaises(TypeError):
+ # consistent MRO not possible
+ class MM2(collections.MutableMapping, MutableMapping[str, str]):
+ pass
+
+ def test_orig_bases(self):
+ T = TypeVar('T')
+ class C(typing.Dict[str, T]): pass
+ self.assertEqual(C.__orig_bases__, (typing.Dict[str, T],))
+
+ def test_naive_runtime_checks(self):
+ def naive_dict_check(obj, tp):
+ # Check if a dictionary conforms to Dict type
+ if len(tp.__parameters__) > 0:
+ raise NotImplementedError
+ if tp.__args__:
+ KT, VT = tp.__args__
+ return all(
+ isinstance(k, KT) and isinstance(v, VT)
+ for k, v in obj.items()
+ )
+ self.assertTrue(naive_dict_check({'x': 1}, typing.Dict[typing.Text, int]))
+ self.assertFalse(naive_dict_check({1: 'x'}, typing.Dict[typing.Text, int]))
+ with self.assertRaises(NotImplementedError):
+ naive_dict_check({1: 'x'}, typing.Dict[typing.Text, T])
+
+ def naive_generic_check(obj, tp):
+ # Check if an instance conforms to the generic class
+ if not hasattr(obj, '__orig_class__'):
+ raise NotImplementedError
+ return obj.__orig_class__ == tp
+ class Node(Generic[T]): pass
+ self.assertTrue(naive_generic_check(Node[int](), Node[int]))
+ self.assertFalse(naive_generic_check(Node[str](), Node[int]))
+ self.assertFalse(naive_generic_check(Node[str](), List))
+ with self.assertRaises(NotImplementedError):
+ naive_generic_check([1, 2, 3], Node[int])
+
+ def naive_list_base_check(obj, tp):
+ # Check if list conforms to a List subclass
+ return all(isinstance(x, tp.__orig_bases__[0].__args__[0])
+ for x in obj)
+ class C(List[int]): pass
+ self.assertTrue(naive_list_base_check([1, 2, 3], C))
+ self.assertFalse(naive_list_base_check(['a', 'b'], C))
+
+ def test_multi_subscr_base(self):
+ T = TypeVar('T')
+ U = TypeVar('U')
+ V = TypeVar('V')
+ class C(List[T][U][V]): pass
+ class D(C, List[T][U][V]): pass
+ self.assertEqual(C.__parameters__, (V,))
+ self.assertEqual(D.__parameters__, (V,))
+ self.assertEqual(C[int].__parameters__, ())
+ self.assertEqual(D[int].__parameters__, ())
+ self.assertEqual(C[int].__args__, (int,))
+ self.assertEqual(D[int].__args__, (int,))
+ self.assertEqual(C.__bases__, (List,))
+ self.assertEqual(D.__bases__, (C, List))
+ self.assertEqual(C.__orig_bases__, (List[T][U][V],))
+ self.assertEqual(D.__orig_bases__, (C, List[T][U][V]))
+
+ def test_subscript_meta(self):
+ T = TypeVar('T')
+ self.assertEqual(Type[GenericMeta], Type[GenericMeta])
+ self.assertEqual(Union[T, int][GenericMeta], Union[GenericMeta, int])
+ self.assertEqual(Callable[..., GenericMeta].__args__, (Ellipsis, GenericMeta))
+
+ def test_generic_hashes(self):
+ import mod_generics_cache
+ class A(Generic[T]):
+ __module__ = 'test_typing'
+
+ class B(Generic[T]):
+ class A(Generic[T]):
+ pass
+
+ self.assertEqual(A, A)
+ self.assertEqual(mod_generics_cache.A[str], mod_generics_cache.A[str])
+ self.assertEqual(B.A, B.A)
+ self.assertEqual(mod_generics_cache.B.A[B.A[str]],
+ mod_generics_cache.B.A[B.A[str]])
+
+ self.assertNotEqual(A, B.A)
+ self.assertNotEqual(A, mod_generics_cache.A)
+ self.assertNotEqual(A, mod_generics_cache.B.A)
+ self.assertNotEqual(B.A, mod_generics_cache.A)
+ self.assertNotEqual(B.A, mod_generics_cache.B.A)
+
+ self.assertNotEqual(A[str], B.A[str])
+ self.assertNotEqual(A[List[Any]], B.A[List[Any]])
+ self.assertNotEqual(A[str], mod_generics_cache.A[str])
+ self.assertNotEqual(A[str], mod_generics_cache.B.A[str])
+ self.assertNotEqual(B.A[int], mod_generics_cache.A[int])
+ self.assertNotEqual(B.A[List[Any]], mod_generics_cache.B.A[List[Any]])
+
+ self.assertNotEqual(Tuple[A[str]], Tuple[B.A[str]])
+ self.assertNotEqual(Tuple[A[List[Any]]], Tuple[B.A[List[Any]]])
+ self.assertNotEqual(Union[str, A[str]], Union[str, mod_generics_cache.A[str]])
+ self.assertNotEqual(Union[A[str], A[str]],
+ Union[A[str], mod_generics_cache.A[str]])
+ self.assertNotEqual(typing.FrozenSet[A[str]],
+ typing.FrozenSet[mod_generics_cache.B.A[str]])
+
+ self.assertTrue(repr(Tuple[A[str]]).endswith('test_typing.A[str]]'))
+ self.assertTrue(repr(Tuple[mod_generics_cache.A[str]])
+ .endswith('mod_generics_cache.A[str]]'))
+
+ def test_extended_generic_rules_eq(self):
+ T = TypeVar('T')
+ U = TypeVar('U')
+ self.assertEqual(Tuple[T, T][int], Tuple[int, int])
+ self.assertEqual(typing.Iterable[Tuple[T, T]][T], typing.Iterable[Tuple[T, T]])
+ with self.assertRaises(TypeError):
+ Tuple[T, int][()]
+ with self.assertRaises(TypeError):
+ Tuple[T, U][T, ...]
+
+ self.assertEqual(Union[T, int][int], int)
+ self.assertEqual(Union[T, U][int, Union[int, str]], Union[int, str])
+ class Base(object): pass
+ class Derived(Base): pass
+ self.assertEqual(Union[T, Base][Derived], Base)
+ with self.assertRaises(TypeError):
+ Union[T, int][1]
+
+ self.assertEqual(Callable[[T], T][KT], Callable[[KT], KT])
+ self.assertEqual(Callable[..., List[T]][int], Callable[..., List[int]])
+ with self.assertRaises(TypeError):
+ Callable[[T], U][..., int]
+ with self.assertRaises(TypeError):
+ Callable[[T], U][[], int]
+
+ def test_extended_generic_rules_repr(self):
+ T = TypeVar('T')
+ self.assertEqual(repr(Union[Tuple, Callable]).replace('typing.', ''),
+ 'Union[Tuple, Callable]')
+ self.assertEqual(repr(Union[Tuple, Tuple[int]]).replace('typing.', ''),
+ 'Tuple')
+ self.assertEqual(repr(Callable[..., Optional[T]][int]).replace('typing.', ''),
+ 'Callable[..., Union[int, NoneType]]')
+ self.assertEqual(repr(Callable[[], List[T]][int]).replace('typing.', ''),
+ 'Callable[[], List[int]]')
+
+ def test_generic_forvard_ref(self):
+ LLT = List[List['CC']]
+ class CC: pass
+ self.assertEqual(typing._eval_type(LLT, globals(), locals()), List[List[CC]])
+ T = TypeVar('T')
+ AT = Tuple[T, ...]
+ self.assertIs(typing._eval_type(AT, globals(), locals()), AT)
+ CT = Callable[..., List[T]]
+ self.assertIs(typing._eval_type(CT, globals(), locals()), CT)
+
+ def test_extended_generic_rules_subclassing(self):
+ class T1(Tuple[T, KT]): pass
+ class T2(Tuple[T, ...]): pass
+ class C1(Callable[[T], T]): pass
+ class C2(Callable[..., int]):
+ def __call__(self):
+ return None
+
+ self.assertEqual(T1.__parameters__, (T, KT))
+ self.assertEqual(T1[int, str].__args__, (int, str))
+ self.assertEqual(T1[int, T].__origin__, T1)
+
+ self.assertEqual(T2.__parameters__, (T,))
+ with self.assertRaises(TypeError):
+ T1[int]
+ with self.assertRaises(TypeError):
+ T2[int, str]
+
+ self.assertEqual(repr(C1[int]).split('.')[-1], 'C1[int]')
+ self.assertEqual(C2.__parameters__, ())
+ self.assertIsInstance(C2(), collections.Callable)
+ self.assertIsSubclass(C2, collections.Callable)
+ self.assertIsSubclass(C1, collections.Callable)
+ self.assertIsInstance(T1(), tuple)
+ self.assertIsSubclass(T2, tuple)
+ self.assertIsSubclass(Tuple[int, ...], typing.Sequence)
+ self.assertIsSubclass(Tuple[int, ...], typing.Iterable)
+
+ def test_fail_with_bare_union(self):
+ with self.assertRaises(TypeError):
+ List[Union]
+ with self.assertRaises(TypeError):
+ Tuple[Optional]
+ with self.assertRaises(TypeError):
+ ClassVar[ClassVar]
+ with self.assertRaises(TypeError):
+ List[ClassVar[int]]
+
+ def test_fail_with_bare_generic(self):
+ T = TypeVar('T')
+ with self.assertRaises(TypeError):
+ List[Generic]
+ with self.assertRaises(TypeError):
+ Tuple[Generic[T]]
+ with self.assertRaises(TypeError):
+ List[typing.Protocol]
+ with self.assertRaises(TypeError):
+ isinstance(1, Generic)
+
+ def test_type_erasure_special(self):
+ T = TypeVar('T')
+ # this is the only test that checks type caching
+ self.clear_caches()
+ class MyTup(Tuple[T, T]): pass
+ self.assertIs(MyTup[int]().__class__, MyTup)
+ self.assertIs(MyTup[int]().__orig_class__, MyTup[int])
+ class MyCall(Callable[..., T]):
+ def __call__(self): return None
+ self.assertIs(MyCall[T]().__class__, MyCall)
+ self.assertIs(MyCall[T]().__orig_class__, MyCall[T])
+ class MyDict(typing.Dict[T, T]): pass
+ self.assertIs(MyDict[int]().__class__, MyDict)
+ self.assertIs(MyDict[int]().__orig_class__, MyDict[int])
+ class MyDef(typing.DefaultDict[str, T]): pass
+ self.assertIs(MyDef[int]().__class__, MyDef)
+ self.assertIs(MyDef[int]().__orig_class__, MyDef[int])
+
+ def test_all_repr_eq_any(self):
+ objs = (getattr(typing, el) for el in typing.__all__)
+ for obj in objs:
+ self.assertNotEqual(repr(obj), '')
+ self.assertEqual(obj, obj)
+ if getattr(obj, '__parameters__', None) and len(obj.__parameters__) == 1:
+ self.assertEqual(obj[Any].__args__, (Any,))
+ if isinstance(obj, type):
+ for base in obj.__mro__:
+ self.assertNotEqual(repr(base), '')
+ self.assertEqual(base, base)
+
+ def test_pickle(self):
+ global C # pickle wants to reference the class by name
+ T = TypeVar('T')
+
+ class B(Generic[T]):
+ pass
+
+ class C(B[int]):
+ pass
+
+ c = C()
+ c.foo = 42
+ c.bar = 'abc'
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ z = pickle.dumps(c, proto)
+ x = pickle.loads(z)
+ self.assertEqual(x.foo, 42)
+ self.assertEqual(x.bar, 'abc')
+ self.assertEqual(x.__dict__, {'foo': 42, 'bar': 'abc'})
+ simples = [Any, Union, Tuple, Callable, ClassVar, List, typing.Iterable]
+ for s in simples:
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ z = pickle.dumps(s, proto)
+ x = pickle.loads(z)
+ self.assertEqual(s, x)
+
+ def test_copy_and_deepcopy(self):
+ T = TypeVar('T')
+ class Node(Generic[T]): pass
+ things = [
+ Any,
+ Callable[..., T],
+ Callable[[int], int],
+ ClassVar[List[T]],
+ ClassVar[int],
+ List['T'],
+ Node[Any],
+ Node[T],
+ Node[int],
+ Tuple['T', 'T'],
+ Tuple[Any, Any],
+ Tuple[T, int],
+ Union['T', int],
+ Union[T, int],
+ typing.Dict[T, Any],
+ typing.Dict[int, str],
+ typing.Iterable[Any],
+ typing.Iterable[T],
+ typing.Iterable[int],
+ typing.Mapping['T', int]
+ ]
+ for t in things:
+ self.assertEqual(t, deepcopy(t))
+ self.assertEqual(t, copy(t))
+
+ def test_copy_generic_instances(self):
+ T = TypeVar('T')
+ class C(Generic[T]):
+ def __init__(self, attr):
+ self.attr = attr
+
+ c = C(42)
+ self.assertEqual(copy(c).attr, 42)
+ self.assertEqual(deepcopy(c).attr, 42)
+ self.assertIsNot(copy(c), c)
+ self.assertIsNot(deepcopy(c), c)
+ c.attr = 1
+ self.assertEqual(copy(c).attr, 1)
+ self.assertEqual(deepcopy(c).attr, 1)
+ ci = C[int](42)
+ self.assertEqual(copy(ci).attr, 42)
+ self.assertEqual(deepcopy(ci).attr, 42)
+ self.assertIsNot(copy(ci), ci)
+ self.assertIsNot(deepcopy(ci), ci)
+ ci.attr = 1
+ self.assertEqual(copy(ci).attr, 1)
+ self.assertEqual(deepcopy(ci).attr, 1)
+ self.assertEqual(ci.__orig_class__, C[int])
+
+ def test_weakref_all(self):
+ T = TypeVar('T')
+ things = [Any, Union[T, int], Callable[..., T], Tuple[Any, Any],
+ Optional[List[int]], typing.Mapping[int, str],
+ typing.re.Match[bytes], typing.Iterable['whatever']]
+ for t in things:
+ self.assertEqual(weakref.ref(t)(), t)
+
+ def test_parameterized_slots(self):
+ T = TypeVar('T')
+ class C(Generic[T]):
+ __slots__ = ('potato',)
+
+ c = C()
+ c_int = C[int]()
+ self.assertEqual(C.__slots__, C[str].__slots__)
+
+ c.potato = 0
+ c_int.potato = 0
+ with self.assertRaises(AttributeError):
+ c.tomato = 0
+ with self.assertRaises(AttributeError):
+ c_int.tomato = 0
+
+ self.assertEqual(typing._eval_type(C['C'], globals(), locals()), C[C])
+ self.assertEqual(typing._eval_type(C['C'], globals(), locals()).__slots__,
+ C.__slots__)
+ self.assertEqual(copy(C[int]), deepcopy(C[int]))
+
+ def test_parameterized_slots_dict(self):
+ T = TypeVar('T')
+ class D(Generic[T]):
+ __slots__ = {'banana': 42}
+
+ d = D()
+ d_int = D[int]()
+ self.assertEqual(D.__slots__, D[str].__slots__)
+
+ d.banana = 'yes'
+ d_int.banana = 'yes'
+ with self.assertRaises(AttributeError):
+ d.foobar = 'no'
+ with self.assertRaises(AttributeError):
+ d_int.foobar = 'no'
+
+ def test_errors(self):
+ with self.assertRaises(TypeError):
+ B = SimpleMapping[XK, Any]
+
+ class C(Generic[B]):
+ pass
+
+ def test_repr_2(self):
+ PY32 = sys.version_info[:2] < (3, 3)
+
+ class C(Generic[T]):
+ pass
+
+ self.assertEqual(C.__module__, __name__)
+ if not PY32:
+ self.assertEqual(C.__qualname__,
+ 'GenericTests.test_repr_2.<locals>.C')
+ self.assertEqual(repr(C).split('.')[-1], 'C')
+ X = C[int]
+ self.assertEqual(X.__module__, __name__)
+ if not PY32:
+ self.assertTrue(X.__qualname__.endswith('.<locals>.C'))
+ self.assertEqual(repr(X).split('.')[-1], 'C[int]')
+
+ class Y(C[int]):
+ pass
+
+ self.assertEqual(Y.__module__, __name__)
+ if not PY32:
+ self.assertEqual(Y.__qualname__,
+ 'GenericTests.test_repr_2.<locals>.Y')
+ self.assertEqual(repr(Y).split('.')[-1], 'Y')
+
+ def test_eq_1(self):
+ self.assertEqual(Generic, Generic)
+ self.assertEqual(Generic[T], Generic[T])
+ self.assertNotEqual(Generic[KT], Generic[VT])
+
+ def test_eq_2(self):
+
+ class A(Generic[T]):
+ pass
+
+ class B(Generic[T]):
+ pass
+
+ self.assertEqual(A, A)
+ self.assertNotEqual(A, B)
+ self.assertEqual(A[T], A[T])
+ self.assertNotEqual(A[T], B[T])
+
+ def test_multiple_inheritance(self):
+
+ class A(Generic[T, VT]):
+ pass
+
+ class B(Generic[KT, T]):
+ pass
+
+ class C(A[T, VT], Generic[VT, T, KT], B[KT, T]):
+ pass
+
+ self.assertEqual(C.__parameters__, (VT, T, KT))
+
+ def test_nested(self):
+
+ G = Generic
+
+ class Visitor(G[T]):
+
+ a = None
+
+ def set(self, a):
+ self.a = a
+
+ def get(self):
+ return self.a
+
+ def visit(self):
+ return self.a
+
+ V = Visitor[typing.List[int]]
+
+ class IntListVisitor(V):
+
+ def append(self, x):
+ self.a.append(x)
+
+ a = IntListVisitor()
+ a.set([])
+ a.append(1)
+ a.append(42)
+ self.assertEqual(a.get(), [1, 42])
+
+ def test_type_erasure(self):
+ T = TypeVar('T')
+
+ class Node(Generic[T]):
+ def __init__(self, label,
+ left=None,
+ right=None):
+ self.label = label # type: T
+ self.left = left # type: Optional[Node[T]]
+ self.right = right # type: Optional[Node[T]]
+
+ def foo(x):
+ a = Node(x)
+ b = Node[T](x)
+ c = Node[Any](x)
+ self.assertIs(type(a), Node)
+ self.assertIs(type(b), Node)
+ self.assertIs(type(c), Node)
+ self.assertEqual(a.label, x)
+ self.assertEqual(b.label, x)
+ self.assertEqual(c.label, x)
+
+ foo(42)
+
+ def test_implicit_any(self):
+ T = TypeVar('T')
+
+ class C(Generic[T]):
+ pass
+
+ class D(C):
+ pass
+
+ self.assertEqual(D.__parameters__, ())
+
+ with self.assertRaises(Exception):
+ D[int]
+ with self.assertRaises(Exception):
+ D[Any]
+ with self.assertRaises(Exception):
+ D[T]
+
+ def test_new_with_args(self):
+
+ class A(Generic[T]):
+ pass
+
+ class B(object):
+ def __new__(cls, arg):
+ # call object.__new__
+ obj = super(B, cls).__new__(cls)
+ obj.arg = arg
+ return obj
+
+ # mro: C, A, Generic, B, object
+ class C(A, B):
+ pass
+
+ c = C('foo')
+ self.assertEqual(c.arg, 'foo')
+
+ def test_new_with_args2(self):
+
+ class A(object):
+ def __init__(self, arg):
+ self.from_a = arg
+ # call object
+ super(A, self).__init__()
+
+ # mro: C, Generic, A, object
+ class C(Generic[T], A):
+ def __init__(self, arg):
+ self.from_c = arg
+ # call Generic
+ super(C, self).__init__(arg)
+
+ c = C('foo')
+ self.assertEqual(c.from_a, 'foo')
+ self.assertEqual(c.from_c, 'foo')
+
+ def test_new_no_args(self):
+
+ class A(Generic[T]):
+ pass
+
+ with self.assertRaises(TypeError):
+ A('foo')
+
+ class B(object):
+ def __new__(cls):
+ # call object
+ obj = super(B, cls).__new__(cls)
+ obj.from_b = 'b'
+ return obj
+
+ # mro: C, A, Generic, B, object
+ class C(A, B):
+ def __init__(self, arg):
+ self.arg = arg
+
+ def __new__(cls, arg):
+ # call A
+ obj = super(C, cls).__new__(cls)
+ obj.from_c = 'c'
+ return obj
+
+ c = C('foo')
+ self.assertEqual(c.arg, 'foo')
+ self.assertEqual(c.from_b, 'b')
+ self.assertEqual(c.from_c, 'c')
+
+
+class ClassVarTests(BaseTestCase):
+
+ def test_basics(self):
+ with self.assertRaises(TypeError):
+ ClassVar[1]
+ with self.assertRaises(TypeError):
+ ClassVar[int, str]
+ with self.assertRaises(TypeError):
+ ClassVar[int][str]
+
+ def test_repr(self):
+ self.assertEqual(repr(ClassVar), 'typing.ClassVar')
+ cv = ClassVar[int]
+ self.assertEqual(repr(cv), 'typing.ClassVar[int]')
+ cv = ClassVar[Employee]
+ self.assertEqual(repr(cv), 'typing.ClassVar[%s.Employee]' % __name__)
+
+ def test_cannot_subclass(self):
+ with self.assertRaises(TypeError):
+ class C(type(ClassVar)):
+ pass
+ with self.assertRaises(TypeError):
+ class C(type(ClassVar[int])):
+ pass
+
+ def test_cannot_init(self):
+ with self.assertRaises(TypeError):
+ ClassVar()
+ with self.assertRaises(TypeError):
+ type(ClassVar)()
+ with self.assertRaises(TypeError):
+ type(ClassVar[Optional[int]])()
+
+ def test_no_isinstance(self):
+ with self.assertRaises(TypeError):
+ isinstance(1, ClassVar[int])
+ with self.assertRaises(TypeError):
+ issubclass(int, ClassVar)
+
+
+class FinalTests(BaseTestCase):
+
+ def test_basics(self):
+ with self.assertRaises(TypeError):
+ Final[1]
+ with self.assertRaises(TypeError):
+ Final[int, str]
+ with self.assertRaises(TypeError):
+ Final[int][str]
+
+ def test_repr(self):
+ self.assertEqual(repr(Final), 'typing.Final')
+ cv = Final[int]
+ self.assertEqual(repr(cv), 'typing.Final[int]')
+ cv = Final[Employee]
+ self.assertEqual(repr(cv), 'typing.Final[%s.Employee]' % __name__)
+
+ def test_cannot_subclass(self):
+ with self.assertRaises(TypeError):
+ class C(type(Final)):
+ pass
+ with self.assertRaises(TypeError):
+ class C(type(Final[int])):
+ pass
+
+ def test_cannot_init(self):
+ with self.assertRaises(TypeError):
+ Final()
+ with self.assertRaises(TypeError):
+ type(Final)()
+ with self.assertRaises(TypeError):
+ type(Final[typing.Optional[int]])()
+
+ def test_no_isinstance(self):
+ with self.assertRaises(TypeError):
+ isinstance(1, Final[int])
+ with self.assertRaises(TypeError):
+ issubclass(int, Final)
+
+
+class LiteralTests(BaseTestCase):
+ def test_basics(self):
+ Literal[1]
+ Literal[1, 2, 3]
+ Literal["x", "y", "z"]
+ Literal[None]
+
+ def test_illegal_parameters_do_not_raise_runtime_errors(self):
+ # Type checkers should reject these types, but we do not
+ # raise errors at runtime to maintain maximium flexibility
+ Literal[int]
+ Literal[Literal[1, 2], Literal[4, 5]]
+ Literal[3j + 2, ..., ()]
+ Literal[b"foo", u"bar"]
+ Literal[{"foo": 3, "bar": 4}]
+ Literal[T]
+
+ def test_literals_inside_other_types(self):
+ typing.List[Literal[1, 2, 3]]
+ typing.List[Literal[("foo", "bar", "baz")]]
+
+ def test_repr(self):
+ self.assertEqual(repr(Literal[1]), "typing.Literal[1]")
+ self.assertEqual(repr(Literal[1, True, "foo"]), "typing.Literal[1, True, u'foo']")
+ self.assertEqual(repr(Literal[int]), "typing.Literal[int]")
+ self.assertEqual(repr(Literal), "typing.Literal")
+ self.assertEqual(repr(Literal[None]), "typing.Literal[None]")
+
+ def test_cannot_init(self):
+ with self.assertRaises(TypeError):
+ Literal()
+ with self.assertRaises(TypeError):
+ Literal[1]()
+ with self.assertRaises(TypeError):
+ type(Literal)()
+ with self.assertRaises(TypeError):
+ type(Literal[1])()
+
+ def test_no_isinstance_or_issubclass(self):
+ with self.assertRaises(TypeError):
+ isinstance(1, Literal[1])
+ with self.assertRaises(TypeError):
+ isinstance(int, Literal[1])
+ with self.assertRaises(TypeError):
+ issubclass(1, Literal[1])
+ with self.assertRaises(TypeError):
+ issubclass(int, Literal[1])
+
+ def test_no_subclassing(self):
+ with self.assertRaises(TypeError):
+ class Foo(Literal[1]): pass
+ with self.assertRaises(TypeError):
+ class Bar(Literal): pass
+
+ def test_no_multiple_subscripts(self):
+ with self.assertRaises(TypeError):
+ Literal[1][1]
+
+
+class CastTests(BaseTestCase):
+
+ def test_basics(self):
+ self.assertEqual(cast(int, 42), 42)
+ self.assertEqual(cast(float, 42), 42)
+ self.assertIs(type(cast(float, 42)), int)
+ self.assertEqual(cast(Any, 42), 42)
+ self.assertEqual(cast(list, 42), 42)
+ self.assertEqual(cast(Union[str, float], 42), 42)
+ self.assertEqual(cast(AnyStr, 42), 42)
+ self.assertEqual(cast(None, 42), 42)
+
+ def test_errors(self):
+ # Bogus calls are not expected to fail.
+ cast(42, 42)
+ cast('hello', 42)
+
+
+class ForwardRefTests(BaseTestCase):
+
+ def test_forwardref_instance_type_error(self):
+ fr = typing._ForwardRef('int')
+ with self.assertRaises(TypeError):
+ isinstance(42, fr)
+
+ def test_syntax_error(self):
+
+ with self.assertRaises(SyntaxError):
+ Generic['/T']
+
+ def test_forwardref_subclass_type_error(self):
+ fr = typing._ForwardRef('int')
+ with self.assertRaises(TypeError):
+ issubclass(int, fr)
+
+ def test_forward_equality(self):
+ fr = typing._ForwardRef('int')
+ self.assertEqual(fr, typing._ForwardRef('int'))
+ self.assertNotEqual(List['int'], List[int])
+
+ def test_forward_repr(self):
+ self.assertEqual(repr(List['int']), "typing.List[_ForwardRef(%r)]" % 'int')
+
+
+class OverloadTests(BaseTestCase):
+
+ def test_overload_fails(self):
+ from typing import overload
+
+ with self.assertRaises(RuntimeError):
+
+ @overload
+ def blah():
+ pass
+
+ blah()
+
+ def test_overload_succeeds(self):
+ from typing import overload
+
+ @overload
+ def blah():
+ pass
+
+ def blah():
+ pass
+
+ blah()
+
+
+class CollectionsAbcTests(BaseTestCase):
+
+ def test_hashable(self):
+ self.assertIsInstance(42, typing.Hashable)
+ self.assertNotIsInstance([], typing.Hashable)
+
+ def test_iterable(self):
+ self.assertIsInstance([], typing.Iterable)
+ # Due to ABC caching, the second time takes a separate code
+ # path and could fail. So call this a few times.
+ self.assertIsInstance([], typing.Iterable)
+ self.assertIsInstance([], typing.Iterable)
+ self.assertNotIsInstance(42, typing.Iterable)
+ # Just in case, also test issubclass() a few times.
+ self.assertIsSubclass(list, typing.Iterable)
+ self.assertIsSubclass(list, typing.Iterable)
+
+ def test_iterator(self):
+ it = iter([])
+ self.assertIsInstance(it, typing.Iterator)
+ self.assertNotIsInstance(42, typing.Iterator)
+
+ def test_sized(self):
+ self.assertIsInstance([], typing.Sized)
+ self.assertNotIsInstance(42, typing.Sized)
+
+ def test_container(self):
+ self.assertIsInstance([], typing.Container)
+ self.assertNotIsInstance(42, typing.Container)
+
+ def test_abstractset(self):
+ self.assertIsInstance(set(), typing.AbstractSet)
+ self.assertNotIsInstance(42, typing.AbstractSet)
+
+ def test_mutableset(self):
+ self.assertIsInstance(set(), typing.MutableSet)
+ self.assertNotIsInstance(frozenset(), typing.MutableSet)
+
+ def test_mapping(self):
+ self.assertIsInstance({}, typing.Mapping)
+ self.assertNotIsInstance(42, typing.Mapping)
+
+ def test_mutablemapping(self):
+ self.assertIsInstance({}, typing.MutableMapping)
+ self.assertNotIsInstance(42, typing.MutableMapping)
+
+ def test_sequence(self):
+ self.assertIsInstance([], typing.Sequence)
+ self.assertNotIsInstance(42, typing.Sequence)
+
+ def test_mutablesequence(self):
+ self.assertIsInstance([], typing.MutableSequence)
+ self.assertNotIsInstance((), typing.MutableSequence)
+
+ def test_bytestring(self):
+ self.assertIsInstance(b'', typing.ByteString)
+ self.assertIsInstance(bytearray(b''), typing.ByteString)
+
+ def test_list(self):
+ self.assertIsSubclass(list, typing.List)
+
+ def test_deque(self):
+ self.assertIsSubclass(collections.deque, typing.Deque)
+ class MyDeque(typing.Deque[int]): pass
+ self.assertIsInstance(MyDeque(), collections.deque)
+
+ def test_counter(self):
+ self.assertIsSubclass(collections.Counter, typing.Counter)
+
+ def test_set(self):
+ self.assertIsSubclass(set, typing.Set)
+ self.assertNotIsSubclass(frozenset, typing.Set)
+
+ def test_frozenset(self):
+ self.assertIsSubclass(frozenset, typing.FrozenSet)
+ self.assertNotIsSubclass(set, typing.FrozenSet)
+
+ def test_dict(self):
+ self.assertIsSubclass(dict, typing.Dict)
+
+ def test_no_list_instantiation(self):
+ with self.assertRaises(TypeError):
+ typing.List()
+ with self.assertRaises(TypeError):
+ typing.List[T]()
+ with self.assertRaises(TypeError):
+ typing.List[int]()
+
+ def test_list_subclass(self):
+
+ class MyList(typing.List[int]):
+ pass
+
+ a = MyList()
+ self.assertIsInstance(a, MyList)
+ self.assertIsInstance(a, typing.Sequence)
+
+ self.assertIsSubclass(MyList, list)
+ self.assertNotIsSubclass(list, MyList)
+
+ def test_no_dict_instantiation(self):
+ with self.assertRaises(TypeError):
+ typing.Dict()
+ with self.assertRaises(TypeError):
+ typing.Dict[KT, VT]()
+ with self.assertRaises(TypeError):
+ typing.Dict[str, int]()
+
+ def test_dict_subclass(self):
+
+ class MyDict(typing.Dict[str, int]):
+ pass
+
+ d = MyDict()
+ self.assertIsInstance(d, MyDict)
+ self.assertIsInstance(d, typing.MutableMapping)
+
+ self.assertIsSubclass(MyDict, dict)
+ self.assertNotIsSubclass(dict, MyDict)
+
+ def test_defaultdict_instantiation(self):
+ self.assertIs(type(typing.DefaultDict()), collections.defaultdict)
+ self.assertIs(type(typing.DefaultDict[KT, VT]()), collections.defaultdict)
+ self.assertIs(type(typing.DefaultDict[str, int]()), collections.defaultdict)
+
+ def test_defaultdict_subclass(self):
+
+ class MyDefDict(typing.DefaultDict[str, int]):
+ pass
+
+ dd = MyDefDict()
+ self.assertIsInstance(dd, MyDefDict)
+
+ self.assertIsSubclass(MyDefDict, collections.defaultdict)
+ self.assertNotIsSubclass(collections.defaultdict, MyDefDict)
+
+ def test_deque_instantiation(self):
+ self.assertIs(type(typing.Deque()), collections.deque)
+ self.assertIs(type(typing.Deque[T]()), collections.deque)
+ self.assertIs(type(typing.Deque[int]()), collections.deque)
+ class D(typing.Deque[T]): pass
+ self.assertIs(type(D[int]()), D)
+
+ def test_counter_instantiation(self):
+ self.assertIs(type(typing.Counter()), collections.Counter)
+ self.assertIs(type(typing.Counter[T]()), collections.Counter)
+ self.assertIs(type(typing.Counter[int]()), collections.Counter)
+ class C(typing.Counter[T]): pass
+ self.assertIs(type(C[int]()), C)
+
+ def test_counter_subclass_instantiation(self):
+
+ class MyCounter(typing.Counter[int]):
+ pass
+
+ d = MyCounter()
+ self.assertIsInstance(d, MyCounter)
+ self.assertIsInstance(d, typing.Counter)
+ self.assertIsInstance(d, collections.Counter)
+
+ def test_no_set_instantiation(self):
+ with self.assertRaises(TypeError):
+ typing.Set()
+ with self.assertRaises(TypeError):
+ typing.Set[T]()
+ with self.assertRaises(TypeError):
+ typing.Set[int]()
+
+ def test_set_subclass_instantiation(self):
+
+ class MySet(typing.Set[int]):
+ pass
+
+ d = MySet()
+ self.assertIsInstance(d, MySet)
+
+ def test_no_frozenset_instantiation(self):
+ with self.assertRaises(TypeError):
+ typing.FrozenSet()
+ with self.assertRaises(TypeError):
+ typing.FrozenSet[T]()
+ with self.assertRaises(TypeError):
+ typing.FrozenSet[int]()
+
+ def test_frozenset_subclass_instantiation(self):
+
+ class MyFrozenSet(typing.FrozenSet[int]):
+ pass
+
+ d = MyFrozenSet()
+ self.assertIsInstance(d, MyFrozenSet)
+
+ def test_no_tuple_instantiation(self):
+ with self.assertRaises(TypeError):
+ Tuple()
+ with self.assertRaises(TypeError):
+ Tuple[T]()
+ with self.assertRaises(TypeError):
+ Tuple[int]()
+
+ def test_generator(self):
+ def foo():
+ yield 42
+ g = foo()
+ self.assertIsSubclass(type(g), typing.Generator)
+
+ def test_no_generator_instantiation(self):
+ with self.assertRaises(TypeError):
+ typing.Generator()
+ with self.assertRaises(TypeError):
+ typing.Generator[T, T, T]()
+ with self.assertRaises(TypeError):
+ typing.Generator[int, int, int]()
+
+ def test_subclassing(self):
+
+ class MMA(typing.MutableMapping):
+ pass
+
+ with self.assertRaises(TypeError): # It's abstract
+ MMA()
+
+ class MMC(MMA):
+ 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
+
+ self.assertEqual(len(MMC()), 0)
+ assert callable(MMC.update)
+ self.assertIsInstance(MMC(), typing.Mapping)
+
+ class MMB(typing.MutableMapping[KT, VT]):
+ 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
+
+ self.assertEqual(len(MMB()), 0)
+ self.assertEqual(len(MMB[str, str]()), 0)
+ self.assertEqual(len(MMB[KT, VT]()), 0)
+
+ self.assertNotIsSubclass(dict, MMA)
+ self.assertNotIsSubclass(dict, MMB)
+
+ self.assertIsSubclass(MMA, typing.Mapping)
+ self.assertIsSubclass(MMB, typing.Mapping)
+ self.assertIsSubclass(MMC, typing.Mapping)
+
+ self.assertIsInstance(MMB[KT, VT](), typing.Mapping)
+ self.assertIsInstance(MMB[KT, VT](), collections.Mapping)
+
+ self.assertIsSubclass(MMA, collections.Mapping)
+ self.assertIsSubclass(MMB, collections.Mapping)
+ self.assertIsSubclass(MMC, collections.Mapping)
+
+ self.assertIsSubclass(MMB[str, str], typing.Mapping)
+ self.assertIsSubclass(MMC, MMA)
+
+ class It(typing.Iterable): pass
+ self.assertNotIsSubclass(list, It)
+
+ class G(typing.Generator[int, int, int]): pass
+ def g(): yield 0
+ self.assertIsSubclass(G, typing.Generator)
+ self.assertIsSubclass(G, typing.Iterable)
+ if hasattr(collections, 'Generator'):
+ self.assertIsSubclass(G, collections.Generator)
+ self.assertIsSubclass(G, collections.Iterable)
+ self.assertNotIsSubclass(type(g), G)
+
+ def test_subclassing_subclasshook(self):
+
+ class Base(typing.Iterable):
+ @classmethod
+ def __subclasshook__(cls, other):
+ if other.__name__ == 'Foo':
+ return True
+ else:
+ return False
+
+ class C(Base): pass
+ class Foo: pass
+ class Bar: pass
+ self.assertIsSubclass(Foo, Base)
+ self.assertIsSubclass(Foo, C)
+ self.assertNotIsSubclass(Bar, C)
+
+ def test_subclassing_register(self):
+
+ class A(typing.Container): pass
+ class B(A): pass
+
+ class C: pass
+ A.register(C)
+ self.assertIsSubclass(C, A)
+ self.assertNotIsSubclass(C, B)
+
+ class D: pass
+ B.register(D)
+ self.assertIsSubclass(D, A)
+ self.assertIsSubclass(D, B)
+
+ class M(): pass
+ collections.MutableMapping.register(M)
+ self.assertIsSubclass(M, typing.Mapping)
+
+ def test_collections_as_base(self):
+
+ class M(collections.Mapping): pass
+ self.assertIsSubclass(M, typing.Mapping)
+ self.assertIsSubclass(M, typing.Iterable)
+
+ class S(collections.MutableSequence): pass
+ self.assertIsSubclass(S, typing.MutableSequence)
+ self.assertIsSubclass(S, typing.Iterable)
+
+ class It(collections.Iterable): pass
+ self.assertIsSubclass(It, typing.Iterable)
+
+ class A(collections.Mapping): pass
+ class B: pass
+ A.register(B)
+ self.assertIsSubclass(B, typing.Mapping)
+
+
+class OtherABCTests(BaseTestCase):
+
+ def test_contextmanager(self):
+ @contextlib.contextmanager
+ def manager():
+ yield 42
+
+ cm = manager()
+ self.assertIsInstance(cm, typing.ContextManager)
+ self.assertNotIsInstance(42, typing.ContextManager)
+
+
+class TypeTests(BaseTestCase):
+
+ def test_type_basic(self):
+
+ class User(object): pass
+ class BasicUser(User): pass
+ class ProUser(User): pass
+
+ def new_user(user_class):
+ # type: (Type[User]) -> User
+ return user_class()
+
+ new_user(BasicUser)
+
+ def test_type_typevar(self):
+
+ class User(object): pass
+ class BasicUser(User): pass
+ class ProUser(User): pass
+
+ global U
+ U = TypeVar('U', bound=User)
+
+ def new_user(user_class):
+ # type: (Type[U]) -> U
+ return user_class()
+
+ new_user(BasicUser)
+
+ def test_type_optional(self):
+ A = Optional[Type[BaseException]] # noqa
+
+ def foo(a):
+ # type: (A) -> Optional[BaseException]
+ if a is None:
+ return None
+ else:
+ return a()
+
+ assert isinstance(foo(KeyboardInterrupt), KeyboardInterrupt)
+ assert foo(None) is None
+
+
+class NewTypeTests(BaseTestCase):
+
+ def test_basic(self):
+ UserId = NewType('UserId', int)
+ UserName = NewType('UserName', str)
+ self.assertIsInstance(UserId(5), int)
+ self.assertIsInstance(UserName('Joe'), type('Joe'))
+ self.assertEqual(UserId(5) + 1, 6)
+
+ def test_errors(self):
+ UserId = NewType('UserId', int)
+ UserName = NewType('UserName', str)
+ with self.assertRaises(TypeError):
+ issubclass(UserId, int)
+ with self.assertRaises(TypeError):
+ class D(UserName):
+ pass
+
+
+class NamedTupleTests(BaseTestCase):
+
+ def test_basics(self):
+ Emp = NamedTuple('Emp', [('name', str), ('id', int)])
+ self.assertIsSubclass(Emp, tuple)
+ joe = Emp('Joe', 42)
+ jim = Emp(name='Jim', id=1)
+ self.assertIsInstance(joe, Emp)
+ self.assertIsInstance(joe, tuple)
+ self.assertEqual(joe.name, 'Joe')
+ self.assertEqual(joe.id, 42)
+ self.assertEqual(jim.name, 'Jim')
+ self.assertEqual(jim.id, 1)
+ self.assertEqual(Emp.__name__, 'Emp')
+ self.assertEqual(Emp._fields, ('name', 'id'))
+ self.assertEqual(Emp._field_types, dict(name=str, id=int))
+
+ def test_pickle(self):
+ global Emp # pickle wants to reference the class by name
+ Emp = NamedTuple('Emp', [('name', str), ('id', int)])
+ jane = Emp('jane', 37)
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ z = pickle.dumps(jane, proto)
+ jane2 = pickle.loads(z)
+ self.assertEqual(jane2, jane)
+
+
+class TypedDictTests(BaseTestCase):
+
+ def test_basics_iterable_syntax(self):
+ Emp = TypedDict(b'Emp', {'name': str, 'id': int})
+ self.assertIsSubclass(Emp, dict)
+ self.assertIsSubclass(Emp, typing.MutableMapping)
+ if sys.version_info[0] >= 3:
+ import collections.abc
+ self.assertNotIsSubclass(Emp, collections.abc.Sequence)
+ jim = Emp(name='Jim', id=1)
+ self.assertIs(type(jim), dict)
+ self.assertEqual(jim['name'], 'Jim')
+ self.assertEqual(jim['id'], 1)
+ self.assertEqual(Emp.__name__, 'Emp')
+ self.assertEqual(Emp.__module__, __name__)
+ self.assertEqual(Emp.__bases__, (dict,))
+ self.assertEqual(Emp.__annotations__, {'name': str, 'id': int})
+ self.assertEqual(Emp.__total__, True)
+
+ def test_basics_keywords_syntax(self):
+ Emp = TypedDict(b'Emp', name=str, id=int)
+ self.assertIsSubclass(Emp, dict)
+ self.assertIsSubclass(Emp, typing.MutableMapping)
+ if sys.version_info[0] >= 3:
+ import collections.abc
+ self.assertNotIsSubclass(Emp, collections.abc.Sequence)
+ jim = Emp(name='Jim', id=1)
+ self.assertIs(type(jim), dict)
+ self.assertEqual(jim['name'], 'Jim')
+ self.assertEqual(jim['id'], 1)
+ self.assertEqual(Emp.__name__, 'Emp')
+ self.assertEqual(Emp.__module__, __name__)
+ self.assertEqual(Emp.__bases__, (dict,))
+ self.assertEqual(Emp.__annotations__, {'name': str, 'id': int})
+ self.assertEqual(Emp.__total__, True)
+
+ def test_typeddict_errors(self):
+ Emp = TypedDict(b'Emp', {'name': str, 'id': int})
+ self.assertEqual(TypedDict.__module__, 'typing')
+ jim = Emp(name='Jim', id=1)
+ with self.assertRaises(TypeError):
+ isinstance({}, Emp)
+ with self.assertRaises(TypeError):
+ isinstance(jim, Emp)
+ with self.assertRaises(TypeError):
+ issubclass(dict, Emp)
+ with self.assertRaises(TypeError):
+ TypedDict('Hi', x=1)
+ with self.assertRaises(TypeError):
+ TypedDict('Hi', [('x', int), ('y', 1)])
+ with self.assertRaises(TypeError):
+ TypedDict('Hi', [('x', int)], y=int)
+
+ def test_pickle(self):
+ global EmpD # pickle wants to reference the class by name
+ EmpD = TypedDict(b'EmpD', name=str, id=int)
+ jane = EmpD({'name': 'jane', 'id': 37})
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ z = pickle.dumps(jane, proto)
+ jane2 = pickle.loads(z)
+ self.assertEqual(jane2, jane)
+ self.assertEqual(jane2, {'name': 'jane', 'id': 37})
+ ZZ = pickle.dumps(EmpD, proto)
+ EmpDnew = pickle.loads(ZZ)
+ self.assertEqual(EmpDnew({'name': 'jane', 'id': 37}), jane)
+
+ def test_optional(self):
+ EmpD = TypedDict(b'EmpD', name=str, id=int)
+
+ self.assertEqual(typing.Optional[EmpD], typing.Union[None, EmpD])
+ self.assertNotEqual(typing.List[EmpD], typing.Tuple[EmpD])
+
+ def test_total(self):
+ D = TypedDict(b'D', {'x': int}, total=False)
+ self.assertEqual(D(), {})
+ self.assertEqual(D(x=1), {'x': 1})
+ self.assertEqual(D.__total__, False)
+
+
+class IOTests(BaseTestCase):
+
+ def test_io_submodule(self):
+ from typing.io import IO, TextIO, BinaryIO, __all__, __name__
+ self.assertIs(IO, typing.IO)
+ self.assertIs(TextIO, typing.TextIO)
+ self.assertIs(BinaryIO, typing.BinaryIO)
+ self.assertEqual(set(__all__), set(['IO', 'TextIO', 'BinaryIO']))
+ self.assertEqual(__name__, 'typing.io')
+
+
+class RETests(BaseTestCase):
+ # Much of this is really testing _TypeAlias.
+
+ def test_basics(self):
+ pat = re.compile('[a-z]+', re.I)
+ self.assertIsSubclass(pat.__class__, Pattern)
+ self.assertIsSubclass(type(pat), Pattern)
+ self.assertIsInstance(pat, Pattern)
+
+ mat = pat.search('12345abcde.....')
+ self.assertIsSubclass(mat.__class__, Match)
+ self.assertIsSubclass(type(mat), Match)
+ self.assertIsInstance(mat, Match)
+
+ # these should just work
+ Pattern[Union[str, bytes]]
+ Match[Union[bytes, str]]
+
+ def test_alias_equality(self):
+ self.assertEqual(Pattern[str], Pattern[str])
+ self.assertNotEqual(Pattern[str], Pattern[bytes])
+ self.assertNotEqual(Pattern[str], Match[str])
+ self.assertNotEqual(Pattern[str], str)
+
+ def test_errors(self):
+ with self.assertRaises(TypeError):
+ # Doesn't fit AnyStr.
+ Pattern[int]
+ with self.assertRaises(TypeError):
+ # Can't change type vars?
+ Match[T]
+ m = Match[Union[str, bytes]]
+ with self.assertRaises(TypeError):
+ # Too complicated?
+ m[str]
+ with self.assertRaises(TypeError):
+ # We don't support isinstance().
+ isinstance(42, Pattern[str])
+ with self.assertRaises(TypeError):
+ # We don't support issubclass().
+ issubclass(Pattern[bytes], Pattern[str])
+
+ def test_repr(self):
+ self.assertEqual(repr(Pattern), 'Pattern[~AnyStr]')
+ self.assertEqual(repr(Pattern[unicode]), 'Pattern[unicode]')
+ self.assertEqual(repr(Pattern[str]), 'Pattern[str]')
+ self.assertEqual(repr(Match), 'Match[~AnyStr]')
+ self.assertEqual(repr(Match[unicode]), 'Match[unicode]')
+ self.assertEqual(repr(Match[str]), 'Match[str]')
+
+ def test_re_submodule(self):
+ from typing.re import Match, Pattern, __all__, __name__
+ self.assertIs(Match, typing.Match)
+ self.assertIs(Pattern, typing.Pattern)
+ self.assertEqual(set(__all__), set(['Match', 'Pattern']))
+ self.assertEqual(__name__, 'typing.re')
+
+ def test_cannot_subclass(self):
+ with self.assertRaises(TypeError) as ex:
+
+ class A(typing.Match):
+ pass
+
+ self.assertEqual(str(ex.exception),
+ "Cannot subclass typing._TypeAlias")
+
+
+class AllTests(BaseTestCase):
+ """Tests for __all__."""
+
+ def test_all(self):
+ from typing import __all__ as a
+ # Just spot-check the first and last of every category.
+ self.assertIn('AbstractSet', a)
+ self.assertIn('ValuesView', a)
+ self.assertIn('cast', a)
+ self.assertIn('overload', a)
+ # Check that io and re are not exported.
+ self.assertNotIn('io', a)
+ self.assertNotIn('re', a)
+ # Spot-check that stdlib modules aren't exported.
+ self.assertNotIn('os', a)
+ self.assertNotIn('sys', a)
+ # Check that Text is defined.
+ self.assertIn('Text', a)
+ # Check previously missing class.
+ self.assertIn('SupportsComplex', a)
+
+ def test_respect_no_type_check(self):
+ @typing.no_type_check
+ class NoTpCheck(object):
+ class Inn(object):
+ def __init__(self, x):
+ # type: (this is not actually a type) -> None # noqa
+ pass
+ self.assertTrue(NoTpCheck.__no_type_check__)
+ self.assertTrue(NoTpCheck.Inn.__init__.__no_type_check__)
+
+ def test_get_type_hints_dummy(self):
+
+ def foo(x):
+ # type: (int) -> int
+ return x + 1
+
+ self.assertIsNone(typing.get_type_hints(foo))
+
+ # def test_typing_compiles_with_opt(self):
+ # file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ # 'typing.py')
+ # try:
+ # subprocess.check_output([sys.executable, '-OO', file_path],
+ # stderr=subprocess.STDOUT)
+ # except subprocess.CalledProcessError:
+ # self.fail('Module does not compile with optimize=2 (-OO flag).')
+
+
+if __name__ == '__main__':
+ main()