Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Doc/library/test.rst
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,12 @@ The :mod:`test.support` module defines the following functions:
macOS version is less than the minimum, the test is skipped.


.. decorator:: requires_gil_enabled

Decorator for skipping tests on the free-threaded build. If the
:term:`GIL` is disabled, the test is skipped.


.. decorator:: requires_IEEE_754

Decorator for skipping tests on non-IEEE 754 platforms.
Expand Down
7 changes: 6 additions & 1 deletion Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"captured_stdin", "captured_stderr",
# unittest
"is_resource_enabled", "requires", "requires_freebsd_version",
"requires_linux_version", "requires_mac_ver",
"requires_gil_enabled", "requires_linux_version", "requires_mac_ver",
"check_syntax_error",
"requires_gzip", "requires_bz2", "requires_lzma",
"bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
Expand Down Expand Up @@ -837,6 +837,11 @@ def check_cflags_pgo():


Py_GIL_DISABLED = bool(sysconfig.get_config_var('Py_GIL_DISABLED'))

def requires_gil_enabled(msg="needs the GIL enabled"):
"""Decorator for skipping tests on the free-threaded build."""
return unittest.skipIf(Py_GIL_DISABLED, msg)

if Py_GIL_DISABLED:
_header = 'PHBBInP'
else:
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_capi/test_mem.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ class C(): pass
self.assertGreaterEqual(count, i*10-4)


# Py_GIL_DISABLED requires mimalloc (not malloc)
@unittest.skipIf(support.Py_GIL_DISABLED, 'need malloc')
# free-threading requires mimalloc (not malloc)
@support.requires_gil_enabled
class PyMemMallocDebugTests(PyMemDebugTests):
PYTHONMALLOC = 'malloc_debug'

Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_cext/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ def test_build_c11(self):
def test_build_c99(self):
self.check_build('_test_c99_cext', std='c99')

@unittest.skipIf(support.Py_GIL_DISABLED, 'incompatible with Free Threading')
@support.requires_gil_enabled('incompatible with Free Threading')
def test_build_limited(self):
self.check_build('_test_limited_cext', limited=True)

@unittest.skipIf(support.Py_GIL_DISABLED, 'broken for now with Free Threading')
@support.requires_gil_enabled('broken for now with Free Threading')
def test_build_limited_c11(self):
self.check_build('_test_limited_c11_cext', limited=True, std='c11')

Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_concurrent_futures/test_process_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def test_saturation(self):
for _ in range(job_count):
sem.release()

@unittest.skipIf(support.Py_GIL_DISABLED, "gh-117344: test is flaky without the GIL")
@support.requires_gil_enabled("gh-117344: test is flaky without the GIL")
def test_idle_process_reuse_one(self):
executor = self.executor
assert executor._max_workers >= 4
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_concurrent_futures/test_thread_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def acquire_lock(lock):
sem.release()
executor.shutdown(wait=True)

@unittest.skipIf(support.Py_GIL_DISABLED, "gh-117344: test is flaky without the GIL")
@support.requires_gil_enabled("gh-117344: test is flaky without the GIL")
def test_idle_thread_reuse(self):
executor = self.executor_type()
executor.submit(mul, 21, 2).result()
Expand Down
9 changes: 5 additions & 4 deletions Lib/test/test_gc.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import unittest
import unittest.mock
from test.support import (verbose, refcount_test,
cpython_only, requires_subprocess, Py_GIL_DISABLED)
cpython_only, requires_subprocess,
requires_gil_enabled)
from test.support.import_helper import import_module
from test.support.os_helper import temp_dir, TESTFN, unlink
from test.support.script_helper import assert_python_ok, make_script
Expand Down Expand Up @@ -363,7 +364,7 @@ def __del__(self):
# To minimize variations, though, we first store the get_count() results
# and check them at the end.
@refcount_test
@unittest.skipIf(Py_GIL_DISABLED, 'needs precise allocation counts')
@requires_gil_enabled('needs precise allocation counts')
def test_get_count(self):
gc.collect()
a, b, c = gc.get_count()
Expand Down Expand Up @@ -815,7 +816,7 @@ def test_get_objects(self):
any(l is element for element in gc.get_objects())
)

@unittest.skipIf(Py_GIL_DISABLED, 'need generational GC')
@requires_gil_enabled('need generational GC')
def test_get_objects_generations(self):
gc.collect()
l = []
Expand Down Expand Up @@ -1046,7 +1047,7 @@ def setUp(self):
def tearDown(self):
gc.disable()

@unittest.skipIf(Py_GIL_DISABLED, "Free threading does not support incremental GC")
@requires_gil_enabled("Free threading does not support incremental GC")
# Use small increments to emulate longer running process in a shorter time
@gc_threshold(200, 10)
def test_incremental_gc_handles_fast_cycle_creation(self):
Expand Down