(root)/
Python-3.11.7/
Lib/
test/
test_subclassinit.py
       1  import types
       2  import unittest
       3  
       4  
       5  class ESC[4;38;5;81mTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
       6      def test_init_subclass(self):
       7          class ESC[4;38;5;81mA:
       8              initialized = False
       9  
      10              def __init_subclass__(cls):
      11                  super().__init_subclass__()
      12                  cls.initialized = True
      13  
      14          class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
      15              pass
      16  
      17          self.assertFalse(A.initialized)
      18          self.assertTrue(B.initialized)
      19  
      20      def test_init_subclass_dict(self):
      21          class ESC[4;38;5;81mA(ESC[4;38;5;149mdict):
      22              initialized = False
      23  
      24              def __init_subclass__(cls):
      25                  super().__init_subclass__()
      26                  cls.initialized = True
      27  
      28          class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
      29              pass
      30  
      31          self.assertFalse(A.initialized)
      32          self.assertTrue(B.initialized)
      33  
      34      def test_init_subclass_kwargs(self):
      35          class ESC[4;38;5;81mA:
      36              def __init_subclass__(cls, **kwargs):
      37                  cls.kwargs = kwargs
      38  
      39          class ESC[4;38;5;81mB(ESC[4;38;5;149mA, x=3):
      40              pass
      41  
      42          self.assertEqual(B.kwargs, dict(x=3))
      43  
      44      def test_init_subclass_error(self):
      45          class ESC[4;38;5;81mA:
      46              def __init_subclass__(cls):
      47                  raise RuntimeError
      48  
      49          with self.assertRaises(RuntimeError):
      50              class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
      51                  pass
      52  
      53      def test_init_subclass_wrong(self):
      54          class ESC[4;38;5;81mA:
      55              def __init_subclass__(cls, whatever):
      56                  pass
      57  
      58          with self.assertRaises(TypeError):
      59              class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
      60                  pass
      61  
      62      def test_init_subclass_skipped(self):
      63          class ESC[4;38;5;81mBaseWithInit:
      64              def __init_subclass__(cls, **kwargs):
      65                  super().__init_subclass__(**kwargs)
      66                  cls.initialized = cls
      67  
      68          class ESC[4;38;5;81mBaseWithoutInit(ESC[4;38;5;149mBaseWithInit):
      69              pass
      70  
      71          class ESC[4;38;5;81mA(ESC[4;38;5;149mBaseWithoutInit):
      72              pass
      73  
      74          self.assertIs(A.initialized, A)
      75          self.assertIs(BaseWithoutInit.initialized, BaseWithoutInit)
      76  
      77      def test_init_subclass_diamond(self):
      78          class ESC[4;38;5;81mBase:
      79              def __init_subclass__(cls, **kwargs):
      80                  super().__init_subclass__(**kwargs)
      81                  cls.calls = []
      82  
      83          class ESC[4;38;5;81mLeft(ESC[4;38;5;149mBase):
      84              pass
      85  
      86          class ESC[4;38;5;81mMiddle:
      87              def __init_subclass__(cls, middle, **kwargs):
      88                  super().__init_subclass__(**kwargs)
      89                  cls.calls += [middle]
      90  
      91          class ESC[4;38;5;81mRight(ESC[4;38;5;149mBase):
      92              def __init_subclass__(cls, right="right", **kwargs):
      93                  super().__init_subclass__(**kwargs)
      94                  cls.calls += [right]
      95  
      96          class ESC[4;38;5;81mA(ESC[4;38;5;149mLeft, ESC[4;38;5;149mMiddle, ESC[4;38;5;149mRight, middle="middle"):
      97              pass
      98  
      99          self.assertEqual(A.calls, ["right", "middle"])
     100          self.assertEqual(Left.calls, [])
     101          self.assertEqual(Right.calls, [])
     102  
     103      def test_set_name(self):
     104          class ESC[4;38;5;81mDescriptor:
     105              def __set_name__(self, owner, name):
     106                  self.owner = owner
     107                  self.name = name
     108  
     109          class ESC[4;38;5;81mA:
     110              d = Descriptor()
     111  
     112          self.assertEqual(A.d.name, "d")
     113          self.assertIs(A.d.owner, A)
     114  
     115      def test_set_name_metaclass(self):
     116          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     117              def __new__(cls, name, bases, ns):
     118                  ret = super().__new__(cls, name, bases, ns)
     119                  self.assertEqual(ret.d.name, "d")
     120                  self.assertIs(ret.d.owner, ret)
     121                  return 0
     122  
     123          class ESC[4;38;5;81mDescriptor:
     124              def __set_name__(self, owner, name):
     125                  self.owner = owner
     126                  self.name = name
     127  
     128          class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mMeta):
     129              d = Descriptor()
     130          self.assertEqual(A, 0)
     131  
     132      def test_set_name_error(self):
     133          class ESC[4;38;5;81mDescriptor:
     134              def __set_name__(self, owner, name):
     135                  1/0
     136  
     137          with self.assertRaises(RuntimeError) as cm:
     138              class ESC[4;38;5;81mNotGoingToWork:
     139                  attr = Descriptor()
     140  
     141          exc = cm.exception
     142          self.assertRegex(str(exc), r'\bNotGoingToWork\b')
     143          self.assertRegex(str(exc), r'\battr\b')
     144          self.assertRegex(str(exc), r'\bDescriptor\b')
     145          self.assertIsInstance(exc.__cause__, ZeroDivisionError)
     146  
     147      def test_set_name_wrong(self):
     148          class ESC[4;38;5;81mDescriptor:
     149              def __set_name__(self):
     150                  pass
     151  
     152          with self.assertRaises(RuntimeError) as cm:
     153              class ESC[4;38;5;81mNotGoingToWork:
     154                  attr = Descriptor()
     155  
     156          exc = cm.exception
     157          self.assertRegex(str(exc), r'\bNotGoingToWork\b')
     158          self.assertRegex(str(exc), r'\battr\b')
     159          self.assertRegex(str(exc), r'\bDescriptor\b')
     160          self.assertIsInstance(exc.__cause__, TypeError)
     161  
     162      def test_set_name_lookup(self):
     163          resolved = []
     164          class ESC[4;38;5;81mNonDescriptor:
     165              def __getattr__(self, name):
     166                  resolved.append(name)
     167  
     168          class ESC[4;38;5;81mA:
     169              d = NonDescriptor()
     170  
     171          self.assertNotIn('__set_name__', resolved,
     172                           '__set_name__ is looked up in instance dict')
     173  
     174      def test_set_name_init_subclass(self):
     175          class ESC[4;38;5;81mDescriptor:
     176              def __set_name__(self, owner, name):
     177                  self.owner = owner
     178                  self.name = name
     179  
     180          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     181              def __new__(cls, name, bases, ns):
     182                  self = super().__new__(cls, name, bases, ns)
     183                  self.meta_owner = self.owner
     184                  self.meta_name = self.name
     185                  return self
     186  
     187          class ESC[4;38;5;81mA:
     188              def __init_subclass__(cls):
     189                  cls.owner = cls.d.owner
     190                  cls.name = cls.d.name
     191  
     192          class ESC[4;38;5;81mB(ESC[4;38;5;149mA, metaclass=ESC[4;38;5;149mMeta):
     193              d = Descriptor()
     194  
     195          self.assertIs(B.owner, B)
     196          self.assertEqual(B.name, 'd')
     197          self.assertIs(B.meta_owner, B)
     198          self.assertEqual(B.name, 'd')
     199  
     200      def test_set_name_modifying_dict(self):
     201          notified = []
     202          class ESC[4;38;5;81mDescriptor:
     203              def __set_name__(self, owner, name):
     204                  setattr(owner, name + 'x', None)
     205                  notified.append(name)
     206  
     207          class ESC[4;38;5;81mA:
     208              a = Descriptor()
     209              b = Descriptor()
     210              c = Descriptor()
     211              d = Descriptor()
     212              e = Descriptor()
     213  
     214          self.assertCountEqual(notified, ['a', 'b', 'c', 'd', 'e'])
     215  
     216      def test_errors(self):
     217          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     218              pass
     219  
     220          with self.assertRaises(TypeError):
     221              class ESC[4;38;5;81mMyClass(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
     222                  pass
     223  
     224          with self.assertRaises(TypeError):
     225              types.new_class("MyClass", (object,),
     226                              dict(metaclass=MyMeta, otherarg=1))
     227          types.prepare_class("MyClass", (object,),
     228                              dict(metaclass=MyMeta, otherarg=1))
     229  
     230          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     231              def __init__(self, name, bases, namespace, otherarg):
     232                  super().__init__(name, bases, namespace)
     233  
     234          with self.assertRaises(TypeError):
     235              class ESC[4;38;5;81mMyClass2(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
     236                  pass
     237  
     238          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     239              def __new__(cls, name, bases, namespace, otherarg):
     240                  return super().__new__(cls, name, bases, namespace)
     241  
     242              def __init__(self, name, bases, namespace, otherarg):
     243                  super().__init__(name, bases, namespace)
     244                  self.otherarg = otherarg
     245  
     246          class ESC[4;38;5;81mMyClass3(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
     247              pass
     248  
     249          self.assertEqual(MyClass3.otherarg, 1)
     250  
     251      def test_errors_changed_pep487(self):
     252          # These tests failed before Python 3.6, PEP 487
     253          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     254              def __new__(cls, name, bases, namespace):
     255                  return super().__new__(cls, name=name, bases=bases,
     256                                         dict=namespace)
     257  
     258          with self.assertRaises(TypeError):
     259              class ESC[4;38;5;81mMyClass(metaclass=ESC[4;38;5;149mMyMeta):
     260                  pass
     261  
     262          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     263              def __new__(cls, name, bases, namespace, otherarg):
     264                  self = super().__new__(cls, name, bases, namespace)
     265                  self.otherarg = otherarg
     266                  return self
     267  
     268          class ESC[4;38;5;81mMyClass2(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
     269              pass
     270  
     271          self.assertEqual(MyClass2.otherarg, 1)
     272  
     273      def test_type(self):
     274          t = type('NewClass', (object,), {})
     275          self.assertIsInstance(t, type)
     276          self.assertEqual(t.__name__, 'NewClass')
     277  
     278          with self.assertRaises(TypeError):
     279              type(name='NewClass', bases=(object,), dict={})
     280  
     281  
     282  if __name__ == "__main__":
     283      unittest.main()