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