(root)/
Python-3.11.7/
Lib/
test/
test_genericalias.py
       1  """Tests for C-implemented GenericAlias."""
       2  
       3  import unittest
       4  import pickle
       5  import copy
       6  from collections import (
       7      defaultdict, deque, OrderedDict, Counter, UserDict, UserList
       8  )
       9  from collections.abc import *
      10  from concurrent.futures import Future
      11  from concurrent.futures.thread import _WorkItem
      12  from contextlib import AbstractContextManager, AbstractAsyncContextManager
      13  from contextvars import ContextVar, Token
      14  from dataclasses import Field
      15  from functools import partial, partialmethod, cached_property
      16  from graphlib import TopologicalSorter
      17  from logging import LoggerAdapter, StreamHandler
      18  from mailbox import Mailbox, _PartialFile
      19  try:
      20      import ctypes
      21  except ImportError:
      22      ctypes = None
      23  from difflib import SequenceMatcher
      24  from filecmp import dircmp
      25  from fileinput import FileInput
      26  from itertools import chain
      27  from http.cookies import Morsel
      28  try:
      29      from multiprocessing.managers import ValueProxy
      30      from multiprocessing.pool import ApplyResult
      31      from multiprocessing.queues import SimpleQueue as MPSimpleQueue
      32  except ImportError:
      33      # _multiprocessing module is optional
      34      ValueProxy = None
      35      ApplyResult = None
      36      MPSimpleQueue = None
      37  try:
      38      from multiprocessing.shared_memory import ShareableList
      39  except ImportError:
      40      # multiprocessing.shared_memory is not available on e.g. Android
      41      ShareableList = None
      42  from os import DirEntry
      43  from re import Pattern, Match
      44  from types import GenericAlias, MappingProxyType, AsyncGeneratorType
      45  from tempfile import TemporaryDirectory, SpooledTemporaryFile
      46  from urllib.parse import SplitResult, ParseResult
      47  from unittest.case import _AssertRaisesContext
      48  from queue import Queue, SimpleQueue
      49  from weakref import WeakSet, ReferenceType, ref
      50  import typing
      51  from typing import Unpack
      52  
      53  from typing import TypeVar
      54  T = TypeVar('T')
      55  K = TypeVar('K')
      56  V = TypeVar('V')
      57  
      58  _UNPACKED_TUPLES = [
      59      # Unpacked tuple using `*`
      60      (*tuple[int],)[0],
      61      (*tuple[T],)[0],
      62      (*tuple[int, str],)[0],
      63      (*tuple[int, ...],)[0],
      64      (*tuple[T, ...],)[0],
      65      tuple[*tuple[int, ...]],
      66      tuple[*tuple[T, ...]],
      67      tuple[str, *tuple[int, ...]],
      68      tuple[*tuple[int, ...], str],
      69      tuple[float, *tuple[int, ...], str],
      70      tuple[*tuple[*tuple[int, ...]]],
      71      # Unpacked tuple using `Unpack`
      72      Unpack[tuple[int]],
      73      Unpack[tuple[T]],
      74      Unpack[tuple[int, str]],
      75      Unpack[tuple[int, ...]],
      76      Unpack[tuple[T, ...]],
      77      tuple[Unpack[tuple[int, ...]]],
      78      tuple[Unpack[tuple[T, ...]]],
      79      tuple[str, Unpack[tuple[int, ...]]],
      80      tuple[Unpack[tuple[int, ...]], str],
      81      tuple[float, Unpack[tuple[int, ...]], str],
      82      tuple[Unpack[tuple[Unpack[tuple[int, ...]]]]],
      83      # Unpacked tuple using `*` AND `Unpack`
      84      tuple[Unpack[tuple[*tuple[int, ...]]]],
      85      tuple[*tuple[Unpack[tuple[int, ...]]]],
      86  ]
      87  
      88  
      89  class ESC[4;38;5;81mBaseTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      90      """Test basics."""
      91      generic_types = [type, tuple, list, dict, set, frozenset, enumerate,
      92                       defaultdict, deque,
      93                       SequenceMatcher,
      94                       dircmp,
      95                       FileInput,
      96                       OrderedDict, Counter, UserDict, UserList,
      97                       Pattern, Match,
      98                       partial, partialmethod, cached_property,
      99                       TopologicalSorter,
     100                       AbstractContextManager, AbstractAsyncContextManager,
     101                       Awaitable, Coroutine,
     102                       AsyncIterable, AsyncIterator,
     103                       AsyncGenerator, Generator,
     104                       Iterable, Iterator,
     105                       Reversible,
     106                       Container, Collection,
     107                       Mailbox, _PartialFile,
     108                       ContextVar, Token,
     109                       Field,
     110                       Set, MutableSet,
     111                       Mapping, MutableMapping, MappingView,
     112                       KeysView, ItemsView, ValuesView,
     113                       Sequence, MutableSequence,
     114                       MappingProxyType, AsyncGeneratorType,
     115                       DirEntry,
     116                       chain,
     117                       LoggerAdapter, StreamHandler,
     118                       TemporaryDirectory, SpooledTemporaryFile,
     119                       Queue, SimpleQueue,
     120                       _AssertRaisesContext,
     121                       SplitResult, ParseResult,
     122                       WeakSet, ReferenceType, ref,
     123                       ShareableList,
     124                       Future, _WorkItem,
     125                       Morsel]
     126      if ctypes is not None:
     127          generic_types.extend((ctypes.Array, ctypes.LibraryLoader))
     128      if ValueProxy is not None:
     129          generic_types.extend((ValueProxy, ApplyResult, MPSimpleQueue))
     130  
     131      def test_subscriptable(self):
     132          for t in self.generic_types:
     133              if t is None:
     134                  continue
     135              tname = t.__name__
     136              with self.subTest(f"Testing {tname}"):
     137                  alias = t[int]
     138                  self.assertIs(alias.__origin__, t)
     139                  self.assertEqual(alias.__args__, (int,))
     140                  self.assertEqual(alias.__parameters__, ())
     141  
     142      def test_unsubscriptable(self):
     143          for t in int, str, float, Sized, Hashable:
     144              tname = t.__name__
     145              with self.subTest(f"Testing {tname}"):
     146                  with self.assertRaisesRegex(TypeError, tname):
     147                      t[int]
     148  
     149      def test_instantiate(self):
     150          for t in tuple, list, dict, set, frozenset, defaultdict, deque:
     151              tname = t.__name__
     152              with self.subTest(f"Testing {tname}"):
     153                  alias = t[int]
     154                  self.assertEqual(alias(), t())
     155                  if t is dict:
     156                      self.assertEqual(alias(iter([('a', 1), ('b', 2)])), dict(a=1, b=2))
     157                      self.assertEqual(alias(a=1, b=2), dict(a=1, b=2))
     158                  elif t is defaultdict:
     159                      def default():
     160                          return 'value'
     161                      a = alias(default)
     162                      d = defaultdict(default)
     163                      self.assertEqual(a['test'], d['test'])
     164                  else:
     165                      self.assertEqual(alias(iter((1, 2, 3))), t((1, 2, 3)))
     166  
     167      def test_unbound_methods(self):
     168          t = list[int]
     169          a = t()
     170          t.append(a, 'foo')
     171          self.assertEqual(a, ['foo'])
     172          x = t.__getitem__(a, 0)
     173          self.assertEqual(x, 'foo')
     174          self.assertEqual(t.__len__(a), 1)
     175  
     176      def test_subclassing(self):
     177          class ESC[4;38;5;81mC(ESC[4;38;5;149mlist[int]):
     178              pass
     179          self.assertEqual(C.__bases__, (list,))
     180          self.assertEqual(C.__class__, type)
     181  
     182      def test_class_methods(self):
     183          t = dict[int, None]
     184          self.assertEqual(dict.fromkeys(range(2)), {0: None, 1: None})  # This works
     185          self.assertEqual(t.fromkeys(range(2)), {0: None, 1: None})  # Should be equivalent
     186  
     187      def test_no_chaining(self):
     188          t = list[int]
     189          with self.assertRaises(TypeError):
     190              t[int]
     191  
     192      def test_generic_subclass(self):
     193          class ESC[4;38;5;81mMyList(ESC[4;38;5;149mlist):
     194              pass
     195          t = MyList[int]
     196          self.assertIs(t.__origin__, MyList)
     197          self.assertEqual(t.__args__, (int,))
     198          self.assertEqual(t.__parameters__, ())
     199  
     200      def test_repr(self):
     201          class ESC[4;38;5;81mMyList(ESC[4;38;5;149mlist):
     202              pass
     203          self.assertEqual(repr(list[str]), 'list[str]')
     204          self.assertEqual(repr(list[()]), 'list[()]')
     205          self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]')
     206          x1 = tuple[*tuple[int]]
     207          self.assertEqual(repr(x1), 'tuple[*tuple[int]]')
     208          x2 = tuple[*tuple[int, str]]
     209          self.assertEqual(repr(x2), 'tuple[*tuple[int, str]]')
     210          x3 = tuple[*tuple[int, ...]]
     211          self.assertEqual(repr(x3), 'tuple[*tuple[int, ...]]')
     212          self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]'))
     213          self.assertEqual(repr(list[str]()), '[]')  # instances should keep their normal repr
     214  
     215      def test_exposed_type(self):
     216          import types
     217          a = types.GenericAlias(list, int)
     218          self.assertEqual(str(a), 'list[int]')
     219          self.assertIs(a.__origin__, list)
     220          self.assertEqual(a.__args__, (int,))
     221          self.assertEqual(a.__parameters__, ())
     222  
     223      def test_parameters(self):
     224          from typing import List, Dict, Callable
     225  
     226          D0 = dict[str, int]
     227          self.assertEqual(D0.__args__, (str, int))
     228          self.assertEqual(D0.__parameters__, ())
     229          D1a = dict[str, V]
     230          self.assertEqual(D1a.__args__, (str, V))
     231          self.assertEqual(D1a.__parameters__, (V,))
     232          D1b = dict[K, int]
     233          self.assertEqual(D1b.__args__, (K, int))
     234          self.assertEqual(D1b.__parameters__, (K,))
     235          D2a = dict[K, V]
     236          self.assertEqual(D2a.__args__, (K, V))
     237          self.assertEqual(D2a.__parameters__, (K, V))
     238          D2b = dict[T, T]
     239          self.assertEqual(D2b.__args__, (T, T))
     240          self.assertEqual(D2b.__parameters__, (T,))
     241  
     242          L0 = list[str]
     243          self.assertEqual(L0.__args__, (str,))
     244          self.assertEqual(L0.__parameters__, ())
     245          L1 = list[T]
     246          self.assertEqual(L1.__args__, (T,))
     247          self.assertEqual(L1.__parameters__, (T,))
     248          L2 = list[list[T]]
     249          self.assertEqual(L2.__args__, (list[T],))
     250          self.assertEqual(L2.__parameters__, (T,))
     251          L3 = list[List[T]]
     252          self.assertEqual(L3.__args__, (List[T],))
     253          self.assertEqual(L3.__parameters__, (T,))
     254          L4a = list[Dict[K, V]]
     255          self.assertEqual(L4a.__args__, (Dict[K, V],))
     256          self.assertEqual(L4a.__parameters__, (K, V))
     257          L4b = list[Dict[T, int]]
     258          self.assertEqual(L4b.__args__, (Dict[T, int],))
     259          self.assertEqual(L4b.__parameters__, (T,))
     260          L5 = list[Callable[[K, V], K]]
     261          self.assertEqual(L5.__args__, (Callable[[K, V], K],))
     262          self.assertEqual(L5.__parameters__, (K, V))
     263  
     264          T1 = tuple[*tuple[int]]
     265          self.assertEqual(
     266              T1.__args__,
     267              (*tuple[int],),
     268          )
     269          self.assertEqual(T1.__parameters__, ())
     270  
     271          T2 = tuple[*tuple[T]]
     272          self.assertEqual(
     273              T2.__args__,
     274              (*tuple[T],),
     275          )
     276          self.assertEqual(T2.__parameters__, (T,))
     277  
     278          T4 = tuple[*tuple[int, str]]
     279          self.assertEqual(
     280              T4.__args__,
     281              (*tuple[int, str],),
     282          )
     283          self.assertEqual(T4.__parameters__, ())
     284  
     285      def test_parameter_chaining(self):
     286          from typing import List, Dict, Union, Callable
     287          self.assertEqual(list[T][int], list[int])
     288          self.assertEqual(dict[str, T][int], dict[str, int])
     289          self.assertEqual(dict[T, int][str], dict[str, int])
     290          self.assertEqual(dict[K, V][str, int], dict[str, int])
     291          self.assertEqual(dict[T, T][int], dict[int, int])
     292  
     293          self.assertEqual(list[list[T]][int], list[list[int]])
     294          self.assertEqual(list[dict[T, int]][str], list[dict[str, int]])
     295          self.assertEqual(list[dict[str, T]][int], list[dict[str, int]])
     296          self.assertEqual(list[dict[K, V]][str, int], list[dict[str, int]])
     297          self.assertEqual(dict[T, list[int]][str], dict[str, list[int]])
     298  
     299          self.assertEqual(list[List[T]][int], list[List[int]])
     300          self.assertEqual(list[Dict[K, V]][str, int], list[Dict[str, int]])
     301          self.assertEqual(list[Union[K, V]][str, int], list[Union[str, int]])
     302          self.assertEqual(list[Callable[[K, V], K]][str, int],
     303                           list[Callable[[str, int], str]])
     304          self.assertEqual(dict[T, List[int]][str], dict[str, List[int]])
     305  
     306          with self.assertRaises(TypeError):
     307              list[int][int]
     308          with self.assertRaises(TypeError):
     309              dict[T, int][str, int]
     310          with self.assertRaises(TypeError):
     311              dict[str, T][str, int]
     312          with self.assertRaises(TypeError):
     313              dict[T, T][str, int]
     314  
     315      def test_equality(self):
     316          self.assertEqual(list[int], list[int])
     317          self.assertEqual(dict[str, int], dict[str, int])
     318          self.assertEqual((*tuple[int],)[0], (*tuple[int],)[0])
     319          self.assertEqual(tuple[*tuple[int]], tuple[*tuple[int]])
     320          self.assertNotEqual(dict[str, int], dict[str, str])
     321          self.assertNotEqual(list, list[int])
     322          self.assertNotEqual(list[int], list)
     323          self.assertNotEqual(list[int], tuple[int])
     324          self.assertNotEqual((*tuple[int],)[0], tuple[int])
     325  
     326      def test_isinstance(self):
     327          self.assertTrue(isinstance([], list))
     328          with self.assertRaises(TypeError):
     329              isinstance([], list[str])
     330  
     331      def test_issubclass(self):
     332          class ESC[4;38;5;81mL(ESC[4;38;5;149mlist): ...
     333          self.assertTrue(issubclass(L, list))
     334          with self.assertRaises(TypeError):
     335              issubclass(L, list[str])
     336  
     337      def test_type_generic(self):
     338          t = type[int]
     339          Test = t('Test', (), {})
     340          self.assertTrue(isinstance(Test, type))
     341          test = Test()
     342          self.assertEqual(t(test), Test)
     343          self.assertEqual(t(0), int)
     344  
     345      def test_type_subclass_generic(self):
     346          class ESC[4;38;5;81mMyType(ESC[4;38;5;149mtype):
     347              pass
     348          with self.assertRaisesRegex(TypeError, 'MyType'):
     349              MyType[int]
     350  
     351      def test_pickle(self):
     352          aliases = [GenericAlias(list, T)] + _UNPACKED_TUPLES
     353          for alias in aliases:
     354              for proto in range(pickle.HIGHEST_PROTOCOL + 1):
     355                  with self.subTest(alias=alias, proto=proto):
     356                      s = pickle.dumps(alias, proto)
     357                      loaded = pickle.loads(s)
     358                      self.assertEqual(loaded.__origin__, alias.__origin__)
     359                      self.assertEqual(loaded.__args__, alias.__args__)
     360                      self.assertEqual(loaded.__parameters__, alias.__parameters__)
     361                      self.assertEqual(type(loaded), type(alias))
     362  
     363      def test_copy(self):
     364          class ESC[4;38;5;81mX(ESC[4;38;5;149mlist):
     365              def __copy__(self):
     366                  return self
     367              def __deepcopy__(self, memo):
     368                  return self
     369  
     370          aliases = [
     371              GenericAlias(list, T),
     372              GenericAlias(deque, T),
     373              GenericAlias(X, T)
     374          ] + _UNPACKED_TUPLES
     375          for alias in aliases:
     376              with self.subTest(alias=alias):
     377                  copied = copy.copy(alias)
     378                  self.assertEqual(copied.__origin__, alias.__origin__)
     379                  self.assertEqual(copied.__args__, alias.__args__)
     380                  self.assertEqual(copied.__parameters__, alias.__parameters__)
     381                  copied = copy.deepcopy(alias)
     382                  self.assertEqual(copied.__origin__, alias.__origin__)
     383                  self.assertEqual(copied.__args__, alias.__args__)
     384                  self.assertEqual(copied.__parameters__, alias.__parameters__)
     385  
     386      def test_unpack(self):
     387          alias = tuple[str, ...]
     388          self.assertIs(alias.__unpacked__, False)
     389          unpacked = (*alias,)[0]
     390          self.assertIs(unpacked.__unpacked__, True)
     391  
     392      def test_union(self):
     393          a = typing.Union[list[int], list[str]]
     394          self.assertEqual(a.__args__, (list[int], list[str]))
     395          self.assertEqual(a.__parameters__, ())
     396  
     397      def test_union_generic(self):
     398          a = typing.Union[list[T], tuple[T, ...]]
     399          self.assertEqual(a.__args__, (list[T], tuple[T, ...]))
     400          self.assertEqual(a.__parameters__, (T,))
     401  
     402      def test_dir(self):
     403          dir_of_gen_alias = set(dir(list[int]))
     404          self.assertTrue(dir_of_gen_alias.issuperset(dir(list)))
     405          for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
     406              self.assertIn(generic_alias_property, dir_of_gen_alias)
     407  
     408      def test_weakref(self):
     409          for t in self.generic_types:
     410              if t is None:
     411                  continue
     412              tname = t.__name__
     413              with self.subTest(f"Testing {tname}"):
     414                  alias = t[int]
     415                  self.assertEqual(ref(alias)(), alias)
     416  
     417      def test_no_kwargs(self):
     418          # bpo-42576
     419          with self.assertRaises(TypeError):
     420              GenericAlias(bad=float)
     421  
     422      def test_subclassing_types_genericalias(self):
     423          class ESC[4;38;5;81mSubClass(ESC[4;38;5;149mGenericAlias): ...
     424          alias = SubClass(list, int)
     425          class ESC[4;38;5;81mBad(ESC[4;38;5;149mGenericAlias):
     426              def __new__(cls, *args, **kwargs):
     427                  super().__new__(cls, *args, **kwargs)
     428  
     429          self.assertEqual(alias, list[int])
     430          with self.assertRaises(TypeError):
     431              Bad(list, int, bad=int)
     432  
     433      def test_iter_creates_starred_tuple(self):
     434          t = tuple[int, str]
     435          iter_t = iter(t)
     436          x = next(iter_t)
     437          self.assertEqual(repr(x), '*tuple[int, str]')
     438  
     439      def test_calling_next_twice_raises_stopiteration(self):
     440          t = tuple[int, str]
     441          iter_t = iter(t)
     442          next(iter_t)
     443          with self.assertRaises(StopIteration):
     444              next(iter_t)
     445  
     446      def test_del_iter(self):
     447          t = tuple[int, str]
     448          iter_x = iter(t)
     449          del iter_x
     450  
     451  
     452  class ESC[4;38;5;81mTypeIterationTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     453      _UNITERABLE_TYPES = (list, tuple)
     454  
     455      def test_cannot_iterate(self):
     456          for test_type in self._UNITERABLE_TYPES:
     457              with self.subTest(type=test_type):
     458                  expected_error_regex = "object is not iterable"
     459                  with self.assertRaisesRegex(TypeError, expected_error_regex):
     460                      iter(test_type)
     461                  with self.assertRaisesRegex(TypeError, expected_error_regex):
     462                      list(test_type)
     463                  with self.assertRaisesRegex(TypeError, expected_error_regex):
     464                      for _ in test_type:
     465                          pass
     466  
     467      def test_is_not_instance_of_iterable(self):
     468          for type_to_test in self._UNITERABLE_TYPES:
     469              self.assertNotIsInstance(type_to_test, Iterable)
     470  
     471  
     472  if __name__ == "__main__":
     473      unittest.main()