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