1"""Unit tests for zero-argument super() & related machinery.""" 2 3import unittest 4 5 6class A: 7 def f(self): 8 return 'A' 9 @classmethod 10 def cm(cls): 11 return (cls, 'A') 12 13class B(A): 14 def f(self): 15 return super().f() + 'B' 16 @classmethod 17 def cm(cls): 18 return (cls, super().cm(), 'B') 19 20class C(A): 21 def f(self): 22 return super().f() + 'C' 23 @classmethod 24 def cm(cls): 25 return (cls, super().cm(), 'C') 26 27class D(C, B): 28 def f(self): 29 return super().f() + 'D' 30 def cm(cls): 31 return (cls, super().cm(), 'D') 32 33class E(D): 34 pass 35 36class F(E): 37 f = E.f 38 39class G(A): 40 pass 41 42 43class TestSuper(unittest.TestCase): 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 E(A): 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 X(A): 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 X: 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 X: 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 X: 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 X: 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 X: 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 X: 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 Meta(type): 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 A(metaclass=Meta): 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 Meta(type): 169 def __new__(cls, name, bases, namespace): 170 nonlocal test_namespace 171 test_namespace = namespace 172 return None 173 174 class A(metaclass=Meta): 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 Meta(type): 189 def mro(self): 190 # self.f() doesn't work yet... 191 self.__dict__["f"]() 192 return super().mro() 193 194 class A(metaclass=Meta): 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 Meta(type): 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 WithoutClassRef(metaclass=Meta): 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 WithClassRef(metaclass=Meta): 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 Meta(type): 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 WithoutClassRef(metaclass=Meta): 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 WithClassRef(metaclass=Meta): 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 Meta(type): 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 A(metaclass=Meta, cell=bad_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 Meta(type): 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 A(metaclass=Meta): 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 X: 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 X: 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 321if __name__ == "__main__": 322 unittest.main() 323