Skip to content

Commit c2ea003

Browse files
committed
Update test_super.py from 3.13.9
1 parent 92a0cea commit c2ea003

File tree

2 files changed

+291
-48
lines changed

2 files changed

+291
-48
lines changed

Lib/test/test_super.py

Lines changed: 268 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
"""Unit tests for zero-argument super() & related machinery."""
22

3+
import textwrap
4+
import threading
35
import unittest
6+
from unittest.mock import patch
7+
from test.support import import_helper, threading_helper
8+
9+
10+
ADAPTIVE_WARMUP_DELAY = 2
411

512

613
class A:
@@ -84,41 +91,43 @@ def nested():
8491

8592
self.assertEqual(E().f(), 'AE')
8693

87-
# SyntaxError
88-
# def test_various___class___pathologies(self):
89-
# # See issue #12370
90-
# class X(A):
91-
# def f(self):
92-
# return super().f()
93-
# __class__ = 413
94-
# x = X()
95-
# self.assertEqual(x.f(), 'A')
96-
# self.assertEqual(x.__class__, 413)
97-
# class X:
98-
# x = __class__
99-
# def f():
100-
# __class__
101-
# self.assertIs(X.x, type(self))
102-
# with self.assertRaises(NameError) as e:
103-
# exec("""class X:
104-
# __class__
105-
# def f():
106-
# __class__""", globals(), {})
107-
# self.assertIs(type(e.exception), NameError) # Not UnboundLocalError
108-
# class X:
109-
# global __class__
110-
# __class__ = 42
111-
# def f():
112-
# __class__
113-
# self.assertEqual(globals()["__class__"], 42)
114-
# del globals()["__class__"]
115-
# self.assertNotIn("__class__", X.__dict__)
116-
# class X:
117-
# nonlocal __class__
118-
# __class__ = 42
119-
# def f():
120-
# __class__
121-
# self.assertEqual(__class__, 42)
94+
# TODO: RUSTPYTHON; SyntaxError: name '__class__' is assigned to before global declaration
95+
'''
96+
def test_various___class___pathologies(self):
97+
# See issue #12370
98+
class X(A):
99+
def f(self):
100+
return super().f()
101+
__class__ = 413
102+
x = X()
103+
self.assertEqual(x.f(), 'A')
104+
self.assertEqual(x.__class__, 413)
105+
class X:
106+
x = __class__
107+
def f():
108+
__class__
109+
self.assertIs(X.x, type(self))
110+
with self.assertRaises(NameError) as e:
111+
exec("""class X:
112+
__class__
113+
def f():
114+
__class__""", globals(), {})
115+
self.assertIs(type(e.exception), NameError) # Not UnboundLocalError
116+
class X:
117+
global __class__
118+
__class__ = 42
119+
def f():
120+
__class__
121+
self.assertEqual(globals()["__class__"], 42)
122+
del globals()["__class__"]
123+
self.assertNotIn("__class__", X.__dict__)
124+
class X:
125+
nonlocal __class__
126+
__class__ = 42
127+
def f():
128+
__class__
129+
self.assertEqual(__class__, 42)
130+
'''
122131

123132
def test___class___instancemethod(self):
124133
# See issue #14857
@@ -182,8 +191,7 @@ def f():
182191
B = type("B", (), test_namespace)
183192
self.assertIs(B.f(), B)
184193

185-
# TODO: RUSTPYTHON
186-
@unittest.expectedFailure
194+
@unittest.expectedFailure # TODO: RUSTPYTHON
187195
def test___class___mro(self):
188196
# See issue #23722
189197
test_class = None
@@ -201,8 +209,7 @@ def f():
201209

202210
self.assertIs(test_class, A)
203211

204-
# TODO: RUSTPYTHON
205-
@unittest.expectedFailure
212+
@unittest.expectedFailure # TODO: RUSTPYTHON
206213
def test___classcell___expected_behaviour(self):
207214
# See issue #23722
208215
class Meta(type):
@@ -288,17 +295,28 @@ def f(self):
288295
def test_obscure_super_errors(self):
289296
def f():
290297
super()
291-
self.assertRaises(RuntimeError, f)
298+
with self.assertRaisesRegex(RuntimeError, r"no arguments"):
299+
f()
300+
301+
class C:
302+
def f():
303+
super()
304+
with self.assertRaisesRegex(RuntimeError, r"no arguments"):
305+
C.f()
306+
292307
def f(x):
293308
del x
294309
super()
295-
self.assertRaises(RuntimeError, f, None)
310+
with self.assertRaisesRegex(RuntimeError, r"arg\[0\] deleted"):
311+
f(None)
312+
296313
class X:
297314
def f(x):
298315
nonlocal __class__
299316
del __class__
300317
super()
301-
self.assertRaises(RuntimeError, X().f)
318+
with self.assertRaisesRegex(RuntimeError, r"empty __class__ cell"):
319+
X().f()
302320

303321
def test_cell_as_self(self):
304322
class X:
@@ -322,6 +340,214 @@ def test_super_init_leaks(self):
322340
for i in range(1000):
323341
super.__init__(sp, int, i)
324342

343+
def test_super_argcount(self):
344+
with self.assertRaisesRegex(TypeError, "expected at most"):
345+
super(int, int, int)
346+
347+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: "argument 1 must be a type" does not match "Expected type 'type' but 'int' found."
348+
def test_super_argtype(self):
349+
with self.assertRaisesRegex(TypeError, "argument 1 must be a type"):
350+
super(1, int)
351+
352+
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: module 'test.support.import_helper' has no attribute 'ready_to_import'
353+
def test_shadowed_global(self):
354+
source = textwrap.dedent(
355+
"""
356+
class super:
357+
msg = "truly super"
358+
359+
class C:
360+
def method(self):
361+
return super().msg
362+
""",
363+
)
364+
with import_helper.ready_to_import(name="shadowed_super", source=source):
365+
import shadowed_super
366+
self.assertEqual(shadowed_super.C().method(), "truly super")
367+
import_helper.unload("shadowed_super")
368+
369+
def test_shadowed_local(self):
370+
class super:
371+
msg = "quite super"
372+
373+
class C:
374+
def method(self):
375+
return super().msg
376+
377+
self.assertEqual(C().method(), "quite super")
378+
379+
def test_shadowed_dynamic(self):
380+
class MySuper:
381+
msg = "super super"
382+
383+
class C:
384+
def method(self):
385+
return super().msg
386+
387+
with patch(f"{__name__}.super", MySuper) as m:
388+
self.assertEqual(C().method(), "super super")
389+
390+
def test_shadowed_dynamic_two_arg(self):
391+
call_args = []
392+
class MySuper:
393+
def __init__(self, *args):
394+
call_args.append(args)
395+
msg = "super super"
396+
397+
class C:
398+
def method(self):
399+
return super(1, 2).msg
400+
401+
with patch(f"{__name__}.super", MySuper) as m:
402+
self.assertEqual(C().method(), "super super")
403+
self.assertEqual(call_args, [(1, 2)])
404+
405+
def test_attribute_error(self):
406+
class C:
407+
def method(self):
408+
return super().msg
409+
410+
with self.assertRaisesRegex(AttributeError, "'super' object has no attribute 'msg'"):
411+
C().method()
412+
413+
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: "argument 1 must be a type" does not match "Expected type 'type' but 'int' found."
414+
def test_bad_first_arg(self):
415+
class C:
416+
def method(self):
417+
return super(1, self).method()
418+
419+
with self.assertRaisesRegex(TypeError, "argument 1 must be a type"):
420+
C().method()
421+
422+
def test_supercheck_fail(self):
423+
class C:
424+
def method(self, type_, obj):
425+
return super(type_, obj).method()
426+
427+
c = C()
428+
err_msg = (
429+
r"super\(type, obj\): obj \({} {}\) is not "
430+
r"an instance or subtype of type \({}\)."
431+
)
432+
433+
cases = (
434+
(int, c, int.__name__, C.__name__, "instance of"),
435+
# obj is instance of type
436+
(C, list(), C.__name__, list.__name__, "instance of"),
437+
# obj is type itself
438+
(C, list, C.__name__, list.__name__, "type"),
439+
)
440+
441+
for case in cases:
442+
with self.subTest(case=case):
443+
type_, obj, type_str, obj_str, instance_or_type = case
444+
regex = err_msg.format(instance_or_type, obj_str, type_str)
445+
446+
with self.assertRaisesRegex(TypeError, regex):
447+
c.method(type_, obj)
448+
449+
def test_super___class__(self):
450+
class C:
451+
def method(self):
452+
return super().__class__
453+
454+
self.assertEqual(C().method(), super)
455+
456+
@unittest.expectedFailure # TODO: RUSTPYTHON; TypeError: type 'super' is not an acceptable base type
457+
def test_super_subclass___class__(self):
458+
class mysuper(super):
459+
pass
460+
461+
class C:
462+
def method(self):
463+
return mysuper(C, self).__class__
464+
465+
self.assertEqual(C().method(), mysuper)
466+
467+
def test_unusual_getattro(self):
468+
class MyType(type):
469+
pass
470+
471+
def test(name):
472+
mytype = MyType(name, (MyType,), {})
473+
super(MyType, type(mytype)).__setattr__(mytype, "bar", 1)
474+
self.assertEqual(mytype.bar, 1)
475+
476+
for _ in range(ADAPTIVE_WARMUP_DELAY):
477+
test("foo1")
478+
479+
def test_reassigned_new(self):
480+
class A:
481+
def __new__(cls):
482+
pass
483+
484+
def __init_subclass__(cls):
485+
if "__new__" not in cls.__dict__:
486+
cls.__new__ = cls.__new__
487+
488+
class B(A):
489+
pass
490+
491+
class C(B):
492+
def __new__(cls):
493+
return super().__new__(cls)
494+
495+
for _ in range(ADAPTIVE_WARMUP_DELAY):
496+
C()
497+
498+
def test_mixed_staticmethod_hierarchy(self):
499+
# This test is just a desugared version of `test_reassigned_new`
500+
class A:
501+
@staticmethod
502+
def some(cls, *args, **kwargs):
503+
self.assertFalse(args)
504+
self.assertFalse(kwargs)
505+
506+
class B(A):
507+
def some(cls, *args, **kwargs):
508+
return super().some(cls, *args, **kwargs)
509+
510+
class C(B):
511+
@staticmethod
512+
def some(cls):
513+
return super().some(cls)
514+
515+
for _ in range(ADAPTIVE_WARMUP_DELAY):
516+
C.some(C)
517+
518+
@threading_helper.requires_working_threading()
519+
def test___class___modification_multithreaded(self):
520+
""" Note: this test isn't actually testing anything on its own.
521+
It requires a sys audithook to be set to crash on older Python.
522+
This should be the case anyways as our test suite sets
523+
an audit hook.
524+
"""
525+
526+
class Foo:
527+
pass
528+
529+
class Bar:
530+
pass
531+
532+
thing = Foo()
533+
def work():
534+
foo = thing
535+
for _ in range(200):
536+
foo.__class__ = Bar
537+
type(foo)
538+
foo.__class__ = Foo
539+
type(foo)
540+
541+
542+
threads = []
543+
for _ in range(6):
544+
thread = threading.Thread(target=work)
545+
thread.start()
546+
threads.append(thread)
547+
548+
for thread in threads:
549+
thread.join()
550+
325551

326552
if __name__ == "__main__":
327553
unittest.main()

0 commit comments

Comments
 (0)