(root)/
Python-3.12.0/
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(ZeroDivisionError) as cm:
     138              class ESC[4;38;5;81mNotGoingToWork:
     139                  attr = Descriptor()
     140  
     141          notes = cm.exception.__notes__
     142          self.assertRegex(str(notes), r'\bNotGoingToWork\b')
     143          self.assertRegex(str(notes), r'\battr\b')
     144          self.assertRegex(str(notes), r'\bDescriptor\b')
     145  
     146      def test_set_name_wrong(self):
     147          class ESC[4;38;5;81mDescriptor:
     148              def __set_name__(self):
     149                  pass
     150  
     151          with self.assertRaises(TypeError) as cm:
     152              class ESC[4;38;5;81mNotGoingToWork:
     153                  attr = Descriptor()
     154  
     155          notes = cm.exception.__notes__
     156          self.assertRegex(str(notes), r'\bNotGoingToWork\b')
     157          self.assertRegex(str(notes), r'\battr\b')
     158          self.assertRegex(str(notes), r'\bDescriptor\b')
     159  
     160      def test_set_name_lookup(self):
     161          resolved = []
     162          class ESC[4;38;5;81mNonDescriptor:
     163              def __getattr__(self, name):
     164                  resolved.append(name)
     165  
     166          class ESC[4;38;5;81mA:
     167              d = NonDescriptor()
     168  
     169          self.assertNotIn('__set_name__', resolved,
     170                           '__set_name__ is looked up in instance dict')
     171  
     172      def test_set_name_init_subclass(self):
     173          class ESC[4;38;5;81mDescriptor:
     174              def __set_name__(self, owner, name):
     175                  self.owner = owner
     176                  self.name = name
     177  
     178          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     179              def __new__(cls, name, bases, ns):
     180                  self = super().__new__(cls, name, bases, ns)
     181                  self.meta_owner = self.owner
     182                  self.meta_name = self.name
     183                  return self
     184  
     185          class ESC[4;38;5;81mA:
     186              def __init_subclass__(cls):
     187                  cls.owner = cls.d.owner
     188                  cls.name = cls.d.name
     189  
     190          class ESC[4;38;5;81mB(ESC[4;38;5;149mA, metaclass=ESC[4;38;5;149mMeta):
     191              d = Descriptor()
     192  
     193          self.assertIs(B.owner, B)
     194          self.assertEqual(B.name, 'd')
     195          self.assertIs(B.meta_owner, B)
     196          self.assertEqual(B.name, 'd')
     197  
     198      def test_set_name_modifying_dict(self):
     199          notified = []
     200          class ESC[4;38;5;81mDescriptor:
     201              def __set_name__(self, owner, name):
     202                  setattr(owner, name + 'x', None)
     203                  notified.append(name)
     204  
     205          class ESC[4;38;5;81mA:
     206              a = Descriptor()
     207              b = Descriptor()
     208              c = Descriptor()
     209              d = Descriptor()
     210              e = Descriptor()
     211  
     212          self.assertCountEqual(notified, ['a', 'b', 'c', 'd', 'e'])
     213  
     214      def test_errors(self):
     215          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     216              pass
     217  
     218          with self.assertRaises(TypeError):
     219              class ESC[4;38;5;81mMyClass(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
     220                  pass
     221  
     222          with self.assertRaises(TypeError):
     223              types.new_class("MyClass", (object,),
     224                              dict(metaclass=MyMeta, otherarg=1))
     225          types.prepare_class("MyClass", (object,),
     226                              dict(metaclass=MyMeta, otherarg=1))
     227  
     228          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     229              def __init__(self, name, bases, namespace, otherarg):
     230                  super().__init__(name, bases, namespace)
     231  
     232          with self.assertRaises(TypeError):
     233              class ESC[4;38;5;81mMyClass(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
     234                  pass
     235  
     236          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     237              def __new__(cls, name, bases, namespace, otherarg):
     238                  return super().__new__(cls, name, bases, namespace)
     239  
     240              def __init__(self, name, bases, namespace, otherarg):
     241                  super().__init__(name, bases, namespace)
     242                  self.otherarg = otherarg
     243  
     244          class ESC[4;38;5;81mMyClass(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
     245              pass
     246  
     247          self.assertEqual(MyClass.otherarg, 1)
     248  
     249      def test_errors_changed_pep487(self):
     250          # These tests failed before Python 3.6, PEP 487
     251          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     252              def __new__(cls, name, bases, namespace):
     253                  return super().__new__(cls, name=name, bases=bases,
     254                                         dict=namespace)
     255  
     256          with self.assertRaises(TypeError):
     257              class ESC[4;38;5;81mMyClass(metaclass=ESC[4;38;5;149mMyMeta):
     258                  pass
     259  
     260          class ESC[4;38;5;81mMyMeta(ESC[4;38;5;149mtype):
     261              def __new__(cls, name, bases, namespace, otherarg):
     262                  self = super().__new__(cls, name, bases, namespace)
     263                  self.otherarg = otherarg
     264                  return self
     265  
     266          class ESC[4;38;5;81mMyClass(metaclass=ESC[4;38;5;149mMyMeta, otherarg=1):
     267              pass
     268  
     269          self.assertEqual(MyClass.otherarg, 1)
     270  
     271      def test_type(self):
     272          t = type('NewClass', (object,), {})
     273          self.assertIsInstance(t, type)
     274          self.assertEqual(t.__name__, 'NewClass')
     275  
     276          with self.assertRaises(TypeError):
     277              type(name='NewClass', bases=(object,), dict={})
     278  
     279  
     280  if __name__ == "__main__":
     281      unittest.main()