blob: 9d8dbfe04205fd500f4bd7ad0e13175026e2b7ad [file] [log] [blame]
Guido van Rossum48b069a2020-04-07 09:50:06 -07001"""Tests for C-implemented GenericAlias."""
2
3import unittest
4import pickle
5from collections import (
6 defaultdict, deque, OrderedDict, Counter, UserDict, UserList
7)
8from collections.abc import *
9from contextlib import AbstractContextManager, AbstractAsyncContextManager
10from re import Pattern, Match
11from types import GenericAlias, MappingProxyType
12import typing
13
14from typing import TypeVar
15T = TypeVar('T')
16
17class BaseTest(unittest.TestCase):
18 """Test basics."""
19
20 def test_subscriptable(self):
21 for t in (type, tuple, list, dict, set, frozenset,
22 defaultdict, deque,
23 OrderedDict, Counter, UserDict, UserList,
24 Pattern, Match,
25 AbstractContextManager, AbstractAsyncContextManager,
26 Awaitable, Coroutine,
27 AsyncIterable, AsyncIterator,
28 AsyncGenerator, Generator,
29 Iterable, Iterator,
30 Reversible,
31 Container, Collection,
32 Callable,
33 Set, MutableSet,
34 Mapping, MutableMapping, MappingView,
35 KeysView, ItemsView, ValuesView,
36 Sequence, MutableSequence,
37 MappingProxyType,
38 ):
39 tname = t.__name__
40 with self.subTest(f"Testing {tname}"):
41 alias = t[int]
42 self.assertIs(alias.__origin__, t)
43 self.assertEqual(alias.__args__, (int,))
44 self.assertEqual(alias.__parameters__, ())
45
46 def test_unsubscriptable(self):
47 for t in int, str, float, Sized, Hashable:
48 tname = t.__name__
49 with self.subTest(f"Testing {tname}"):
50 with self.assertRaises(TypeError):
51 t[int]
52
53 def test_instantiate(self):
54 for t in tuple, list, dict, set, frozenset, defaultdict, deque:
55 tname = t.__name__
56 with self.subTest(f"Testing {tname}"):
57 alias = t[int]
58 self.assertEqual(alias(), t())
59 if t is dict:
60 self.assertEqual(alias(iter([('a', 1), ('b', 2)])), dict(a=1, b=2))
61 self.assertEqual(alias(a=1, b=2), dict(a=1, b=2))
62 elif t is defaultdict:
63 def default():
64 return 'value'
65 a = alias(default)
66 d = defaultdict(default)
67 self.assertEqual(a['test'], d['test'])
68 else:
69 self.assertEqual(alias(iter((1, 2, 3))), t((1, 2, 3)))
70
71 def test_unbound_methods(self):
72 t = list[int]
73 a = t()
74 t.append(a, 'foo')
75 self.assertEqual(a, ['foo'])
76 x = t.__getitem__(a, 0)
77 self.assertEqual(x, 'foo')
78 self.assertEqual(t.__len__(a), 1)
79
80 def test_subclassing(self):
81 class C(list[int]):
82 pass
83 self.assertEqual(C.__bases__, (list,))
84 self.assertEqual(C.__class__, type)
85
86 def test_class_methods(self):
87 t = dict[int, None]
88 self.assertEqual(dict.fromkeys(range(2)), {0: None, 1: None}) # This works
89 self.assertEqual(t.fromkeys(range(2)), {0: None, 1: None}) # Should be equivalent
90
91 def test_no_chaining(self):
92 t = list[int]
93 with self.assertRaises(TypeError):
94 t[int]
95
96 def test_generic_subclass(self):
97 class MyList(list):
98 pass
99 t = MyList[int]
100 self.assertIs(t.__origin__, MyList)
101 self.assertEqual(t.__args__, (int,))
102 self.assertEqual(t.__parameters__, ())
103
104 def test_repr(self):
105 class MyList(list):
106 pass
107 self.assertEqual(repr(list[str]), 'list[str]')
108 self.assertEqual(repr(list[()]), 'list[()]')
109 self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]')
110 self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]'))
111 self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr
112
113 def test_exposed_type(self):
114 import types
115 a = types.GenericAlias(list, int)
116 self.assertEqual(str(a), 'list[int]')
117 self.assertIs(a.__origin__, list)
118 self.assertEqual(a.__args__, (int,))
119 self.assertEqual(a.__parameters__, ())
120
121 def test_parameters(self):
122 from typing import TypeVar
123 T = TypeVar('T')
124 K = TypeVar('K')
125 V = TypeVar('V')
126 D0 = dict[str, int]
127 self.assertEqual(D0.__args__, (str, int))
128 self.assertEqual(D0.__parameters__, ())
129 D1a = dict[str, V]
130 self.assertEqual(D1a.__args__, (str, V))
131 self.assertEqual(D1a.__parameters__, (V,))
132 D1b = dict[K, int]
133 self.assertEqual(D1b.__args__, (K, int))
134 self.assertEqual(D1b.__parameters__, (K,))
135 D2a = dict[K, V]
136 self.assertEqual(D2a.__args__, (K, V))
137 self.assertEqual(D2a.__parameters__, (K, V))
138 D2b = dict[T, T]
139 self.assertEqual(D2b.__args__, (T, T))
140 self.assertEqual(D2b.__parameters__, (T,))
141 L0 = list[str]
142 self.assertEqual(L0.__args__, (str,))
143 self.assertEqual(L0.__parameters__, ())
144 L1 = list[T]
145 self.assertEqual(L1.__args__, (T,))
146 self.assertEqual(L1.__parameters__, (T,))
147
148 def test_parameter_chaining(self):
149 from typing import TypeVar
150 T = TypeVar('T')
151 self.assertEqual(list[T][int], list[int])
152 self.assertEqual(dict[str, T][int], dict[str, int])
153 self.assertEqual(dict[T, int][str], dict[str, int])
154 self.assertEqual(dict[T, T][int], dict[int, int])
155 with self.assertRaises(TypeError):
156 list[int][int]
157 dict[T, int][str, int]
158 dict[str, T][str, int]
159 dict[T, T][str, int]
160
161 def test_equality(self):
162 self.assertEqual(list[int], list[int])
163 self.assertEqual(dict[str, int], dict[str, int])
164 self.assertNotEqual(dict[str, int], dict[str, str])
165 self.assertNotEqual(list, list[int])
166 self.assertNotEqual(list[int], list)
167
168 def test_isinstance(self):
169 self.assertTrue(isinstance([], list))
170 with self.assertRaises(TypeError):
171 isinstance([], list[str])
172
173 def test_issubclass(self):
174 class L(list): ...
175 self.assertTrue(issubclass(L, list))
176 with self.assertRaises(TypeError):
177 issubclass(L, list[str])
178
179 def test_type_generic(self):
180 t = type[int]
181 Test = t('Test', (), {})
182 self.assertTrue(isinstance(Test, type))
183 test = Test()
184 self.assertEqual(t(test), Test)
185 self.assertEqual(t(0), int)
186
187 def test_type_subclass_generic(self):
188 class MyType(type):
189 pass
190 with self.assertRaises(TypeError):
191 MyType[int]
192
193 def test_pickle(self):
194 alias = GenericAlias(list, T)
195 s = pickle.dumps(alias)
196 loaded = pickle.loads(s)
197 self.assertEqual(alias.__origin__, loaded.__origin__)
198 self.assertEqual(alias.__args__, loaded.__args__)
199 self.assertEqual(alias.__parameters__, loaded.__parameters__)
200
201 def test_union(self):
202 a = typing.Union[list[int], list[str]]
203 self.assertEqual(a.__args__, (list[int], list[str]))
204 self.assertEqual(a.__parameters__, ())
205
206 def test_union_generic(self):
207 T = typing.TypeVar('T')
208 a = typing.Union[list[T], tuple[T, ...]]
209 self.assertEqual(a.__args__, (list[T], tuple[T, ...]))
210 self.assertEqual(a.__parameters__, (T,))
211
212
213if __name__ == "__main__":
214 unittest.main()