Skip to content

Commit 6198a35

Browse files
committed
gh-119659: Fix support.no_rerun decorator
1 parent 0518edc commit 6198a35

File tree

4 files changed

+33
-11
lines changed

4 files changed

+33
-11
lines changed

Lib/test/libregrtest/refleak.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ def get_pooled_int(value):
173173
interned_before = interned_after
174174

175175
restore_support_xml(xml_filename)
176+
refleak_helper._refleak_iteration += 1
177+
refleak_helper._refleak_iteration = 0
176178

177179
if not quiet:
178180
print(file=sys.stderr)

Lib/test/support/__init__.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,16 +1196,28 @@ def no_rerun(reason):
11961196
impossible to find reference leaks. Provide a clear reason for skipping the
11971197
test using the 'reason' parameter.
11981198
"""
1199-
def deco(func):
1200-
_has_run = False
1201-
def wrapper(self):
1202-
nonlocal _has_run
1203-
if _has_run:
1204-
self.skipTest(reason)
1205-
func(self)
1206-
_has_run = True
1199+
def decorator(func_or_class):
1200+
if isinstance(func_or_class, type):
1201+
setUpClass = func_or_class.__dict__.get('setUpClass')
1202+
if setUpClass is None:
1203+
def setUpClass(cls):
1204+
super(func_or_class, cls).setUpClass()
1205+
setUpClass.__qualname__ = func_or_class.__qualname__ + '.setUpClass'
1206+
setUpClass.__module__ = func_or_class.__module__
1207+
else:
1208+
setUpClass = setUpClass.__func__
1209+
setUpClass = classmethod(decorator(setUpClass))
1210+
func_or_class.setUpClass = setUpClass
1211+
return func_or_class
1212+
1213+
@functools.wraps(func_or_class)
1214+
def wrapper(*args, **kwargs):
1215+
from test.support import refleak_helper
1216+
if refleak_helper._refleak_iteration > 0:
1217+
raise unittest.SkipTest(reason)
1218+
return func_or_class(*args, **kwargs)
12071219
return wrapper
1208-
return deco
1220+
return decorator
12091221

12101222

12111223
def refcount_test(test):

Lib/test/support/refleak_helper.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66
_hunting_for_refleaks = False
77
def hunting_for_refleaks():
88
return _hunting_for_refleaks
9+
10+
_refleak_iteration = 0

Lib/test/test_datetime.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,22 @@ def load_tests(loader, tests, pattern):
3939
for cls in test_classes:
4040
cls.__name__ += suffix
4141
cls.__qualname__ += suffix
42+
orig_setUpClass = getattr(cls, 'setUpClass', None)
43+
orig_tearDownClass = getattr(cls, 'tearDownClass', None)
4244
@classmethod
43-
def setUpClass(cls_, module=module):
45+
def setUpClass(cls_, module=module, orig_setUpClass=orig_setUpClass):
4446
cls_._save_sys_modules = sys.modules.copy()
4547
sys.modules[TESTS] = module
4648
sys.modules['datetime'] = module.datetime_module
4749
if hasattr(module, '_pydatetime'):
4850
sys.modules['_pydatetime'] = module._pydatetime
4951
sys.modules['_strptime'] = module._strptime
52+
if orig_setUpClass is not None:
53+
orig_setUpClass()
5054
@classmethod
51-
def tearDownClass(cls_):
55+
def tearDownClass(cls_, orig_tearDownClass=orig_tearDownClass):
56+
if orig_tearDownClass is not None:
57+
orig_tearDownClass()
5258
sys.modules.clear()
5359
sys.modules.update(cls_._save_sys_modules)
5460
cls.setUpClass = setUpClass

0 commit comments

Comments
 (0)