Skip to content

Commit 1670f97

Browse files
Support marking modules.
1 parent 9aad8b0 commit 1670f97

4 files changed

Lines changed: 45 additions & 12 deletions

File tree

Lib/test/support/__init__.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,9 @@ def is_resource_enabled(resource):
302302

303303
def requires(resource, msg=None):
304304
"""Raise ResourceDenied if the specified resource is not available."""
305+
f = sys._getframe(1)
306+
if f.f_globals is f.f_locals:
307+
mark(f'requires_{resource}', globals=f.f_globals)
305308
if not is_resource_enabled(resource):
306309
if msg is None:
307310
msg = "Use of the %r resource not enabled" % resource
@@ -536,22 +539,27 @@ def requires_fork():
536539

537540
def requires_subprocess():
538541
"""Used for subprocess, os.spawn calls, fd inheritance"""
539-
return skipUnless(has_subprocess_support, "requires subprocess support", label='requires_subprocess')
542+
return skipUnless(has_subprocess_support, "requires subprocess support",
543+
label='requires_subprocess')
540544

541545
# Emscripten's socket emulation and WASI sockets have limitations.
542546
has_socket_support = not is_emscripten and not is_wasi
543547

544-
def requires_working_socket(*, module=False):
548+
def requires_working_socket(*, module=False, globals=None):
545549
"""Skip tests or modules that require working sockets
546550
547551
Can be used as a function/class decorator or to skip an entire module.
548552
"""
553+
label = 'requires_socket'
549554
msg = "requires socket support"
550-
if module:
555+
if module or globals is not None:
556+
if globals is None:
557+
globals = sys._getframe(1).f_globals
558+
mark(label, globals=globals)
551559
if not has_socket_support:
552560
raise unittest.SkipTest(msg)
553561
else:
554-
return skipUnless(has_socket_support, msg, label='requires_socket')
562+
return skipUnless(has_socket_support, msg, label=label)
555563

556564
# Does strftime() support glibc extension like '%4Y'?
557565
has_strftime_extensions = False
@@ -1008,9 +1016,18 @@ def wrapper(self):
10081016
#=======================================================================
10091017
# unittest integration.
10101018

1011-
def mark(label):
1019+
def mark(label, *, globals=None):
1020+
"""Add a label to test.
1021+
1022+
To add a label to method or class, use it as a decorator.
1023+
1024+
To add a label to module, pass the globals() dict as the globals argument.
1025+
"""
1026+
if globals is not None:
1027+
globals[f'_label_{label}'] = True
1028+
return
10121029
def decorator(test):
1013-
setattr(test, label, True)
1030+
setattr(test, f'_label_{label}', True)
10141031
return test
10151032
return decorator
10161033

@@ -1028,11 +1045,12 @@ def skipIf(condition, reason, *, label):
10281045
return combine(unittest.skipIf(condition, reason), mark(label))
10291046

10301047
def requires_resource(resource):
1048+
label = 'requires_' + resource
10311049
if resource == 'gui' and not _is_gui_available():
1032-
return skipUnless(False, _is_gui_available.reason, label='requires_gui')
1050+
return skipUnless(False, _is_gui_available.reason, label=label)
10331051
return skipUnless(is_resource_enabled(resource),
10341052
f"resource {resource!r} is not enabled",
1035-
label='requires_' + resource)
1053+
label=label)
10361054

10371055
def cpython_only(test):
10381056
"""
@@ -1218,7 +1236,7 @@ def match_function(test_id):
12181236

12191237
def _check_obj_labels(obj, labels):
12201238
for label in labels:
1221-
if hasattr(obj, label):
1239+
if hasattr(obj, f'_label_{label}'):
12221240
return True
12231241
return False
12241242

@@ -1230,6 +1248,12 @@ def _check_test_labels(test, labels):
12301248
if _check_obj_labels(testMethod, labels):
12311249
return True
12321250
testMethod = getattr(testMethod, '__wrapped__', None)
1251+
try:
1252+
module = sys.modules[test.__class__.__module__]
1253+
if _check_obj_labels(module, labels):
1254+
return True
1255+
except KeyError:
1256+
pass
12331257
return False
12341258

12351259
def set_match_tests2(accept_labels=None, ignore_labels=None):

Lib/test/support/import_helper.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import unittest
99
import warnings
1010

11+
from .. import support
1112
from .os_helper import unlink
1213

1314

@@ -74,6 +75,9 @@ def import_module(name, deprecated=False, *, required_on=()):
7475
compared against sys.platform.
7576
"""
7677
with _ignore_deprecated_imports(deprecated):
78+
f = sys._getframe(1)
79+
if f.f_globals is f.f_locals:
80+
support.mark(f'requires_{name}', globals=f.f_globals)
7781
try:
7882
return importlib.import_module(name)
7983
except ImportError as msg:

Lib/test/support/socket_helper.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ def _is_ipv6_enabled():
146146
_bind_nix_socket_error = None
147147
def skip_unless_bind_unix_socket(test):
148148
"""Decorator for tests requiring a functional bind() for unix sockets."""
149+
test = support.mark('requires_unix_sockets')(test)
149150
if not hasattr(socket, 'AF_UNIX'):
150151
return unittest.skip('No UNIX Sockets')(test)
151152
global _bind_nix_socket_error

Lib/test/support/threading_helper.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,18 @@ def _can_start_thread() -> bool:
234234

235235
can_start_thread = _can_start_thread()
236236

237-
def requires_working_threading(*, module=False):
237+
def requires_working_threading(*, module=False, globals=None):
238238
"""Skip tests or modules that require working threading.
239239
240240
Can be used as a function/class decorator or to skip an entire module.
241241
"""
242+
label = 'requires_threading'
242243
msg = "requires threading support"
243-
if module:
244+
if module or globals is not None:
245+
if globals is None:
246+
globals = sys._getframe(1).f_globals
247+
support.mark(label, globals=globals)
244248
if not can_start_thread:
245249
raise unittest.SkipTest(msg)
246250
else:
247-
return unittest.skipUnless(can_start_thread, msg)
251+
return support.skipUnless(can_start_thread, msg, label=label)

0 commit comments

Comments
 (0)