ยปCore Development>Code coverage>Lib/test/test_super.py

# Python code coverage for Lib/test/test_super.py

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