Hi there, I ran into an issue recently where ResourceWarnings weren't getting raised as errors as expected.
The unraisableexception plugin registers a config.add_cleanup() callback that forces 5 rounds of gc.collect() at session end to catch leaked resources. However, config.add_cleanup() pushes onto a contextlib.ExitStack (LIFO), and the warnings plugin registers its cleanup after unraisableexception in the default_plugins tuple. This means:
warnings cleanup runs first — tears down the catch_warnings context, removing filterwarnings = error::ResourceWarning from pytest.ini
unraisableexception cleanup runs second — calls gc.collect(), finalizing unclosed resources. Their __del__ methods emit ResourceWarning, but the error filter is gone. The warning is silently discarded and never reaches sys.unraisablehook.
Reproducible example here
Suggested fixes (either would work)
- Reorder
default_plugins: Swap unraisableexception and warnings so that unraisableexception's cleanup (including gc.collect()) runs while warning filters are still active.
- Move the GC logic to
pytest_unconfigure: pytest_unconfigure runs before _cleanup_stack.close(), so both warning filters and sys.unraisablehook are still wired up at that point. This avoids depending on registration order entirely.