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