(root)/
Python-3.11.7/
Lib/
test/
test_super.py
       1  """Unit tests for zero-argument super() & related machinery."""
       2  
       3  import unittest
       4  
       5  
       6  class ESC[4;38;5;81mA:
       7      def f(self):
       8          return 'A'
       9      @classmethod
      10      def cm(cls):
      11          return (cls, 'A')
      12  
      13  class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
      14      def f(self):
      15          return super().f() + 'B'
      16      @classmethod
      17      def cm(cls):
      18          return (cls, super().cm(), 'B')
      19  
      20  class ESC[4;38;5;81mC(ESC[4;38;5;149mA):
      21      def f(self):
      22          return super().f() + 'C'
      23      @classmethod
      24      def cm(cls):
      25          return (cls, super().cm(), 'C')
      26  
      27  class ESC[4;38;5;81mD(ESC[4;38;5;149mC, ESC[4;38;5;149mB):
      28      def f(self):
      29          return super().f() + 'D'
      30      def cm(cls):
      31          return (cls, super().cm(), 'D')
      32  
      33  class ESC[4;38;5;81mE(ESC[4;38;5;149mD):
      34      pass
      35  
      36  class ESC[4;38;5;81mF(ESC[4;38;5;149mE):
      37      f = E.f
      38  
      39  class ESC[4;38;5;81mG(ESC[4;38;5;149mA):
      40      pass
      41  
      42  
      43  class ESC[4;38;5;81mTestSuper(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      44  
      45      def tearDown(self):
      46          # This fixes the damage that test_various___class___pathologies does.
      47          nonlocal __class__
      48          __class__ = TestSuper
      49  
      50      def test_basics_working(self):
      51          self.assertEqual(D().f(), 'ABCD')
      52  
      53      def test_class_getattr_working(self):
      54          self.assertEqual(D.f(D()), 'ABCD')
      55  
      56      def test_subclass_no_override_working(self):
      57          self.assertEqual(E().f(), 'ABCD')
      58          self.assertEqual(E.f(E()), 'ABCD')
      59  
      60      def test_unbound_method_transfer_working(self):
      61          self.assertEqual(F().f(), 'ABCD')
      62          self.assertEqual(F.f(F()), 'ABCD')
      63  
      64      def test_class_methods_still_working(self):
      65          self.assertEqual(A.cm(), (A, 'A'))
      66          self.assertEqual(A().cm(), (A, 'A'))
      67          self.assertEqual(G.cm(), (G, 'A'))
      68          self.assertEqual(G().cm(), (G, 'A'))
      69  
      70      def test_super_in_class_methods_working(self):
      71          d = D()
      72          self.assertEqual(d.cm(), (d, (D, (D, (D, 'A'), 'B'), 'C'), 'D'))
      73          e = E()
      74          self.assertEqual(e.cm(), (e, (E, (E, (E, 'A'), 'B'), 'C'), 'D'))
      75  
      76      def test_super_with_closure(self):
      77          # Issue4360: super() did not work in a function that
      78          # contains a closure
      79          class ESC[4;38;5;81mE(ESC[4;38;5;149mA):
      80              def f(self):
      81                  def nested():
      82                      self
      83                  return super().f() + 'E'
      84  
      85          self.assertEqual(E().f(), 'AE')
      86  
      87      def test_various___class___pathologies(self):
      88          # See issue #12370
      89          class ESC[4;38;5;81mX(ESC[4;38;5;149mA):
      90              def f(self):
      91                  return super().f()
      92              __class__ = 413
      93          x = X()
      94          self.assertEqual(x.f(), 'A')
      95          self.assertEqual(x.__class__, 413)
      96          class ESC[4;38;5;81mX:
      97              x = __class__
      98              def f():
      99                  __class__
     100          self.assertIs(X.x, type(self))
     101          with self.assertRaises(NameError) as e:
     102              exec("""class X:
     103                  __class__
     104                  def f():
     105                      __class__""", globals(), {})
     106          self.assertIs(type(e.exception), NameError) # Not UnboundLocalError
     107          class ESC[4;38;5;81mX:
     108              global __class__
     109              __class__ = 42
     110              def f():
     111                  __class__
     112          self.assertEqual(globals()["__class__"], 42)
     113          del globals()["__class__"]
     114          self.assertNotIn("__class__", X.__dict__)
     115          class ESC[4;38;5;81mX:
     116              nonlocal __class__
     117              __class__ = 42
     118              def f():
     119                  __class__
     120          self.assertEqual(__class__, 42)
     121  
     122      def test___class___instancemethod(self):
     123          # See issue #14857
     124          class ESC[4;38;5;81mX:
     125              def f(self):
     126                  return __class__
     127          self.assertIs(X().f(), X)
     128  
     129      def test___class___classmethod(self):
     130          # See issue #14857
     131          class ESC[4;38;5;81mX:
     132              @classmethod
     133              def f(cls):
     134                  return __class__
     135          self.assertIs(X.f(), X)
     136  
     137      def test___class___staticmethod(self):
     138          # See issue #14857
     139          class ESC[4;38;5;81mX:
     140              @staticmethod
     141              def f():
     142                  return __class__
     143          self.assertIs(X.f(), X)
     144  
     145      def test___class___new(self):
     146          # See issue #23722
     147          # Ensure zero-arg super() works as soon as type.__new__() is completed
     148          test_class = None
     149  
     150          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     151              def __new__(cls, name, bases, namespace):
     152                  nonlocal test_class
     153                  self = super().__new__(cls, name, bases, namespace)
     154                  test_class = self.f()
     155                  return self
     156  
     157          class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mMeta):
     158              @staticmethod
     159              def f():
     160                  return __class__
     161  
     162          self.assertIs(test_class, A)
     163  
     164      def test___class___delayed(self):
     165          # See issue #23722
     166          test_namespace = None
     167  
     168          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     169              def __new__(cls, name, bases, namespace):
     170                  nonlocal test_namespace
     171                  test_namespace = namespace
     172                  return None
     173  
     174          class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mMeta):
     175              @staticmethod
     176              def f():
     177                  return __class__
     178  
     179          self.assertIs(A, None)
     180  
     181          B = type("B", (), test_namespace)
     182          self.assertIs(B.f(), B)
     183  
     184      def test___class___mro(self):
     185          # See issue #23722
     186          test_class = None
     187  
     188          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     189              def mro(self):
     190                  # self.f() doesn't work yet...
     191                  self.__dict__["f"]()
     192                  return super().mro()
     193  
     194          class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mMeta):
     195              def f():
     196                  nonlocal test_class
     197                  test_class = __class__
     198  
     199          self.assertIs(test_class, A)
     200  
     201      def test___classcell___expected_behaviour(self):
     202          # See issue #23722
     203          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     204              def __new__(cls, name, bases, namespace):
     205                  nonlocal namespace_snapshot
     206                  namespace_snapshot = namespace.copy()
     207                  return super().__new__(cls, name, bases, namespace)
     208  
     209          # __classcell__ is injected into the class namespace by the compiler
     210          # when at least one method needs it, and should be omitted otherwise
     211          namespace_snapshot = None
     212          class ESC[4;38;5;81mWithoutClassRef(metaclass=ESC[4;38;5;149mMeta):
     213              pass
     214          self.assertNotIn("__classcell__", namespace_snapshot)
     215  
     216          # With zero-arg super() or an explicit __class__ reference,
     217          # __classcell__ is the exact cell reference to be populated by
     218          # type.__new__
     219          namespace_snapshot = None
     220          class ESC[4;38;5;81mWithClassRef(metaclass=ESC[4;38;5;149mMeta):
     221              def f(self):
     222                  return __class__
     223  
     224          class_cell = namespace_snapshot["__classcell__"]
     225          method_closure = WithClassRef.f.__closure__
     226          self.assertEqual(len(method_closure), 1)
     227          self.assertIs(class_cell, method_closure[0])
     228          # Ensure the cell reference *doesn't* get turned into an attribute
     229          with self.assertRaises(AttributeError):
     230              WithClassRef.__classcell__
     231  
     232      def test___classcell___missing(self):
     233          # See issue #23722
     234          # Some metaclasses may not pass the original namespace to type.__new__
     235          # We test that case here by forcibly deleting __classcell__
     236          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     237              def __new__(cls, name, bases, namespace):
     238                  namespace.pop('__classcell__', None)
     239                  return super().__new__(cls, name, bases, namespace)
     240  
     241          # The default case should continue to work without any errors
     242          class ESC[4;38;5;81mWithoutClassRef(metaclass=ESC[4;38;5;149mMeta):
     243              pass
     244  
     245          # With zero-arg super() or an explicit __class__ reference, we expect
     246          # __build_class__ to raise a RuntimeError complaining that
     247          # __class__ was not set, and asking if __classcell__ was propagated
     248          # to type.__new__.
     249          expected_error = '__class__ not set.*__classcell__ propagated'
     250          with self.assertRaisesRegex(RuntimeError, expected_error):
     251              class ESC[4;38;5;81mWithClassRef(metaclass=ESC[4;38;5;149mMeta):
     252                  def f(self):
     253                      return __class__
     254  
     255      def test___classcell___overwrite(self):
     256          # See issue #23722
     257          # Overwriting __classcell__ with nonsense is explicitly prohibited
     258          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     259              def __new__(cls, name, bases, namespace, cell):
     260                  namespace['__classcell__'] = cell
     261                  return super().__new__(cls, name, bases, namespace)
     262  
     263          for bad_cell in (None, 0, "", object()):
     264              with self.subTest(bad_cell=bad_cell):
     265                  with self.assertRaises(TypeError):
     266                      class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mMeta, cell=ESC[4;38;5;149mbad_cell):
     267                          pass
     268  
     269      def test___classcell___wrong_cell(self):
     270          # See issue #23722
     271          # Pointing the cell reference at the wrong class is also prohibited
     272          class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
     273              def __new__(cls, name, bases, namespace):
     274                  cls = super().__new__(cls, name, bases, namespace)
     275                  B = type("B", (), namespace)
     276                  return cls
     277  
     278          with self.assertRaises(TypeError):
     279              class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mMeta):
     280                  def f(self):
     281                      return __class__
     282  
     283      def test_obscure_super_errors(self):
     284          def f():
     285              super()
     286          self.assertRaises(RuntimeError, f)
     287          def f(x):
     288              del x
     289              super()
     290          self.assertRaises(RuntimeError, f, None)
     291          class ESC[4;38;5;81mX:
     292              def f(x):
     293                  nonlocal __class__
     294                  del __class__
     295                  super()
     296          self.assertRaises(RuntimeError, X().f)
     297  
     298      def test_cell_as_self(self):
     299          class ESC[4;38;5;81mX:
     300              def meth(self):
     301                  super()
     302  
     303          def f():
     304              k = X()
     305              def g():
     306                  return k
     307              return g
     308          c = f().__closure__[0]
     309          self.assertRaises(TypeError, X.meth, c)
     310  
     311      def test_super_init_leaks(self):
     312          # Issue #26718: super.__init__ leaked memory if called multiple times.
     313          # This will be caught by regrtest.py -R if this leak.
     314          # NOTE: Despite the use in the test a direct call of super.__init__
     315          # is not endorsed.
     316          sp = super(float, 1.0)
     317          for i in range(1000):
     318              super.__init__(sp, int, i)
     319  
     320      def test_super_argcount(self):
     321          with self.assertRaisesRegex(TypeError, "expected at most"):
     322              super(int, int, int)
     323  
     324      def test_super_argtype(self):
     325          with self.assertRaisesRegex(TypeError, "argument 1 must be a type"):
     326              super(1, int)
     327  
     328  
     329  if __name__ == "__main__":
     330      unittest.main()