| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | """Tests for C-implemented GenericAlias.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | import pickle | 
					
						
							| 
									
										
										
										
											2022-10-31 21:10:18 -07:00
										 |  |  | from array import array | 
					
						
							| 
									
										
										
										
											2021-09-15 21:25:41 +03:00
										 |  |  | import copy | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | from collections import ( | 
					
						
							|  |  |  |     defaultdict, deque, OrderedDict, Counter, UserDict, UserList | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | from collections.abc import * | 
					
						
							| 
									
										
										
										
											2020-04-10 17:46:36 +03:00
										 |  |  | from concurrent.futures import Future | 
					
						
							|  |  |  | from concurrent.futures.thread import _WorkItem | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | from contextlib import AbstractContextManager, AbstractAsyncContextManager | 
					
						
							| 
									
										
										
										
											2020-04-14 16:14:15 -07:00
										 |  |  | from contextvars import ContextVar, Token | 
					
						
							| 
									
										
										
										
											2022-05-08 16:24:54 +02:00
										 |  |  | from csv import DictReader, DictWriter | 
					
						
							| 
									
										
										
										
											2020-04-14 16:14:15 -07:00
										 |  |  | from dataclasses import Field | 
					
						
							|  |  |  | from functools import partial, partialmethod, cached_property | 
					
						
							| 
									
										
										
										
											2021-12-08 13:52:57 -05:00
										 |  |  | from graphlib import TopologicalSorter | 
					
						
							| 
									
										
										
										
											2022-05-02 16:10:02 +01:00
										 |  |  | from logging import LoggerAdapter, StreamHandler | 
					
						
							| 
									
										
										
										
											2020-04-14 16:14:15 -07:00
										 |  |  | from mailbox import Mailbox, _PartialFile | 
					
						
							| 
									
										
										
										
											2020-08-07 17:56:42 +02:00
										 |  |  | try: | 
					
						
							|  |  |  |     import ctypes | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     ctypes = None | 
					
						
							| 
									
										
										
										
											2020-04-09 21:47:31 -07:00
										 |  |  | from difflib import SequenceMatcher | 
					
						
							|  |  |  | from filecmp import dircmp | 
					
						
							|  |  |  | from fileinput import FileInput | 
					
						
							| 
									
										
										
										
											2020-04-09 20:28:08 -07:00
										 |  |  | from itertools import chain | 
					
						
							| 
									
										
										
										
											2020-04-10 17:46:36 +03:00
										 |  |  | from http.cookies import Morsel | 
					
						
							| 
									
										
										
										
											2022-02-05 21:52:01 +02:00
										 |  |  | try: | 
					
						
							|  |  |  |     from multiprocessing.managers import ValueProxy | 
					
						
							|  |  |  |     from multiprocessing.pool import ApplyResult | 
					
						
							|  |  |  |     from multiprocessing.queues import SimpleQueue as MPSimpleQueue | 
					
						
							| 
									
										
										
										
											2022-12-27 07:50:55 +03:00
										 |  |  |     from multiprocessing.queues import Queue as MPQueue | 
					
						
							|  |  |  |     from multiprocessing.queues import JoinableQueue as MPJoinableQueue | 
					
						
							| 
									
										
										
										
											2022-02-05 21:52:01 +02:00
										 |  |  | except ImportError: | 
					
						
							|  |  |  |     # _multiprocessing module is optional | 
					
						
							|  |  |  |     ValueProxy = None | 
					
						
							|  |  |  |     ApplyResult = None | 
					
						
							|  |  |  |     MPSimpleQueue = None | 
					
						
							| 
									
										
										
										
											2022-12-27 07:50:55 +03:00
										 |  |  |     MPQueue = None | 
					
						
							|  |  |  |     MPJoinableQueue = None | 
					
						
							| 
									
										
										
										
											2020-04-14 06:00:16 +08:00
										 |  |  | try: | 
					
						
							|  |  |  |     from multiprocessing.shared_memory import ShareableList | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     # multiprocessing.shared_memory is not available on e.g. Android | 
					
						
							|  |  |  |     ShareableList = None | 
					
						
							| 
									
										
										
										
											2020-04-08 00:37:19 +03:00
										 |  |  | from os import DirEntry | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | from re import Pattern, Match | 
					
						
							| 
									
										
										
										
											2020-04-09 21:25:53 -07:00
										 |  |  | from types import GenericAlias, MappingProxyType, AsyncGeneratorType | 
					
						
							| 
									
										
										
										
											2020-04-10 17:46:36 +03:00
										 |  |  | from tempfile import TemporaryDirectory, SpooledTemporaryFile | 
					
						
							|  |  |  | from urllib.parse import SplitResult, ParseResult | 
					
						
							|  |  |  | from unittest.case import _AssertRaisesContext | 
					
						
							|  |  |  | from queue import Queue, SimpleQueue | 
					
						
							| 
									
										
										
										
											2020-04-13 21:54:40 -07:00
										 |  |  | from weakref import WeakSet, ReferenceType, ref | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | import typing | 
					
						
							| 
									
										
										
										
											2022-04-05 03:52:42 +01:00
										 |  |  | from typing import Unpack | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | from typing import TypeVar | 
					
						
							|  |  |  | T = TypeVar('T') | 
					
						
							| 
									
										
										
										
											2020-05-04 10:56:05 +03:00
										 |  |  | K = TypeVar('K') | 
					
						
							|  |  |  | V = TypeVar('V') | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 03:52:42 +01:00
										 |  |  | _UNPACKED_TUPLES = [ | 
					
						
							|  |  |  |     # Unpacked tuple using `*` | 
					
						
							|  |  |  |     (*tuple[int],)[0], | 
					
						
							|  |  |  |     (*tuple[T],)[0], | 
					
						
							|  |  |  |     (*tuple[int, str],)[0], | 
					
						
							|  |  |  |     (*tuple[int, ...],)[0], | 
					
						
							|  |  |  |     (*tuple[T, ...],)[0], | 
					
						
							|  |  |  |     tuple[*tuple[int, ...]], | 
					
						
							|  |  |  |     tuple[*tuple[T, ...]], | 
					
						
							|  |  |  |     tuple[str, *tuple[int, ...]], | 
					
						
							|  |  |  |     tuple[*tuple[int, ...], str], | 
					
						
							|  |  |  |     tuple[float, *tuple[int, ...], str], | 
					
						
							|  |  |  |     tuple[*tuple[*tuple[int, ...]]], | 
					
						
							|  |  |  |     # Unpacked tuple using `Unpack` | 
					
						
							|  |  |  |     Unpack[tuple[int]], | 
					
						
							|  |  |  |     Unpack[tuple[T]], | 
					
						
							|  |  |  |     Unpack[tuple[int, str]], | 
					
						
							|  |  |  |     Unpack[tuple[int, ...]], | 
					
						
							|  |  |  |     Unpack[tuple[T, ...]], | 
					
						
							|  |  |  |     tuple[Unpack[tuple[int, ...]]], | 
					
						
							|  |  |  |     tuple[Unpack[tuple[T, ...]]], | 
					
						
							|  |  |  |     tuple[str, Unpack[tuple[int, ...]]], | 
					
						
							|  |  |  |     tuple[Unpack[tuple[int, ...]], str], | 
					
						
							|  |  |  |     tuple[float, Unpack[tuple[int, ...]], str], | 
					
						
							|  |  |  |     tuple[Unpack[tuple[Unpack[tuple[int, ...]]]]], | 
					
						
							|  |  |  |     # Unpacked tuple using `*` AND `Unpack` | 
					
						
							|  |  |  |     tuple[Unpack[tuple[*tuple[int, ...]]]], | 
					
						
							|  |  |  |     tuple[*tuple[Unpack[tuple[int, ...]]]], | 
					
						
							|  |  |  | ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | class BaseTest(unittest.TestCase): | 
					
						
							|  |  |  |     """Test basics.""" | 
					
						
							| 
									
										
										
										
											2020-11-16 11:27:23 +08:00
										 |  |  |     generic_types = [type, tuple, list, dict, set, frozenset, enumerate, | 
					
						
							|  |  |  |                      defaultdict, deque, | 
					
						
							|  |  |  |                      SequenceMatcher, | 
					
						
							|  |  |  |                      dircmp, | 
					
						
							|  |  |  |                      FileInput, | 
					
						
							|  |  |  |                      OrderedDict, Counter, UserDict, UserList, | 
					
						
							|  |  |  |                      Pattern, Match, | 
					
						
							|  |  |  |                      partial, partialmethod, cached_property, | 
					
						
							| 
									
										
										
										
											2021-12-08 13:52:57 -05:00
										 |  |  |                      TopologicalSorter, | 
					
						
							| 
									
										
										
										
											2020-11-16 11:27:23 +08:00
										 |  |  |                      AbstractContextManager, AbstractAsyncContextManager, | 
					
						
							|  |  |  |                      Awaitable, Coroutine, | 
					
						
							|  |  |  |                      AsyncIterable, AsyncIterator, | 
					
						
							|  |  |  |                      AsyncGenerator, Generator, | 
					
						
							|  |  |  |                      Iterable, Iterator, | 
					
						
							|  |  |  |                      Reversible, | 
					
						
							|  |  |  |                      Container, Collection, | 
					
						
							|  |  |  |                      Mailbox, _PartialFile, | 
					
						
							|  |  |  |                      ContextVar, Token, | 
					
						
							|  |  |  |                      Field, | 
					
						
							|  |  |  |                      Set, MutableSet, | 
					
						
							|  |  |  |                      Mapping, MutableMapping, MappingView, | 
					
						
							|  |  |  |                      KeysView, ItemsView, ValuesView, | 
					
						
							|  |  |  |                      Sequence, MutableSequence, | 
					
						
							|  |  |  |                      MappingProxyType, AsyncGeneratorType, | 
					
						
							|  |  |  |                      DirEntry, | 
					
						
							|  |  |  |                      chain, | 
					
						
							| 
									
										
										
										
											2022-05-02 16:10:02 +01:00
										 |  |  |                      LoggerAdapter, StreamHandler, | 
					
						
							| 
									
										
										
										
											2020-11-16 11:27:23 +08:00
										 |  |  |                      TemporaryDirectory, SpooledTemporaryFile, | 
					
						
							|  |  |  |                      Queue, SimpleQueue, | 
					
						
							|  |  |  |                      _AssertRaisesContext, | 
					
						
							|  |  |  |                      SplitResult, ParseResult, | 
					
						
							|  |  |  |                      WeakSet, ReferenceType, ref, | 
					
						
							| 
									
										
										
										
											2022-02-05 21:52:01 +02:00
										 |  |  |                      ShareableList, | 
					
						
							| 
									
										
										
										
											2020-11-16 11:27:23 +08:00
										 |  |  |                      Future, _WorkItem, | 
					
						
							| 
									
										
										
										
											2022-05-08 16:24:54 +02:00
										 |  |  |                      Morsel, | 
					
						
							| 
									
										
										
										
											2022-10-31 21:10:18 -07:00
										 |  |  |                      DictReader, DictWriter, | 
					
						
							|  |  |  |                      array] | 
					
						
							| 
									
										
										
										
											2020-11-16 11:27:23 +08:00
										 |  |  |     if ctypes is not None: | 
					
						
							|  |  |  |         generic_types.extend((ctypes.Array, ctypes.LibraryLoader)) | 
					
						
							| 
									
										
										
										
											2022-02-05 21:52:01 +02:00
										 |  |  |     if ValueProxy is not None: | 
					
						
							| 
									
										
										
										
											2022-12-27 07:50:55 +03:00
										 |  |  |         generic_types.extend((ValueProxy, ApplyResult, | 
					
						
							|  |  |  |                               MPSimpleQueue, MPQueue, MPJoinableQueue)) | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_subscriptable(self): | 
					
						
							| 
									
										
										
										
											2020-11-16 11:27:23 +08:00
										 |  |  |         for t in self.generic_types: | 
					
						
							| 
									
										
										
										
											2020-04-14 06:00:16 +08:00
										 |  |  |             if t is None: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |             tname = t.__name__ | 
					
						
							|  |  |  |             with self.subTest(f"Testing {tname}"): | 
					
						
							|  |  |  |                 alias = t[int] | 
					
						
							|  |  |  |                 self.assertIs(alias.__origin__, t) | 
					
						
							|  |  |  |                 self.assertEqual(alias.__args__, (int,)) | 
					
						
							|  |  |  |                 self.assertEqual(alias.__parameters__, ()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_unsubscriptable(self): | 
					
						
							|  |  |  |         for t in int, str, float, Sized, Hashable: | 
					
						
							|  |  |  |             tname = t.__name__ | 
					
						
							|  |  |  |             with self.subTest(f"Testing {tname}"): | 
					
						
							| 
									
										
										
										
											2022-03-05 15:59:24 +02:00
										 |  |  |                 with self.assertRaisesRegex(TypeError, tname): | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |                     t[int] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_instantiate(self): | 
					
						
							|  |  |  |         for t in tuple, list, dict, set, frozenset, defaultdict, deque: | 
					
						
							|  |  |  |             tname = t.__name__ | 
					
						
							|  |  |  |             with self.subTest(f"Testing {tname}"): | 
					
						
							|  |  |  |                 alias = t[int] | 
					
						
							|  |  |  |                 self.assertEqual(alias(), t()) | 
					
						
							|  |  |  |                 if t is dict: | 
					
						
							|  |  |  |                     self.assertEqual(alias(iter([('a', 1), ('b', 2)])), dict(a=1, b=2)) | 
					
						
							|  |  |  |                     self.assertEqual(alias(a=1, b=2), dict(a=1, b=2)) | 
					
						
							|  |  |  |                 elif t is defaultdict: | 
					
						
							|  |  |  |                     def default(): | 
					
						
							|  |  |  |                         return 'value' | 
					
						
							|  |  |  |                     a = alias(default) | 
					
						
							|  |  |  |                     d = defaultdict(default) | 
					
						
							|  |  |  |                     self.assertEqual(a['test'], d['test']) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     self.assertEqual(alias(iter((1, 2, 3))), t((1, 2, 3))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_unbound_methods(self): | 
					
						
							|  |  |  |         t = list[int] | 
					
						
							|  |  |  |         a = t() | 
					
						
							|  |  |  |         t.append(a, 'foo') | 
					
						
							|  |  |  |         self.assertEqual(a, ['foo']) | 
					
						
							|  |  |  |         x = t.__getitem__(a, 0) | 
					
						
							|  |  |  |         self.assertEqual(x, 'foo') | 
					
						
							|  |  |  |         self.assertEqual(t.__len__(a), 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_subclassing(self): | 
					
						
							|  |  |  |         class C(list[int]): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         self.assertEqual(C.__bases__, (list,)) | 
					
						
							|  |  |  |         self.assertEqual(C.__class__, type) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_class_methods(self): | 
					
						
							|  |  |  |         t = dict[int, None] | 
					
						
							|  |  |  |         self.assertEqual(dict.fromkeys(range(2)), {0: None, 1: None})  # This works | 
					
						
							|  |  |  |         self.assertEqual(t.fromkeys(range(2)), {0: None, 1: None})  # Should be equivalent | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_no_chaining(self): | 
					
						
							|  |  |  |         t = list[int] | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             t[int] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_generic_subclass(self): | 
					
						
							|  |  |  |         class MyList(list): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         t = MyList[int] | 
					
						
							|  |  |  |         self.assertIs(t.__origin__, MyList) | 
					
						
							|  |  |  |         self.assertEqual(t.__args__, (int,)) | 
					
						
							|  |  |  |         self.assertEqual(t.__parameters__, ()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_repr(self): | 
					
						
							|  |  |  |         class MyList(list): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         self.assertEqual(repr(list[str]), 'list[str]') | 
					
						
							|  |  |  |         self.assertEqual(repr(list[()]), 'list[()]') | 
					
						
							|  |  |  |         self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]') | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |         x1 = tuple[*tuple[int]] | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         self.assertEqual(repr(x1), 'tuple[*tuple[int]]') | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |         x2 = tuple[*tuple[int, str]] | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         self.assertEqual(repr(x2), 'tuple[*tuple[int, str]]') | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |         x3 = tuple[*tuple[int, ...]] | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         self.assertEqual(repr(x3), 'tuple[*tuple[int, ...]]') | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |         self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]')) | 
					
						
							|  |  |  |         self.assertEqual(repr(list[str]()), '[]')  # instances should keep their normal repr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_exposed_type(self): | 
					
						
							|  |  |  |         import types | 
					
						
							|  |  |  |         a = types.GenericAlias(list, int) | 
					
						
							|  |  |  |         self.assertEqual(str(a), 'list[int]') | 
					
						
							|  |  |  |         self.assertIs(a.__origin__, list) | 
					
						
							|  |  |  |         self.assertEqual(a.__args__, (int,)) | 
					
						
							|  |  |  |         self.assertEqual(a.__parameters__, ()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_parameters(self): | 
					
						
							| 
									
										
										
										
											2020-05-04 10:56:05 +03:00
										 |  |  |         from typing import List, Dict, Callable | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |         D0 = dict[str, int] | 
					
						
							|  |  |  |         self.assertEqual(D0.__args__, (str, int)) | 
					
						
							|  |  |  |         self.assertEqual(D0.__parameters__, ()) | 
					
						
							|  |  |  |         D1a = dict[str, V] | 
					
						
							|  |  |  |         self.assertEqual(D1a.__args__, (str, V)) | 
					
						
							|  |  |  |         self.assertEqual(D1a.__parameters__, (V,)) | 
					
						
							|  |  |  |         D1b = dict[K, int] | 
					
						
							|  |  |  |         self.assertEqual(D1b.__args__, (K, int)) | 
					
						
							|  |  |  |         self.assertEqual(D1b.__parameters__, (K,)) | 
					
						
							|  |  |  |         D2a = dict[K, V] | 
					
						
							|  |  |  |         self.assertEqual(D2a.__args__, (K, V)) | 
					
						
							|  |  |  |         self.assertEqual(D2a.__parameters__, (K, V)) | 
					
						
							|  |  |  |         D2b = dict[T, T] | 
					
						
							|  |  |  |         self.assertEqual(D2b.__args__, (T, T)) | 
					
						
							|  |  |  |         self.assertEqual(D2b.__parameters__, (T,)) | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |         L0 = list[str] | 
					
						
							|  |  |  |         self.assertEqual(L0.__args__, (str,)) | 
					
						
							|  |  |  |         self.assertEqual(L0.__parameters__, ()) | 
					
						
							|  |  |  |         L1 = list[T] | 
					
						
							|  |  |  |         self.assertEqual(L1.__args__, (T,)) | 
					
						
							|  |  |  |         self.assertEqual(L1.__parameters__, (T,)) | 
					
						
							| 
									
										
										
										
											2020-05-04 10:56:05 +03:00
										 |  |  |         L2 = list[list[T]] | 
					
						
							|  |  |  |         self.assertEqual(L2.__args__, (list[T],)) | 
					
						
							|  |  |  |         self.assertEqual(L2.__parameters__, (T,)) | 
					
						
							|  |  |  |         L3 = list[List[T]] | 
					
						
							|  |  |  |         self.assertEqual(L3.__args__, (List[T],)) | 
					
						
							|  |  |  |         self.assertEqual(L3.__parameters__, (T,)) | 
					
						
							|  |  |  |         L4a = list[Dict[K, V]] | 
					
						
							|  |  |  |         self.assertEqual(L4a.__args__, (Dict[K, V],)) | 
					
						
							|  |  |  |         self.assertEqual(L4a.__parameters__, (K, V)) | 
					
						
							|  |  |  |         L4b = list[Dict[T, int]] | 
					
						
							|  |  |  |         self.assertEqual(L4b.__args__, (Dict[T, int],)) | 
					
						
							|  |  |  |         self.assertEqual(L4b.__parameters__, (T,)) | 
					
						
							|  |  |  |         L5 = list[Callable[[K, V], K]] | 
					
						
							|  |  |  |         self.assertEqual(L5.__args__, (Callable[[K, V], K],)) | 
					
						
							|  |  |  |         self.assertEqual(L5.__parameters__, (K, V)) | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |         T1 = tuple[*tuple[int]] | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             T1.__args__, | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |             (*tuple[int],), | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         ) | 
					
						
							|  |  |  |         self.assertEqual(T1.__parameters__, ()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |         T2 = tuple[*tuple[T]] | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             T2.__args__, | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |             (*tuple[T],), | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         ) | 
					
						
							|  |  |  |         self.assertEqual(T2.__parameters__, (T,)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |         T4 = tuple[*tuple[int, str]] | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             T4.__args__, | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |             (*tuple[int, str],), | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         ) | 
					
						
							|  |  |  |         self.assertEqual(T4.__parameters__, ()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |     def test_parameter_chaining(self): | 
					
						
							| 
									
										
										
										
											2020-05-04 10:56:05 +03:00
										 |  |  |         from typing import List, Dict, Union, Callable | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |         self.assertEqual(list[T][int], list[int]) | 
					
						
							|  |  |  |         self.assertEqual(dict[str, T][int], dict[str, int]) | 
					
						
							|  |  |  |         self.assertEqual(dict[T, int][str], dict[str, int]) | 
					
						
							| 
									
										
										
										
											2020-05-04 10:56:05 +03:00
										 |  |  |         self.assertEqual(dict[K, V][str, int], dict[str, int]) | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |         self.assertEqual(dict[T, T][int], dict[int, int]) | 
					
						
							| 
									
										
										
										
											2020-05-04 10:56:05 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(list[list[T]][int], list[list[int]]) | 
					
						
							|  |  |  |         self.assertEqual(list[dict[T, int]][str], list[dict[str, int]]) | 
					
						
							|  |  |  |         self.assertEqual(list[dict[str, T]][int], list[dict[str, int]]) | 
					
						
							|  |  |  |         self.assertEqual(list[dict[K, V]][str, int], list[dict[str, int]]) | 
					
						
							|  |  |  |         self.assertEqual(dict[T, list[int]][str], dict[str, list[int]]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(list[List[T]][int], list[List[int]]) | 
					
						
							|  |  |  |         self.assertEqual(list[Dict[K, V]][str, int], list[Dict[str, int]]) | 
					
						
							|  |  |  |         self.assertEqual(list[Union[K, V]][str, int], list[Union[str, int]]) | 
					
						
							|  |  |  |         self.assertEqual(list[Callable[[K, V], K]][str, int], | 
					
						
							|  |  |  |                          list[Callable[[str, int], str]]) | 
					
						
							|  |  |  |         self.assertEqual(dict[T, List[int]][str], dict[str, List[int]]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             list[int][int] | 
					
						
							|  |  |  |             dict[T, int][str, int] | 
					
						
							|  |  |  |             dict[str, T][str, int] | 
					
						
							|  |  |  |             dict[T, T][str, int] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_equality(self): | 
					
						
							|  |  |  |         self.assertEqual(list[int], list[int]) | 
					
						
							|  |  |  |         self.assertEqual(dict[str, int], dict[str, int]) | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |         self.assertEqual((*tuple[int],)[0], (*tuple[int],)[0]) | 
					
						
							| 
									
										
										
										
											2022-10-25 15:44:30 +01:00
										 |  |  |         self.assertEqual(tuple[*tuple[int]], tuple[*tuple[int]]) | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |         self.assertNotEqual(dict[str, int], dict[str, str]) | 
					
						
							|  |  |  |         self.assertNotEqual(list, list[int]) | 
					
						
							|  |  |  |         self.assertNotEqual(list[int], list) | 
					
						
							| 
									
										
										
										
											2022-05-05 20:16:06 +03:00
										 |  |  |         self.assertNotEqual(list[int], tuple[int]) | 
					
						
							|  |  |  |         self.assertNotEqual((*tuple[int],)[0], tuple[int]) | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_isinstance(self): | 
					
						
							|  |  |  |         self.assertTrue(isinstance([], list)) | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             isinstance([], list[str]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_issubclass(self): | 
					
						
							|  |  |  |         class L(list): ... | 
					
						
							|  |  |  |         self.assertTrue(issubclass(L, list)) | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             issubclass(L, list[str]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_type_generic(self): | 
					
						
							|  |  |  |         t = type[int] | 
					
						
							|  |  |  |         Test = t('Test', (), {}) | 
					
						
							|  |  |  |         self.assertTrue(isinstance(Test, type)) | 
					
						
							|  |  |  |         test = Test() | 
					
						
							|  |  |  |         self.assertEqual(t(test), Test) | 
					
						
							|  |  |  |         self.assertEqual(t(0), int) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_type_subclass_generic(self): | 
					
						
							|  |  |  |         class MyType(type): | 
					
						
							|  |  |  |             pass | 
					
						
							| 
									
										
										
										
											2022-03-05 15:59:24 +02:00
										 |  |  |         with self.assertRaisesRegex(TypeError, 'MyType'): | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |             MyType[int] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_pickle(self): | 
					
						
							| 
									
										
										
										
											2022-04-05 03:52:42 +01:00
										 |  |  |         aliases = [GenericAlias(list, T)] + _UNPACKED_TUPLES | 
					
						
							|  |  |  |         for alias in aliases: | 
					
						
							|  |  |  |             for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
					
						
							|  |  |  |                 with self.subTest(alias=alias, proto=proto): | 
					
						
							|  |  |  |                     s = pickle.dumps(alias, proto) | 
					
						
							|  |  |  |                     loaded = pickle.loads(s) | 
					
						
							|  |  |  |                     self.assertEqual(loaded.__origin__, alias.__origin__) | 
					
						
							|  |  |  |                     self.assertEqual(loaded.__args__, alias.__args__) | 
					
						
							|  |  |  |                     self.assertEqual(loaded.__parameters__, alias.__parameters__) | 
					
						
							| 
									
										
										
										
											2022-05-05 20:16:06 +03:00
										 |  |  |                     self.assertEqual(type(loaded), type(alias)) | 
					
						
							| 
									
										
										
										
											2021-09-15 21:25:41 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_copy(self): | 
					
						
							|  |  |  |         class X(list): | 
					
						
							|  |  |  |             def __copy__(self): | 
					
						
							|  |  |  |                 return self | 
					
						
							|  |  |  |             def __deepcopy__(self, memo): | 
					
						
							|  |  |  |                 return self | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 03:52:42 +01:00
										 |  |  |         aliases = [ | 
					
						
							|  |  |  |             GenericAlias(list, T), | 
					
						
							|  |  |  |             GenericAlias(deque, T), | 
					
						
							|  |  |  |             GenericAlias(X, T) | 
					
						
							|  |  |  |         ] + _UNPACKED_TUPLES | 
					
						
							|  |  |  |         for alias in aliases: | 
					
						
							|  |  |  |             with self.subTest(alias=alias): | 
					
						
							|  |  |  |                 copied = copy.copy(alias) | 
					
						
							|  |  |  |                 self.assertEqual(copied.__origin__, alias.__origin__) | 
					
						
							|  |  |  |                 self.assertEqual(copied.__args__, alias.__args__) | 
					
						
							|  |  |  |                 self.assertEqual(copied.__parameters__, alias.__parameters__) | 
					
						
							|  |  |  |                 copied = copy.deepcopy(alias) | 
					
						
							|  |  |  |                 self.assertEqual(copied.__origin__, alias.__origin__) | 
					
						
							|  |  |  |                 self.assertEqual(copied.__args__, alias.__args__) | 
					
						
							|  |  |  |                 self.assertEqual(copied.__parameters__, alias.__parameters__) | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 13:21:59 -06:00
										 |  |  |     def test_unpack(self): | 
					
						
							|  |  |  |         alias = tuple[str, ...] | 
					
						
							|  |  |  |         self.assertIs(alias.__unpacked__, False) | 
					
						
							|  |  |  |         unpacked = (*alias,)[0] | 
					
						
							|  |  |  |         self.assertIs(unpacked.__unpacked__, True) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  |     def test_union(self): | 
					
						
							|  |  |  |         a = typing.Union[list[int], list[str]] | 
					
						
							|  |  |  |         self.assertEqual(a.__args__, (list[int], list[str])) | 
					
						
							|  |  |  |         self.assertEqual(a.__parameters__, ()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_union_generic(self): | 
					
						
							|  |  |  |         a = typing.Union[list[T], tuple[T, ...]] | 
					
						
							|  |  |  |         self.assertEqual(a.__args__, (list[T], tuple[T, ...])) | 
					
						
							|  |  |  |         self.assertEqual(a.__parameters__, (T,)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-16 00:58:32 +03:00
										 |  |  |     def test_dir(self): | 
					
						
							|  |  |  |         dir_of_gen_alias = set(dir(list[int])) | 
					
						
							|  |  |  |         self.assertTrue(dir_of_gen_alias.issuperset(dir(list))) | 
					
						
							|  |  |  |         for generic_alias_property in ("__origin__", "__args__", "__parameters__"): | 
					
						
							|  |  |  |             self.assertIn(generic_alias_property, dir_of_gen_alias) | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-16 11:27:23 +08:00
										 |  |  |     def test_weakref(self): | 
					
						
							|  |  |  |         for t in self.generic_types: | 
					
						
							|  |  |  |             if t is None: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             tname = t.__name__ | 
					
						
							|  |  |  |             with self.subTest(f"Testing {tname}"): | 
					
						
							|  |  |  |                 alias = t[int] | 
					
						
							|  |  |  |                 self.assertEqual(ref(alias)(), alias) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 23:02:14 +07:00
										 |  |  |     def test_no_kwargs(self): | 
					
						
							|  |  |  |         # bpo-42576 | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             GenericAlias(bad=float) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 02:38:24 +08:00
										 |  |  |     def test_subclassing_types_genericalias(self): | 
					
						
							|  |  |  |         class SubClass(GenericAlias): ... | 
					
						
							|  |  |  |         alias = SubClass(list, int) | 
					
						
							|  |  |  |         class Bad(GenericAlias): | 
					
						
							|  |  |  |             def __new__(cls, *args, **kwargs): | 
					
						
							|  |  |  |                 super().__new__(cls, *args, **kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(alias, list[int]) | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             Bad(list, int, bad=int) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-12 12:20:12 +00:00
										 |  |  |     def test_iter_creates_starred_tuple(self): | 
					
						
							|  |  |  |         t = tuple[int, str] | 
					
						
							|  |  |  |         iter_t = iter(t) | 
					
						
							|  |  |  |         x = next(iter_t) | 
					
						
							|  |  |  |         self.assertEqual(repr(x), '*tuple[int, str]') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_calling_next_twice_raises_stopiteration(self): | 
					
						
							|  |  |  |         t = tuple[int, str] | 
					
						
							|  |  |  |         iter_t = iter(t) | 
					
						
							|  |  |  |         next(iter_t) | 
					
						
							|  |  |  |         with self.assertRaises(StopIteration): | 
					
						
							|  |  |  |             next(iter_t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_del_iter(self): | 
					
						
							|  |  |  |         t = tuple[int, str] | 
					
						
							|  |  |  |         iter_x = iter(t) | 
					
						
							|  |  |  |         del iter_x | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-28 23:38:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-08 14:21:28 +01:00
										 |  |  | class TypeIterationTests(unittest.TestCase): | 
					
						
							|  |  |  |     _UNITERABLE_TYPES = (list, tuple) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_cannot_iterate(self): | 
					
						
							|  |  |  |         for test_type in self._UNITERABLE_TYPES: | 
					
						
							|  |  |  |             with self.subTest(type=test_type): | 
					
						
							|  |  |  |                 expected_error_regex = "object is not iterable" | 
					
						
							|  |  |  |                 with self.assertRaisesRegex(TypeError, expected_error_regex): | 
					
						
							|  |  |  |                     iter(test_type) | 
					
						
							|  |  |  |                 with self.assertRaisesRegex(TypeError, expected_error_regex): | 
					
						
							|  |  |  |                     list(test_type) | 
					
						
							|  |  |  |                 with self.assertRaisesRegex(TypeError, expected_error_regex): | 
					
						
							|  |  |  |                     for _ in test_type: | 
					
						
							|  |  |  |                         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_is_not_instance_of_iterable(self): | 
					
						
							|  |  |  |         for type_to_test in self._UNITERABLE_TYPES: | 
					
						
							|  |  |  |             self.assertNotIsInstance(type_to_test, Iterable) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 09:50:06 -07:00
										 |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     unittest.main() |