blob: cb2d7c32236b4cea115c73f23e79afbf6fd4d553 [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
Nick Coghlan19d24672016-12-05 16:47:55 +10004import warnings
5from test.support import check_warnings
Guido van Rossumcd16bf62007-06-13 18:07:49 +00006
7
8class A:
9 def f(self):
10 return 'A'
11 @classmethod
12 def cm(cls):
13 return (cls, 'A')
14
15class B(A):
16 def f(self):
17 return super().f() + 'B'
18 @classmethod
19 def cm(cls):
20 return (cls, super().cm(), 'B')
21
22class C(A):
23 def f(self):
24 return super().f() + 'C'
25 @classmethod
26 def cm(cls):
27 return (cls, super().cm(), 'C')
28
29class D(C, B):
30 def f(self):
31 return super().f() + 'D'
32 def cm(cls):
33 return (cls, super().cm(), 'D')
34
35class E(D):
36 pass
37
38class F(E):
39 f = E.f
40
41class G(A):
42 pass
43
44
45class TestSuper(unittest.TestCase):
46
Benjamin Petersona29ac452013-05-17 11:33:26 -050047 def tearDown(self):
48 # This fixes the damage that test_various___class___pathologies does.
49 nonlocal __class__
50 __class__ = TestSuper
51
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050052 def test_basics_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000053 self.assertEqual(D().f(), 'ABCD')
54
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050055 def test_class_getattr_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000056 self.assertEqual(D.f(D()), 'ABCD')
57
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050058 def test_subclass_no_override_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000059 self.assertEqual(E().f(), 'ABCD')
60 self.assertEqual(E.f(E()), 'ABCD')
61
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050062 def test_unbound_method_transfer_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000063 self.assertEqual(F().f(), 'ABCD')
64 self.assertEqual(F.f(F()), 'ABCD')
65
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050066 def test_class_methods_still_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000067 self.assertEqual(A.cm(), (A, 'A'))
68 self.assertEqual(A().cm(), (A, 'A'))
69 self.assertEqual(G.cm(), (G, 'A'))
70 self.assertEqual(G().cm(), (G, 'A'))
71
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050072 def test_super_in_class_methods_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000073 d = D()
74 self.assertEqual(d.cm(), (d, (D, (D, (D, 'A'), 'B'), 'C'), 'D'))
75 e = E()
76 self.assertEqual(e.cm(), (e, (E, (E, (E, 'A'), 'B'), 'C'), 'D'))
77
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050078 def test_super_with_closure(self):
Barry Warsaw91cc8fb2008-11-20 20:01:57 +000079 # Issue4360: super() did not work in a function that
80 # contains a closure
81 class E(A):
82 def f(self):
83 def nested():
84 self
85 return super().f() + 'E'
86
87 self.assertEqual(E().f(), 'AE')
88
Benjamin Peterson312595c2013-05-15 15:26:42 -050089 def test_various___class___pathologies(self):
Benjamin Petersonf5ff2232011-06-19 19:42:22 -050090 # See issue #12370
91 class X(A):
92 def f(self):
93 return super().f()
94 __class__ = 413
95 x = X()
96 self.assertEqual(x.f(), 'A')
97 self.assertEqual(x.__class__, 413)
Benjamin Peterson312595c2013-05-15 15:26:42 -050098 class X:
99 x = __class__
100 def f():
101 __class__
102 self.assertIs(X.x, type(self))
103 with self.assertRaises(NameError) as e:
104 exec("""class X:
105 __class__
106 def f():
107 __class__""", globals(), {})
108 self.assertIs(type(e.exception), NameError) # Not UnboundLocalError
109 class X:
110 global __class__
111 __class__ = 42
112 def f():
113 __class__
114 self.assertEqual(globals()["__class__"], 42)
115 del globals()["__class__"]
116 self.assertNotIn("__class__", X.__dict__)
117 class X:
118 nonlocal __class__
119 __class__ = 42
120 def f():
121 __class__
122 self.assertEqual(__class__, 42)
Benjamin Petersonf5ff2232011-06-19 19:42:22 -0500123
Nick Coghlan0b43bcf2012-05-27 18:17:07 +1000124 def test___class___instancemethod(self):
125 # See issue #14857
126 class X:
127 def f(self):
128 return __class__
129 self.assertIs(X().f(), X)
130
131 def test___class___classmethod(self):
132 # See issue #14857
133 class X:
134 @classmethod
135 def f(cls):
136 return __class__
137 self.assertIs(X.f(), X)
138
139 def test___class___staticmethod(self):
140 # See issue #14857
141 class X:
142 @staticmethod
143 def f():
144 return __class__
145 self.assertIs(X.f(), X)
146
Nick Coghlan944368e2016-09-11 14:45:49 +1000147 def test___class___new(self):
Nick Coghlan19d24672016-12-05 16:47:55 +1000148 # See issue #23722
149 # Ensure zero-arg super() works as soon as type.__new__() is completed
Nick Coghlan944368e2016-09-11 14:45:49 +1000150 test_class = None
151
152 class Meta(type):
153 def __new__(cls, name, bases, namespace):
154 nonlocal test_class
155 self = super().__new__(cls, name, bases, namespace)
156 test_class = self.f()
157 return self
158
159 class A(metaclass=Meta):
160 @staticmethod
161 def f():
162 return __class__
163
164 self.assertIs(test_class, A)
165
166 def test___class___delayed(self):
Nick Coghlan19d24672016-12-05 16:47:55 +1000167 # See issue #23722
Nick Coghlan944368e2016-09-11 14:45:49 +1000168 test_namespace = None
169
170 class Meta(type):
171 def __new__(cls, name, bases, namespace):
172 nonlocal test_namespace
173 test_namespace = namespace
174 return None
175
Nick Coghlan19d24672016-12-05 16:47:55 +1000176 # This case shouldn't trigger the __classcell__ deprecation warning
177 with check_warnings() as w:
178 warnings.simplefilter("always", DeprecationWarning)
179 class A(metaclass=Meta):
180 @staticmethod
181 def f():
182 return __class__
183 self.assertEqual(w.warnings, [])
Nick Coghlan944368e2016-09-11 14:45:49 +1000184
185 self.assertIs(A, None)
186
187 B = type("B", (), test_namespace)
188 self.assertIs(B.f(), B)
189
190 def test___class___mro(self):
Nick Coghlan19d24672016-12-05 16:47:55 +1000191 # See issue #23722
Nick Coghlan944368e2016-09-11 14:45:49 +1000192 test_class = None
193
194 class Meta(type):
195 def mro(self):
196 # self.f() doesn't work yet...
197 self.__dict__["f"]()
198 return super().mro()
199
200 class A(metaclass=Meta):
201 def f():
202 nonlocal test_class
203 test_class = __class__
204
205 self.assertIs(test_class, A)
206
Nick Coghlan19d24672016-12-05 16:47:55 +1000207 def test___classcell___expected_behaviour(self):
208 # See issue #23722
Nick Coghlan944368e2016-09-11 14:45:49 +1000209 class Meta(type):
210 def __new__(cls, name, bases, namespace):
Nick Coghlan19d24672016-12-05 16:47:55 +1000211 nonlocal namespace_snapshot
212 namespace_snapshot = namespace.copy()
Nick Coghlan944368e2016-09-11 14:45:49 +1000213 return super().__new__(cls, name, bases, namespace)
214
Nick Coghlan19d24672016-12-05 16:47:55 +1000215 # __classcell__ is injected into the class namespace by the compiler
216 # when at least one method needs it, and should be omitted otherwise
217 namespace_snapshot = None
218 class WithoutClassRef(metaclass=Meta):
219 pass
220 self.assertNotIn("__classcell__", namespace_snapshot)
Nick Coghlan944368e2016-09-11 14:45:49 +1000221
Nick Coghlan19d24672016-12-05 16:47:55 +1000222 # With zero-arg super() or an explicit __class__ reference,
223 # __classcell__ is the exact cell reference to be populated by
224 # type.__new__
225 namespace_snapshot = None
226 class WithClassRef(metaclass=Meta):
227 def f(self):
228 return __class__
Nick Coghlan944368e2016-09-11 14:45:49 +1000229
Nick Coghlan19d24672016-12-05 16:47:55 +1000230 class_cell = namespace_snapshot["__classcell__"]
231 method_closure = WithClassRef.f.__closure__
232 self.assertEqual(len(method_closure), 1)
233 self.assertIs(class_cell, method_closure[0])
234 # Ensure the cell reference *doesn't* get turned into an attribute
235 with self.assertRaises(AttributeError):
236 WithClassRef.__classcell__
237
238 def test___classcell___missing(self):
239 # See issue #23722
240 # Some metaclasses may not pass the original namespace to type.__new__
241 # We test that case here by forcibly deleting __classcell__
Nick Coghlan944368e2016-09-11 14:45:49 +1000242 class Meta(type):
243 def __new__(cls, name, bases, namespace):
Nick Coghlan19d24672016-12-05 16:47:55 +1000244 namespace.pop('__classcell__', None)
Nick Coghlan944368e2016-09-11 14:45:49 +1000245 return super().__new__(cls, name, bases, namespace)
246
Nick Coghlan19d24672016-12-05 16:47:55 +1000247 # The default case should continue to work without any warnings
248 with check_warnings() as w:
249 warnings.simplefilter("always", DeprecationWarning)
250 class WithoutClassRef(metaclass=Meta):
251 pass
252 self.assertEqual(w.warnings, [])
Nick Coghlan944368e2016-09-11 14:45:49 +1000253
Nick Coghlan19d24672016-12-05 16:47:55 +1000254 # With zero-arg super() or an explicit __class__ reference, we expect
255 # __build_class__ to emit a DeprecationWarning complaining that
256 # __class__ was not set, and asking if __classcell__ was propagated
257 # to type.__new__.
258 # In Python 3.7, that warning will become a RuntimeError.
259 expected_warning = (
260 '__class__ not set.*__classcell__ propagated',
261 DeprecationWarning
262 )
263 with check_warnings(expected_warning):
264 warnings.simplefilter("always", DeprecationWarning)
265 class WithClassRef(metaclass=Meta):
266 def f(self):
267 return __class__
268 # Check __class__ still gets set despite the warning
269 self.assertIs(WithClassRef().f(), WithClassRef)
270
271 # Check the warning is turned into an error as expected
272 with warnings.catch_warnings():
273 warnings.simplefilter("error", DeprecationWarning)
274 with self.assertRaises(DeprecationWarning):
275 class WithClassRef(metaclass=Meta):
276 def f(self):
277 return __class__
278
279 def test___classcell___overwrite(self):
280 # See issue #23722
281 # Overwriting __classcell__ with nonsense is explicitly prohibited
282 class Meta(type):
283 def __new__(cls, name, bases, namespace, cell):
284 namespace['__classcell__'] = cell
285 return super().__new__(cls, name, bases, namespace)
286
287 for bad_cell in (None, 0, "", object()):
288 with self.subTest(bad_cell=bad_cell):
289 with self.assertRaises(TypeError):
290 class A(metaclass=Meta, cell=bad_cell):
291 pass
292
293 def test___classcell___wrong_cell(self):
294 # See issue #23722
295 # Pointing the cell reference at the wrong class is also prohibited
296 class Meta(type):
297 def __new__(cls, name, bases, namespace):
298 cls = super().__new__(cls, name, bases, namespace)
299 B = type("B", (), namespace)
300 return cls
301
302 with self.assertRaises(TypeError):
303 class A(metaclass=Meta):
304 def f(self):
305 return __class__
Nick Coghlan944368e2016-09-11 14:45:49 +1000306
Benjamin Peterson6a42bd62012-09-01 23:04:38 -0400307 def test_obscure_super_errors(self):
308 def f():
309 super()
310 self.assertRaises(RuntimeError, f)
311 def f(x):
312 del x
313 super()
314 self.assertRaises(RuntimeError, f, None)
315 class X:
316 def f(x):
317 nonlocal __class__
318 del __class__
319 super()
320 self.assertRaises(RuntimeError, X().f)
321
Benjamin Peterson159ae412013-05-12 18:16:06 -0500322 def test_cell_as_self(self):
323 class X:
324 def meth(self):
325 super()
326
327 def f():
328 k = X()
329 def g():
330 return k
331 return g
332 c = f().__closure__[0]
333 self.assertRaises(TypeError, X.meth, c)
334
Serhiy Storchaka3d749762016-04-13 15:27:33 +0300335 def test_super_init_leaks(self):
336 # Issue #26718: super.__init__ leaked memory if called multiple times.
337 # This will be caught by regrtest.py -R if this leak.
338 # NOTE: Despite the use in the test a direct call of super.__init__
339 # is not endorsed.
340 sp = super(float, 1.0)
341 for i in range(1000):
342 super.__init__(sp, int, i)
343
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000344
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000345if __name__ == "__main__":
346 unittest.main()