blob: 643fffc073e82f3e2524d64c59f58bd2469848c8 [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 *
Batuhan Taşkaya03615562020-04-10 17:46:36 +03009from concurrent.futures import Future
10from concurrent.futures.thread import _WorkItem
Guido van Rossum48b069a2020-04-07 09:50:06 -070011from contextlib import AbstractContextManager, AbstractAsyncContextManager
Ethan Smithd01628e2020-04-14 16:14:15 -070012from contextvars import ContextVar, Token
13from dataclasses import Field
14from functools import partial, partialmethod, cached_property
15from mailbox import Mailbox, _PartialFile
Victor Stinnerf44693e2020-08-07 17:56:42 +020016try:
17 import ctypes
18except ImportError:
19 ctypes = None
Ethan Smithe3ec44d2020-04-09 21:47:31 -070020from difflib import SequenceMatcher
21from filecmp import dircmp
22from fileinput import FileInput
Ethan Smitha8403d02020-04-09 20:28:08 -070023from itertools import chain
Batuhan Taşkaya03615562020-04-10 17:46:36 +030024from http.cookies import Morsel
25from multiprocessing.managers import ValueProxy
26from multiprocessing.pool import ApplyResult
Chih-Hsuan Yen25a68332020-04-14 06:00:16 +080027try:
28 from multiprocessing.shared_memory import ShareableList
29except ImportError:
30 # multiprocessing.shared_memory is not available on e.g. Android
31 ShareableList = None
Batuhan Taşkaya03615562020-04-10 17:46:36 +030032from multiprocessing.queues import SimpleQueue
Batuhan Taşkayaf9dd51e2020-04-08 00:37:19 +030033from os import DirEntry
Guido van Rossum48b069a2020-04-07 09:50:06 -070034from re import Pattern, Match
Ethan Smith7c4185d2020-04-09 21:25:53 -070035from types import GenericAlias, MappingProxyType, AsyncGeneratorType
Batuhan Taşkaya03615562020-04-10 17:46:36 +030036from tempfile import TemporaryDirectory, SpooledTemporaryFile
37from urllib.parse import SplitResult, ParseResult
38from unittest.case import _AssertRaisesContext
39from queue import Queue, SimpleQueue
Ethan Smith8ef87502020-04-13 21:54:40 -070040from weakref import WeakSet, ReferenceType, ref
Guido van Rossum48b069a2020-04-07 09:50:06 -070041import typing
42
43from typing import TypeVar
44T = TypeVar('T')
Serhiy Storchaka41a64582020-05-04 10:56:05 +030045K = TypeVar('K')
46V = TypeVar('V')
Guido van Rossum48b069a2020-04-07 09:50:06 -070047
48class BaseTest(unittest.TestCase):
49 """Test basics."""
50
51 def test_subscriptable(self):
Victor Stinnerf44693e2020-08-07 17:56:42 +020052 types = [type, tuple, list, dict, set, frozenset, enumerate,
53 defaultdict, deque,
54 SequenceMatcher,
55 dircmp,
56 FileInput,
57 OrderedDict, Counter, UserDict, UserList,
58 Pattern, Match,
59 partial, partialmethod, cached_property,
60 AbstractContextManager, AbstractAsyncContextManager,
61 Awaitable, Coroutine,
62 AsyncIterable, AsyncIterator,
63 AsyncGenerator, Generator,
64 Iterable, Iterator,
65 Reversible,
66 Container, Collection,
67 Callable,
68 Mailbox, _PartialFile,
69 ContextVar, Token,
70 Field,
71 Set, MutableSet,
72 Mapping, MutableMapping, MappingView,
73 KeysView, ItemsView, ValuesView,
74 Sequence, MutableSequence,
75 MappingProxyType, AsyncGeneratorType,
76 DirEntry,
77 chain,
78 TemporaryDirectory, SpooledTemporaryFile,
79 Queue, SimpleQueue,
80 _AssertRaisesContext,
81 SplitResult, ParseResult,
82 ValueProxy, ApplyResult,
83 WeakSet, ReferenceType, ref,
84 ShareableList, SimpleQueue,
85 Future, _WorkItem,
86 Morsel]
87 if ctypes is not None:
88 types.extend((ctypes.Array, ctypes.LibraryLoader))
89 for t in types:
Chih-Hsuan Yen25a68332020-04-14 06:00:16 +080090 if t is None:
91 continue
Guido van Rossum48b069a2020-04-07 09:50:06 -070092 tname = t.__name__
93 with self.subTest(f"Testing {tname}"):
94 alias = t[int]
95 self.assertIs(alias.__origin__, t)
96 self.assertEqual(alias.__args__, (int,))
97 self.assertEqual(alias.__parameters__, ())
98
99 def test_unsubscriptable(self):
100 for t in int, str, float, Sized, Hashable:
101 tname = t.__name__
102 with self.subTest(f"Testing {tname}"):
103 with self.assertRaises(TypeError):
104 t[int]
105
106 def test_instantiate(self):
107 for t in tuple, list, dict, set, frozenset, defaultdict, deque:
108 tname = t.__name__
109 with self.subTest(f"Testing {tname}"):
110 alias = t[int]
111 self.assertEqual(alias(), t())
112 if t is dict:
113 self.assertEqual(alias(iter([('a', 1), ('b', 2)])), dict(a=1, b=2))
114 self.assertEqual(alias(a=1, b=2), dict(a=1, b=2))
115 elif t is defaultdict:
116 def default():
117 return 'value'
118 a = alias(default)
119 d = defaultdict(default)
120 self.assertEqual(a['test'], d['test'])
121 else:
122 self.assertEqual(alias(iter((1, 2, 3))), t((1, 2, 3)))
123
124 def test_unbound_methods(self):
125 t = list[int]
126 a = t()
127 t.append(a, 'foo')
128 self.assertEqual(a, ['foo'])
129 x = t.__getitem__(a, 0)
130 self.assertEqual(x, 'foo')
131 self.assertEqual(t.__len__(a), 1)
132
133 def test_subclassing(self):
134 class C(list[int]):
135 pass
136 self.assertEqual(C.__bases__, (list,))
137 self.assertEqual(C.__class__, type)
138
139 def test_class_methods(self):
140 t = dict[int, None]
141 self.assertEqual(dict.fromkeys(range(2)), {0: None, 1: None}) # This works
142 self.assertEqual(t.fromkeys(range(2)), {0: None, 1: None}) # Should be equivalent
143
144 def test_no_chaining(self):
145 t = list[int]
146 with self.assertRaises(TypeError):
147 t[int]
148
149 def test_generic_subclass(self):
150 class MyList(list):
151 pass
152 t = MyList[int]
153 self.assertIs(t.__origin__, MyList)
154 self.assertEqual(t.__args__, (int,))
155 self.assertEqual(t.__parameters__, ())
156
157 def test_repr(self):
158 class MyList(list):
159 pass
160 self.assertEqual(repr(list[str]), 'list[str]')
161 self.assertEqual(repr(list[()]), 'list[()]')
162 self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]')
163 self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]'))
164 self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr
165
166 def test_exposed_type(self):
167 import types
168 a = types.GenericAlias(list, int)
169 self.assertEqual(str(a), 'list[int]')
170 self.assertIs(a.__origin__, list)
171 self.assertEqual(a.__args__, (int,))
172 self.assertEqual(a.__parameters__, ())
173
174 def test_parameters(self):
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300175 from typing import List, Dict, Callable
Guido van Rossum48b069a2020-04-07 09:50:06 -0700176 D0 = dict[str, int]
177 self.assertEqual(D0.__args__, (str, int))
178 self.assertEqual(D0.__parameters__, ())
179 D1a = dict[str, V]
180 self.assertEqual(D1a.__args__, (str, V))
181 self.assertEqual(D1a.__parameters__, (V,))
182 D1b = dict[K, int]
183 self.assertEqual(D1b.__args__, (K, int))
184 self.assertEqual(D1b.__parameters__, (K,))
185 D2a = dict[K, V]
186 self.assertEqual(D2a.__args__, (K, V))
187 self.assertEqual(D2a.__parameters__, (K, V))
188 D2b = dict[T, T]
189 self.assertEqual(D2b.__args__, (T, T))
190 self.assertEqual(D2b.__parameters__, (T,))
191 L0 = list[str]
192 self.assertEqual(L0.__args__, (str,))
193 self.assertEqual(L0.__parameters__, ())
194 L1 = list[T]
195 self.assertEqual(L1.__args__, (T,))
196 self.assertEqual(L1.__parameters__, (T,))
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300197 L2 = list[list[T]]
198 self.assertEqual(L2.__args__, (list[T],))
199 self.assertEqual(L2.__parameters__, (T,))
200 L3 = list[List[T]]
201 self.assertEqual(L3.__args__, (List[T],))
202 self.assertEqual(L3.__parameters__, (T,))
203 L4a = list[Dict[K, V]]
204 self.assertEqual(L4a.__args__, (Dict[K, V],))
205 self.assertEqual(L4a.__parameters__, (K, V))
206 L4b = list[Dict[T, int]]
207 self.assertEqual(L4b.__args__, (Dict[T, int],))
208 self.assertEqual(L4b.__parameters__, (T,))
209 L5 = list[Callable[[K, V], K]]
210 self.assertEqual(L5.__args__, (Callable[[K, V], K],))
211 self.assertEqual(L5.__parameters__, (K, V))
Guido van Rossum48b069a2020-04-07 09:50:06 -0700212
213 def test_parameter_chaining(self):
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300214 from typing import List, Dict, Union, Callable
Guido van Rossum48b069a2020-04-07 09:50:06 -0700215 self.assertEqual(list[T][int], list[int])
216 self.assertEqual(dict[str, T][int], dict[str, int])
217 self.assertEqual(dict[T, int][str], dict[str, int])
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300218 self.assertEqual(dict[K, V][str, int], dict[str, int])
Guido van Rossum48b069a2020-04-07 09:50:06 -0700219 self.assertEqual(dict[T, T][int], dict[int, int])
Serhiy Storchaka41a64582020-05-04 10:56:05 +0300220
221 self.assertEqual(list[list[T]][int], list[list[int]])
222 self.assertEqual(list[dict[T, int]][str], list[dict[str, int]])
223 self.assertEqual(list[dict[str, T]][int], list[dict[str, int]])
224 self.assertEqual(list[dict[K, V]][str, int], list[dict[str, int]])
225 self.assertEqual(dict[T, list[int]][str], dict[str, list[int]])
226
227 self.assertEqual(list[List[T]][int], list[List[int]])
228 self.assertEqual(list[Dict[K, V]][str, int], list[Dict[str, int]])
229 self.assertEqual(list[Union[K, V]][str, int], list[Union[str, int]])
230 self.assertEqual(list[Callable[[K, V], K]][str, int],
231 list[Callable[[str, int], str]])
232 self.assertEqual(dict[T, List[int]][str], dict[str, List[int]])
233
Guido van Rossum48b069a2020-04-07 09:50:06 -0700234 with self.assertRaises(TypeError):
235 list[int][int]
236 dict[T, int][str, int]
237 dict[str, T][str, int]
238 dict[T, T][str, int]
239
240 def test_equality(self):
241 self.assertEqual(list[int], list[int])
242 self.assertEqual(dict[str, int], dict[str, int])
243 self.assertNotEqual(dict[str, int], dict[str, str])
244 self.assertNotEqual(list, list[int])
245 self.assertNotEqual(list[int], list)
246
247 def test_isinstance(self):
248 self.assertTrue(isinstance([], list))
249 with self.assertRaises(TypeError):
250 isinstance([], list[str])
251
252 def test_issubclass(self):
253 class L(list): ...
254 self.assertTrue(issubclass(L, list))
255 with self.assertRaises(TypeError):
256 issubclass(L, list[str])
257
258 def test_type_generic(self):
259 t = type[int]
260 Test = t('Test', (), {})
261 self.assertTrue(isinstance(Test, type))
262 test = Test()
263 self.assertEqual(t(test), Test)
264 self.assertEqual(t(0), int)
265
266 def test_type_subclass_generic(self):
267 class MyType(type):
268 pass
269 with self.assertRaises(TypeError):
270 MyType[int]
271
272 def test_pickle(self):
273 alias = GenericAlias(list, T)
274 s = pickle.dumps(alias)
275 loaded = pickle.loads(s)
276 self.assertEqual(alias.__origin__, loaded.__origin__)
277 self.assertEqual(alias.__args__, loaded.__args__)
278 self.assertEqual(alias.__parameters__, loaded.__parameters__)
279
280 def test_union(self):
281 a = typing.Union[list[int], list[str]]
282 self.assertEqual(a.__args__, (list[int], list[str]))
283 self.assertEqual(a.__parameters__, ())
284
285 def test_union_generic(self):
Guido van Rossum48b069a2020-04-07 09:50:06 -0700286 a = typing.Union[list[T], tuple[T, ...]]
287 self.assertEqual(a.__args__, (list[T], tuple[T, ...]))
288 self.assertEqual(a.__parameters__, (T,))
289
Batuhan Taskaya2e877742020-09-16 00:58:32 +0300290 def test_dir(self):
291 dir_of_gen_alias = set(dir(list[int]))
292 self.assertTrue(dir_of_gen_alias.issuperset(dir(list)))
293 for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
294 self.assertIn(generic_alias_property, dir_of_gen_alias)
Guido van Rossum48b069a2020-04-07 09:50:06 -0700295
296if __name__ == "__main__":
297 unittest.main()