blob: 686df17d6a961f1ccf9e89ebd80ff2b2ddba42db [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 Smithcecf0492020-04-13 21:53:04 -070012from functools import partial, partialmethod, _lru_cache_wrapper, cached_property
Batuhan Taşkaya03615562020-04-10 17:46:36 +030013from ctypes import Array, LibraryLoader
Ethan Smithe3ec44d2020-04-09 21:47:31 -070014from difflib import SequenceMatcher
15from filecmp import dircmp
16from fileinput import FileInput
Ethan Smith7c4185d2020-04-09 21:25:53 -070017from mmap import mmap
Batuhan Taşkaya2fa67df2020-04-10 07:04:54 +030018from ipaddress import IPv4Network, IPv4Interface, IPv6Network, IPv6Interface
Ethan Smitha8403d02020-04-09 20:28:08 -070019from itertools import chain
Batuhan Taşkaya03615562020-04-10 17:46:36 +030020from http.cookies import Morsel
21from multiprocessing.managers import ValueProxy
22from multiprocessing.pool import ApplyResult
Chih-Hsuan Yen25a68332020-04-14 06:00:16 +080023try:
24 from multiprocessing.shared_memory import ShareableList
25except ImportError:
26 # multiprocessing.shared_memory is not available on e.g. Android
27 ShareableList = None
Batuhan Taşkaya03615562020-04-10 17:46:36 +030028from multiprocessing.queues import SimpleQueue
Batuhan Taşkayaf9dd51e2020-04-08 00:37:19 +030029from os import DirEntry
Guido van Rossum48b069a2020-04-07 09:50:06 -070030from re import Pattern, Match
Ethan Smith7c4185d2020-04-09 21:25:53 -070031from types import GenericAlias, MappingProxyType, AsyncGeneratorType
Batuhan Taşkaya03615562020-04-10 17:46:36 +030032from tempfile import TemporaryDirectory, SpooledTemporaryFile
33from urllib.parse import SplitResult, ParseResult
34from unittest.case import _AssertRaisesContext
35from queue import Queue, SimpleQueue
Ethan Smith8ef87502020-04-13 21:54:40 -070036from weakref import WeakSet, ReferenceType, ref
Guido van Rossum48b069a2020-04-07 09:50:06 -070037import typing
38
39from typing import TypeVar
40T = TypeVar('T')
41
42class BaseTest(unittest.TestCase):
43 """Test basics."""
44
45 def test_subscriptable(self):
Ethan Smith7c4185d2020-04-09 21:25:53 -070046 for t in (type, tuple, list, dict, set, frozenset, enumerate,
47 mmap,
Guido van Rossum48b069a2020-04-07 09:50:06 -070048 defaultdict, deque,
Ethan Smithe3ec44d2020-04-09 21:47:31 -070049 SequenceMatcher,
50 dircmp,
51 FileInput,
Guido van Rossum48b069a2020-04-07 09:50:06 -070052 OrderedDict, Counter, UserDict, UserList,
53 Pattern, Match,
Ethan Smithcecf0492020-04-13 21:53:04 -070054 partial, partialmethod, cached_property,
Guido van Rossum48b069a2020-04-07 09:50:06 -070055 AbstractContextManager, AbstractAsyncContextManager,
56 Awaitable, Coroutine,
57 AsyncIterable, AsyncIterator,
58 AsyncGenerator, Generator,
59 Iterable, Iterator,
60 Reversible,
61 Container, Collection,
62 Callable,
63 Set, MutableSet,
64 Mapping, MutableMapping, MappingView,
65 KeysView, ItemsView, ValuesView,
66 Sequence, MutableSequence,
Ethan Smith7c4185d2020-04-09 21:25:53 -070067 MappingProxyType, AsyncGeneratorType,
Batuhan Taşkaya2fa67df2020-04-10 07:04:54 +030068 DirEntry,
69 IPv4Network, IPv4Interface, IPv6Network, IPv6Interface,
Ethan Smitha8403d02020-04-09 20:28:08 -070070 chain,
Batuhan Taşkaya03615562020-04-10 17:46:36 +030071 TemporaryDirectory, SpooledTemporaryFile,
72 Queue, SimpleQueue,
73 _AssertRaisesContext,
74 Array, LibraryLoader,
75 SplitResult, ParseResult,
76 ValueProxy, ApplyResult,
Ethan Smith8ef87502020-04-13 21:54:40 -070077 WeakSet, ReferenceType, ref,
Batuhan Taşkaya03615562020-04-10 17:46:36 +030078 ShareableList, SimpleQueue,
79 Future, _WorkItem,
80 Morsel,
Guido van Rossum48b069a2020-04-07 09:50:06 -070081 ):
Chih-Hsuan Yen25a68332020-04-14 06:00:16 +080082 if t is None:
83 continue
Guido van Rossum48b069a2020-04-07 09:50:06 -070084 tname = t.__name__
85 with self.subTest(f"Testing {tname}"):
86 alias = t[int]
87 self.assertIs(alias.__origin__, t)
88 self.assertEqual(alias.__args__, (int,))
89 self.assertEqual(alias.__parameters__, ())
90
91 def test_unsubscriptable(self):
92 for t in int, str, float, Sized, Hashable:
93 tname = t.__name__
94 with self.subTest(f"Testing {tname}"):
95 with self.assertRaises(TypeError):
96 t[int]
97
98 def test_instantiate(self):
99 for t in tuple, list, dict, set, frozenset, defaultdict, deque:
100 tname = t.__name__
101 with self.subTest(f"Testing {tname}"):
102 alias = t[int]
103 self.assertEqual(alias(), t())
104 if t is dict:
105 self.assertEqual(alias(iter([('a', 1), ('b', 2)])), dict(a=1, b=2))
106 self.assertEqual(alias(a=1, b=2), dict(a=1, b=2))
107 elif t is defaultdict:
108 def default():
109 return 'value'
110 a = alias(default)
111 d = defaultdict(default)
112 self.assertEqual(a['test'], d['test'])
113 else:
114 self.assertEqual(alias(iter((1, 2, 3))), t((1, 2, 3)))
115
116 def test_unbound_methods(self):
117 t = list[int]
118 a = t()
119 t.append(a, 'foo')
120 self.assertEqual(a, ['foo'])
121 x = t.__getitem__(a, 0)
122 self.assertEqual(x, 'foo')
123 self.assertEqual(t.__len__(a), 1)
124
125 def test_subclassing(self):
126 class C(list[int]):
127 pass
128 self.assertEqual(C.__bases__, (list,))
129 self.assertEqual(C.__class__, type)
130
131 def test_class_methods(self):
132 t = dict[int, None]
133 self.assertEqual(dict.fromkeys(range(2)), {0: None, 1: None}) # This works
134 self.assertEqual(t.fromkeys(range(2)), {0: None, 1: None}) # Should be equivalent
135
136 def test_no_chaining(self):
137 t = list[int]
138 with self.assertRaises(TypeError):
139 t[int]
140
141 def test_generic_subclass(self):
142 class MyList(list):
143 pass
144 t = MyList[int]
145 self.assertIs(t.__origin__, MyList)
146 self.assertEqual(t.__args__, (int,))
147 self.assertEqual(t.__parameters__, ())
148
149 def test_repr(self):
150 class MyList(list):
151 pass
152 self.assertEqual(repr(list[str]), 'list[str]')
153 self.assertEqual(repr(list[()]), 'list[()]')
154 self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]')
155 self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]'))
156 self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr
157
158 def test_exposed_type(self):
159 import types
160 a = types.GenericAlias(list, int)
161 self.assertEqual(str(a), 'list[int]')
162 self.assertIs(a.__origin__, list)
163 self.assertEqual(a.__args__, (int,))
164 self.assertEqual(a.__parameters__, ())
165
166 def test_parameters(self):
167 from typing import TypeVar
168 T = TypeVar('T')
169 K = TypeVar('K')
170 V = TypeVar('V')
171 D0 = dict[str, int]
172 self.assertEqual(D0.__args__, (str, int))
173 self.assertEqual(D0.__parameters__, ())
174 D1a = dict[str, V]
175 self.assertEqual(D1a.__args__, (str, V))
176 self.assertEqual(D1a.__parameters__, (V,))
177 D1b = dict[K, int]
178 self.assertEqual(D1b.__args__, (K, int))
179 self.assertEqual(D1b.__parameters__, (K,))
180 D2a = dict[K, V]
181 self.assertEqual(D2a.__args__, (K, V))
182 self.assertEqual(D2a.__parameters__, (K, V))
183 D2b = dict[T, T]
184 self.assertEqual(D2b.__args__, (T, T))
185 self.assertEqual(D2b.__parameters__, (T,))
186 L0 = list[str]
187 self.assertEqual(L0.__args__, (str,))
188 self.assertEqual(L0.__parameters__, ())
189 L1 = list[T]
190 self.assertEqual(L1.__args__, (T,))
191 self.assertEqual(L1.__parameters__, (T,))
192
193 def test_parameter_chaining(self):
194 from typing import TypeVar
195 T = TypeVar('T')
196 self.assertEqual(list[T][int], list[int])
197 self.assertEqual(dict[str, T][int], dict[str, int])
198 self.assertEqual(dict[T, int][str], dict[str, int])
199 self.assertEqual(dict[T, T][int], dict[int, int])
200 with self.assertRaises(TypeError):
201 list[int][int]
202 dict[T, int][str, int]
203 dict[str, T][str, int]
204 dict[T, T][str, int]
205
206 def test_equality(self):
207 self.assertEqual(list[int], list[int])
208 self.assertEqual(dict[str, int], dict[str, int])
209 self.assertNotEqual(dict[str, int], dict[str, str])
210 self.assertNotEqual(list, list[int])
211 self.assertNotEqual(list[int], list)
212
213 def test_isinstance(self):
214 self.assertTrue(isinstance([], list))
215 with self.assertRaises(TypeError):
216 isinstance([], list[str])
217
218 def test_issubclass(self):
219 class L(list): ...
220 self.assertTrue(issubclass(L, list))
221 with self.assertRaises(TypeError):
222 issubclass(L, list[str])
223
224 def test_type_generic(self):
225 t = type[int]
226 Test = t('Test', (), {})
227 self.assertTrue(isinstance(Test, type))
228 test = Test()
229 self.assertEqual(t(test), Test)
230 self.assertEqual(t(0), int)
231
232 def test_type_subclass_generic(self):
233 class MyType(type):
234 pass
235 with self.assertRaises(TypeError):
236 MyType[int]
237
238 def test_pickle(self):
239 alias = GenericAlias(list, T)
240 s = pickle.dumps(alias)
241 loaded = pickle.loads(s)
242 self.assertEqual(alias.__origin__, loaded.__origin__)
243 self.assertEqual(alias.__args__, loaded.__args__)
244 self.assertEqual(alias.__parameters__, loaded.__parameters__)
245
246 def test_union(self):
247 a = typing.Union[list[int], list[str]]
248 self.assertEqual(a.__args__, (list[int], list[str]))
249 self.assertEqual(a.__parameters__, ())
250
251 def test_union_generic(self):
252 T = typing.TypeVar('T')
253 a = typing.Union[list[T], tuple[T, ...]]
254 self.assertEqual(a.__args__, (list[T], tuple[T, ...]))
255 self.assertEqual(a.__parameters__, (T,))
256
257
258if __name__ == "__main__":
259 unittest.main()