blob: 447dec9130fd96789586eae4c81b55e3867c5e3e [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
3import sys
4import unittest
Nick Coghlan19d24672016-12-05 16:47:55 +10005import warnings
6from test.support import check_warnings
Guido van Rossumcd16bf62007-06-13 18:07:49 +00007
8
9class A:
10 def f(self):
11 return 'A'
12 @classmethod
13 def cm(cls):
14 return (cls, 'A')
15
16class B(A):
17 def f(self):
18 return super().f() + 'B'
19 @classmethod
20 def cm(cls):
21 return (cls, super().cm(), 'B')
22
23class C(A):
24 def f(self):
25 return super().f() + 'C'
26 @classmethod
27 def cm(cls):
28 return (cls, super().cm(), 'C')
29
30class D(C, B):
31 def f(self):
32 return super().f() + 'D'
33 def cm(cls):
34 return (cls, super().cm(), 'D')
35
36class E(D):
37 pass
38
39class F(E):
40 f = E.f
41
42class G(A):
43 pass
44
45
46class TestSuper(unittest.TestCase):
47
Benjamin Petersona29ac452013-05-17 11:33:26 -050048 def tearDown(self):
49 # This fixes the damage that test_various___class___pathologies does.
50 nonlocal __class__
51 __class__ = TestSuper
52
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050053 def test_basics_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000054 self.assertEqual(D().f(), 'ABCD')
55
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050056 def test_class_getattr_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000057 self.assertEqual(D.f(D()), 'ABCD')
58
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050059 def test_subclass_no_override_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000060 self.assertEqual(E().f(), 'ABCD')
61 self.assertEqual(E.f(E()), 'ABCD')
62
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050063 def test_unbound_method_transfer_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000064 self.assertEqual(F().f(), 'ABCD')
65 self.assertEqual(F.f(F()), 'ABCD')
66
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050067 def test_class_methods_still_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000068 self.assertEqual(A.cm(), (A, 'A'))
69 self.assertEqual(A().cm(), (A, 'A'))
70 self.assertEqual(G.cm(), (G, 'A'))
71 self.assertEqual(G().cm(), (G, 'A'))
72
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050073 def test_super_in_class_methods_working(self):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000074 d = D()
75 self.assertEqual(d.cm(), (d, (D, (D, (D, 'A'), 'B'), 'C'), 'D'))
76 e = E()
77 self.assertEqual(e.cm(), (e, (E, (E, (E, 'A'), 'B'), 'C'), 'D'))
78
Benjamin Peterson206cd1c2011-06-19 17:49:13 -050079 def test_super_with_closure(self):
Barry Warsaw91cc8fb2008-11-20 20:01:57 +000080 # Issue4360: super() did not work in a function that
81 # contains a closure
82 class E(A):
83 def f(self):
84 def nested():
85 self
86 return super().f() + 'E'
87
88 self.assertEqual(E().f(), 'AE')
89
Benjamin Peterson312595c2013-05-15 15:26:42 -050090 def test_various___class___pathologies(self):
Benjamin Petersonf5ff2232011-06-19 19:42:22 -050091 # See issue #12370
92 class X(A):
93 def f(self):
94 return super().f()
95 __class__ = 413
96 x = X()
97 self.assertEqual(x.f(), 'A')
98 self.assertEqual(x.__class__, 413)
Benjamin Peterson312595c2013-05-15 15:26:42 -050099 class X:
100 x = __class__
101 def f():
102 __class__
103 self.assertIs(X.x, type(self))
104 with self.assertRaises(NameError) as e:
105 exec("""class X:
106 __class__
107 def f():
108 __class__""", globals(), {})
109 self.assertIs(type(e.exception), NameError) # Not UnboundLocalError
110 class X:
111 global __class__
112 __class__ = 42
113 def f():
114 __class__
115 self.assertEqual(globals()["__class__"], 42)
116 del globals()["__class__"]
117 self.assertNotIn("__class__", X.__dict__)
118 class X:
119 nonlocal __class__
120 __class__ = 42
121 def f():
122 __class__
123 self.assertEqual(__class__, 42)
Benjamin Petersonf5ff2232011-06-19 19:42:22 -0500124
Nick Coghlan0b43bcf2012-05-27 18:17:07 +1000125 def test___class___instancemethod(self):
126 # See issue #14857
127 class X:
128 def f(self):
129 return __class__
130 self.assertIs(X().f(), X)
131
132 def test___class___classmethod(self):
133 # See issue #14857
134 class X:
135 @classmethod
136 def f(cls):
137 return __class__
138 self.assertIs(X.f(), X)
139
140 def test___class___staticmethod(self):
141 # See issue #14857
142 class X:
143 @staticmethod
144 def f():
145 return __class__
146 self.assertIs(X.f(), X)
147
Nick Coghlan944368e2016-09-11 14:45:49 +1000148 def test___class___new(self):
Nick Coghlan19d24672016-12-05 16:47:55 +1000149 # See issue #23722
150 # Ensure zero-arg super() works as soon as type.__new__() is completed
Nick Coghlan944368e2016-09-11 14:45:49 +1000151 test_class = None
152
153 class Meta(type):
154 def __new__(cls, name, bases, namespace):
155 nonlocal test_class
156 self = super().__new__(cls, name, bases, namespace)
157 test_class = self.f()
158 return self
159
160 class A(metaclass=Meta):
161 @staticmethod
162 def f():
163 return __class__
164
165 self.assertIs(test_class, A)
166
167 def test___class___delayed(self):
Nick Coghlan19d24672016-12-05 16:47:55 +1000168 # See issue #23722
Nick Coghlan944368e2016-09-11 14:45:49 +1000169 test_namespace = None
170
171 class Meta(type):
172 def __new__(cls, name, bases, namespace):
173 nonlocal test_namespace
174 test_namespace = namespace
175 return None
176
Nick Coghlan19d24672016-12-05 16:47:55 +1000177 # This case shouldn't trigger the __classcell__ deprecation warning
178 with check_warnings() as w:
179 warnings.simplefilter("always", DeprecationWarning)
180 class A(metaclass=Meta):
181 @staticmethod
182 def f():
183 return __class__
184 self.assertEqual(w.warnings, [])
Nick Coghlan944368e2016-09-11 14:45:49 +1000185
186 self.assertIs(A, None)
187
188 B = type("B", (), test_namespace)
189 self.assertIs(B.f(), B)
190
191 def test___class___mro(self):
Nick Coghlan19d24672016-12-05 16:47:55 +1000192 # See issue #23722
Nick Coghlan944368e2016-09-11 14:45:49 +1000193 test_class = None
194
195 class Meta(type):
196 def mro(self):
197 # self.f() doesn't work yet...
198 self.__dict__["f"]()
199 return super().mro()
200
201 class A(metaclass=Meta):
202 def f():
203 nonlocal test_class
204 test_class = __class__
205
206 self.assertIs(test_class, A)
207
Nick Coghlan19d24672016-12-05 16:47:55 +1000208 def test___classcell___expected_behaviour(self):
209 # See issue #23722
Nick Coghlan944368e2016-09-11 14:45:49 +1000210 class Meta(type):
211 def __new__(cls, name, bases, namespace):
Nick Coghlan19d24672016-12-05 16:47:55 +1000212 nonlocal namespace_snapshot
213 namespace_snapshot = namespace.copy()
Nick Coghlan944368e2016-09-11 14:45:49 +1000214 return super().__new__(cls, name, bases, namespace)
215
Nick Coghlan19d24672016-12-05 16:47:55 +1000216 # __classcell__ is injected into the class namespace by the compiler
217 # when at least one method needs it, and should be omitted otherwise
218 namespace_snapshot = None
219 class WithoutClassRef(metaclass=Meta):
220 pass
221 self.assertNotIn("__classcell__", namespace_snapshot)
Nick Coghlan944368e2016-09-11 14:45:49 +1000222
Nick Coghlan19d24672016-12-05 16:47:55 +1000223 # With zero-arg super() or an explicit __class__ reference,
224 # __classcell__ is the exact cell reference to be populated by
225 # type.__new__
226 namespace_snapshot = None
227 class WithClassRef(metaclass=Meta):
228 def f(self):
229 return __class__
Nick Coghlan944368e2016-09-11 14:45:49 +1000230
Nick Coghlan19d24672016-12-05 16:47:55 +1000231 class_cell = namespace_snapshot["__classcell__"]
232 method_closure = WithClassRef.f.__closure__
233 self.assertEqual(len(method_closure), 1)
234 self.assertIs(class_cell, method_closure[0])
235 # Ensure the cell reference *doesn't* get turned into an attribute
236 with self.assertRaises(AttributeError):
237 WithClassRef.__classcell__
238
239 def test___classcell___missing(self):
240 # See issue #23722
241 # Some metaclasses may not pass the original namespace to type.__new__
242 # We test that case here by forcibly deleting __classcell__
Nick Coghlan944368e2016-09-11 14:45:49 +1000243 class Meta(type):
244 def __new__(cls, name, bases, namespace):
Nick Coghlan19d24672016-12-05 16:47:55 +1000245 namespace.pop('__classcell__', None)
Nick Coghlan944368e2016-09-11 14:45:49 +1000246 return super().__new__(cls, name, bases, namespace)
247
Nick Coghlan19d24672016-12-05 16:47:55 +1000248 # The default case should continue to work without any warnings
249 with check_warnings() as w:
250 warnings.simplefilter("always", DeprecationWarning)
251 class WithoutClassRef(metaclass=Meta):
252 pass
253 self.assertEqual(w.warnings, [])
Nick Coghlan944368e2016-09-11 14:45:49 +1000254
Nick Coghlan19d24672016-12-05 16:47:55 +1000255 # With zero-arg super() or an explicit __class__ reference, we expect
256 # __build_class__ to emit a DeprecationWarning complaining that
257 # __class__ was not set, and asking if __classcell__ was propagated
258 # to type.__new__.
259 # In Python 3.7, that warning will become a RuntimeError.
260 expected_warning = (
261 '__class__ not set.*__classcell__ propagated',
262 DeprecationWarning
263 )
264 with check_warnings(expected_warning):
265 warnings.simplefilter("always", DeprecationWarning)
266 class WithClassRef(metaclass=Meta):
267 def f(self):
268 return __class__
269 # Check __class__ still gets set despite the warning
270 self.assertIs(WithClassRef().f(), WithClassRef)
271
272 # Check the warning is turned into an error as expected
273 with warnings.catch_warnings():
274 warnings.simplefilter("error", DeprecationWarning)
275 with self.assertRaises(DeprecationWarning):
276 class WithClassRef(metaclass=Meta):
277 def f(self):
278 return __class__
279
280 def test___classcell___overwrite(self):
281 # See issue #23722
282 # Overwriting __classcell__ with nonsense is explicitly prohibited
283 class Meta(type):
284 def __new__(cls, name, bases, namespace, cell):
285 namespace['__classcell__'] = cell
286 return super().__new__(cls, name, bases, namespace)
287
288 for bad_cell in (None, 0, "", object()):
289 with self.subTest(bad_cell=bad_cell):
290 with self.assertRaises(TypeError):
291 class A(metaclass=Meta, cell=bad_cell):
292 pass
293
294 def test___classcell___wrong_cell(self):
295 # See issue #23722
296 # Pointing the cell reference at the wrong class is also prohibited
297 class Meta(type):
298 def __new__(cls, name, bases, namespace):
299 cls = super().__new__(cls, name, bases, namespace)
300 B = type("B", (), namespace)
301 return cls
302
303 with self.assertRaises(TypeError):
304 class A(metaclass=Meta):
305 def f(self):
306 return __class__
Nick Coghlan944368e2016-09-11 14:45:49 +1000307
Benjamin Peterson6a42bd62012-09-01 23:04:38 -0400308 def test_obscure_super_errors(self):
309 def f():
310 super()
311 self.assertRaises(RuntimeError, f)
312 def f(x):
313 del x
314 super()
315 self.assertRaises(RuntimeError, f, None)
316 class X:
317 def f(x):
318 nonlocal __class__
319 del __class__
320 super()
321 self.assertRaises(RuntimeError, X().f)
322
Benjamin Peterson159ae412013-05-12 18:16:06 -0500323 def test_cell_as_self(self):
324 class X:
325 def meth(self):
326 super()
327
328 def f():
329 k = X()
330 def g():
331 return k
332 return g
333 c = f().__closure__[0]
334 self.assertRaises(TypeError, X.meth, c)
335
Serhiy Storchaka3d749762016-04-13 15:27:33 +0300336 def test_super_init_leaks(self):
337 # Issue #26718: super.__init__ leaked memory if called multiple times.
338 # This will be caught by regrtest.py -R if this leak.
339 # NOTE: Despite the use in the test a direct call of super.__init__
340 # is not endorsed.
341 sp = super(float, 1.0)
342 for i in range(1000):
343 super.__init__(sp, int, i)
344
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000345
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000346if __name__ == "__main__":
347 unittest.main()