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