blob: 5d94372bf6ec7fda42389d56f06419978ae73fb6 [file] [log] [blame]
Nick Coghlan19d24672016-12-05 16:47:55 +10001"""Unit tests for zero-argument super() & related machinery."""
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002
Guido van Rossumcd16bf62007-06-13 18:07:49 +00003import unittest
Guido van Rossumcd16bf62007-06-13 18:07:49 +00004
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
Benjamin Petersona29ac452013-05-17 11:33:26 -050045 def tearDown(self):
46 # This fixes the damage that test_various___class___pathologies does.
47 nonlocal __class__
48 __class__ = TestSuper
49
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050050 def test_basics_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000051 self.assertEqual(D().f(), 'ABCD')
52
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050053 def test_class_getattr_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000054 self.assertEqual(D.f(D()), 'ABCD')
55
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050056 def test_subclass_no_override_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000057 self.assertEqual(E().f(), 'ABCD')
58 self.assertEqual(E.f(E()), 'ABCD')
59
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050060 def test_unbound_method_transfer_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000061 self.assertEqual(F().f(), 'ABCD')
62 self.assertEqual(F.f(F()), 'ABCD')
63
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050064 def test_class_methods_still_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000065 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
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050070 def test_super_in_class_methods_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000071 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
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050076 def test_super_with_closure(self):
Barry Warsaw91cc8fb2008-11-20 20:01:57 +000077 # 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
Benjamin Peterson312595c2013-05-15 15:26:42 -050087 def test_various___class___pathologies(self):
Benjamin Petersonf5ff2232011-06-19 19:42:22 -050088 # 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)
Benjamin Peterson312595c2013-05-15 15:26:42 -050096 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)
Benjamin Petersonf5ff2232011-06-19 19:42:22 -0500121
Nick Coghlan0b43bcf2012-05-27 18:17:07 +1000122 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
Nick Coghlan944368e2016-09-11 14:45:49 +1000145 def test___class___new(self):
Nick Coghlan19d24672016-12-05 16:47:55 +1000146 # See issue #23722
147 # Ensure zero-arg super() works as soon as type.__new__() is completed
Nick Coghlan944368e2016-09-11 14:45:49 +1000148 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):
Nick Coghlan19d24672016-12-05 16:47:55 +1000165 # See issue #23722
Nick Coghlan944368e2016-09-11 14:45:49 +1000166 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
Serhiy Storchakaf5e7b192018-05-20 08:48:12 +0300174 class A(metaclass=Meta):
175 @staticmethod
176 def f():
177 return __class__
Nick Coghlan944368e2016-09-11 14:45:49 +1000178
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):
Nick Coghlan19d24672016-12-05 16:47:55 +1000185 # See issue #23722
Nick Coghlan944368e2016-09-11 14:45:49 +1000186 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
Nick Coghlan19d24672016-12-05 16:47:55 +1000201 def test___classcell___expected_behaviour(self):
202 # See issue #23722
Nick Coghlan944368e2016-09-11 14:45:49 +1000203 class Meta(type):
204 def __new__(cls, name, bases, namespace):
Nick Coghlan19d24672016-12-05 16:47:55 +1000205 nonlocal namespace_snapshot
206 namespace_snapshot = namespace.copy()
Nick Coghlan944368e2016-09-11 14:45:49 +1000207 return super().__new__(cls, name, bases, namespace)
208
Nick Coghlan19d24672016-12-05 16:47:55 +1000209 # __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)
Nick Coghlan944368e2016-09-11 14:45:49 +1000215
Nick Coghlan19d24672016-12-05 16:47:55 +1000216 # 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__
Nick Coghlan944368e2016-09-11 14:45:49 +1000223
Nick Coghlan19d24672016-12-05 16:47:55 +1000224 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__
Nick Coghlan944368e2016-09-11 14:45:49 +1000236 class Meta(type):
237 def __new__(cls, name, bases, namespace):
Nick Coghlan19d24672016-12-05 16:47:55 +1000238 namespace.pop('__classcell__', None)
Nick Coghlan944368e2016-09-11 14:45:49 +1000239 return super().__new__(cls, name, bases, namespace)
240
Serhiy Storchakaf5e7b192018-05-20 08:48:12 +0300241 # The default case should continue to work without any errors
242 class WithoutClassRef(metaclass=Meta):
243 pass
Nick Coghlan944368e2016-09-11 14:45:49 +1000244
Nick Coghlan19d24672016-12-05 16:47:55 +1000245 # With zero-arg super() or an explicit __class__ reference, we expect
Serhiy Storchakaf5e7b192018-05-20 08:48:12 +0300246 # __build_class__ to raise a RuntimeError complaining that
Nick Coghlan19d24672016-12-05 16:47:55 +1000247 # __class__ was not set, and asking if __classcell__ was propagated
248 # to type.__new__.
Serhiy Storchakaf5e7b192018-05-20 08:48:12 +0300249 expected_error = '__class__ not set.*__classcell__ propagated'
250 with self.assertRaisesRegex(RuntimeError, expected_error):
Nick Coghlan19d24672016-12-05 16:47:55 +1000251 class WithClassRef(metaclass=Meta):
252 def f(self):
253 return __class__
Nick Coghlan19d24672016-12-05 16:47:55 +1000254
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__
Nick Coghlan944368e2016-09-11 14:45:49 +1000282
Benjamin Peterson6a42bd62012-09-01 23:04:38 -0400283 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
Benjamin Peterson159ae412013-05-12 18:16:06 -0500298 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
Serhiy Storchaka3d749762016-04-13 15:27:33 +0300311 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
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000320
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000321if __name__ == "__main__":
322 unittest.main()