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