Skip to content

Conversation

@lysnikolaou
Copy link
Member

@ngoldbaum We can get this into 0.6 as well.

Only problem is I don't really know how to test this. I checked manually with a custom package with a compiled extension and the test suite indeed failed.

if self.warn_gil_enabled:
warnings.warn(GIL_ENABLED_ERROR_TEXT)
else:
pytest.exit(GIL_ENABLED_ERROR_TEXT, returncode=1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will work, but I have a slightly different approach I was thinking about today.

What do you think about instead of checking at the end of the session, we check after collection is finished and then check after every individual test. If it fails during collection, we say "GIL re-enabled during collection", if it's re-enabled in a test we say "GIL re-enabled during execution of test_foo". That way people get an indication exactly when the GIL is re-enabled.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that makes sense to me as well. I was thinking the warning, that indicates what the module that enabled the GIL was, would be enough but that's lost in the case of a pytest.exit. Let me try to do that in this PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit more complicated than I initially thought. I'll work on it tomorrow and hopefully do a 0.6 release as well.

@ngoldbaum
Copy link
Collaborator

Only problem is I don't really know how to test this.

I think you'd need to create a tiny C extension with e.g. meson and then import it in a test. Seems like a lot of complexity - totally fine with me to punt on testing that for now.

@lysnikolaou
Copy link
Member Author

@ngoldbaum This is realy for another review. What do you think of this approach? It fails early during collection or execution phase.

Collection:

❯ pytest                     
======================================================== test session starts ========================================================
platform darwin -- Python 3.13.5, pytest-8.4.1, pluggy-1.6.0
rootdir: /Users/lysnikolaou/repos/quansight/pytest-run-parallel-test
configfile: pyproject.toml
plugins: run-parallel-0.5.1.dev0
collected 1 item                                                                                                                    
Collected 0 items to run in parallel

======================================================= no tests ran in 0.82s =======================================================
! _pytest.outcomes.Exit: GIL was dynamically re-enabled during test collection to load module 'pkg.t'. When running under a free-threaded interpreter with the GIL initially disabled, the test suite must not cause the GIL to be re-enabled at runtime. Check for compiled extension modules that do not use the 'Py_mod_gil' slot or the 'PyUnstable_Module_SetGIL' API. !

❯ pytest --ignore-gil-enabled
======================================================== test session starts ========================================================
platform darwin -- Python 3.13.5, pytest-8.4.1, pluggy-1.6.0
rootdir: /Users/lysnikolaou/repos/quansight/pytest-run-parallel-test
configfile: pyproject.toml
plugins: run-parallel-0.5.1.dev0
collected 1 item                                                                                                                    
Collected 0 items to run in parallel

tests/test_t.py .                                                                                                             [100%]

========================================================= warnings summary ==========================================================
<frozen importlib._bootstrap>:488
  <frozen importlib._bootstrap>:488: RuntimeWarning: The global interpreter lock (GIL) has been enabled to load module 'pkg.t', which has not declared that it can run safely without the GIL. To override this behavior and keep the GIL disabled (at your own risk), run with PYTHON_GIL=0 or -Xgil=0.

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=================================================== 1 passed, 1 warning in 0.14s ====================================================

Execution:

❯ pytest                                      
======================================================== test session starts ========================================================
platform darwin -- Python 3.13.5, pytest-8.4.1, pluggy-1.6.0
rootdir: /Users/lysnikolaou/repos/quansight/pytest-run-parallel-test
configfile: pyproject.toml
plugins: run-parallel-0.5.1.dev0
collected 1 item                                                                                                                    
Collected 0 items to run in parallel

tests/test_t.py .

========================================================= 1 passed in 1.18s =========================================================
! _pytest.outcomes.Exit: GIL was dynamically re-enabled during test execution of 'tests/test_t.py::test_number' to load module 'pkg.t'. When running under a free-threaded interpreter with the GIL initially disabled, the test suite must not cause the GIL to be re-enabled at runtime. Check for compiled extension modules that do not use the 'Py_mod_gil' slot or the 'PyUnstable_Module_SetGIL' API. !

❯ pytest --ignore-gil-enabled
======================================================== test session starts ========================================================
platform darwin -- Python 3.13.5, pytest-8.4.1, pluggy-1.6.0
rootdir: /Users/lysnikolaou/repos/quansight/pytest-run-parallel-test
configfile: pyproject.toml
plugins: run-parallel-0.5.1.dev0
collected 1 item                                                                                                                    
Collected 0 items to run in parallel

tests/test_t.py .                                                                                                             [100%]

========================================================= warnings summary ==========================================================
tests/test_t.py::test_number
  <frozen importlib._bootstrap>:488: RuntimeWarning: The global interpreter lock (GIL) has been enabled to load module 'pkg.t', which has not declared that it can run safely without the GIL. To override this behavior and keep the GIL disabled (at your own risk), run with PYTHON_GIL=0 or -Xgil=0.

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=================================================== 1 passed, 1 warning in 0.13s ====================================================

@lysnikolaou lysnikolaou force-pushed the warn-if-gil-enabled branch from 912f8c9 to c0a5a49 Compare July 25, 2025 18:17
@lysnikolaou lysnikolaou force-pushed the warn-if-gil-enabled branch from c0a5a49 to c63cd26 Compare July 25, 2025 18:25
Copy link
Collaborator

@ngoldbaum ngoldbaum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, let's ship it. I might poke at adding tests with a real extension if we ever have issues with this but your mocking with a warning that you raise yourself in a test is probably more than sufficient.

)

GIL_WARNING_MESSAGE_CONTENT = re.compile(
r"The global interpreter lock \(GIL\) has been enabled to load module '(?P<module>[^']*)'"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gemini gave me this explanation for (?P<module>[^']*):

Capture any sequence of zero or more characters that are not a single quote, and name this captured group 'module'.

There might be a better way to do that but this also seems to work... I kind of hate regexes...

@ngoldbaum ngoldbaum merged commit 13b4544 into Quansight-Labs:main Jul 25, 2025
10 checks passed
@lysnikolaou lysnikolaou deleted the warn-if-gil-enabled branch September 25, 2025 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants