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