python: propagate package-level pytestmark from __init__.py - #14917
Closed
aryansk wants to merge 1 commit into
Closed
python: propagate package-level pytestmark from __init__.py#14917aryansk wants to merge 1 commit into
aryansk wants to merge 1 commit into
Conversation
Package collectors lost pytestmark propagation when Package stopped being a Module/File in pytest-dev#6197 (fix for pytest-dev#6194). The previous fix removed the Module-style own_markers handling without replacing it, so a pytestmark = pytest.mark.skip(...) in a package __init__.py no longer applied to tests in that package. Restore the behaviour without re-collecting __init__.py as a test file: in Package.collect, import the package's __init__.py via importtestmodule, extract marks with get_unpacked_marks, and extend own_markers / keywords before yielding children. Children inherit via Node.iter_markers_with_node. Do this in collect (not setup) so marks are visible before pytest_runtest_setup (skipping is tryfirst). Snapshot and restore sys.modules / sys.path when no marks are found to avoid polluting unrelated imports (test_does_not_put_src_on_path). Fixes pytest-dev#14737
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A
pytestmark = pytest.mark.skip(...)(orxfail, etc.) defined in a package's__init__.pyno longer propagates to tests inside that package. Tests that should be skipped run and fail instead.Minimal reproduction from #14737:
This is a consequence of #6197. Before #6197,
Packagewas aModuleand its__init__.pywas loaded viaPyobjMixin.objwhich populatedown_markersviaget_unpacked_marks. #6197 madePackageaDirectoryto fix incorrect discovery of non-test__init__.pyfiles (#6194) and removed that marking path, without replacement.Fixes #14737.
Change
In
src/_pytest/python.pyPackage.collect, import the package's__init__.pyviaimporttestmodule(already used inPackage.setupforsetup_module), extract marks withget_unpacked_marks, and extendself.own_markers/self.keywordsbefore yielding children. Children inherit viaNode.iter_markers_with_node.collect(notsetup) so marks are visible during collection and beforepytest_runtest_setup(theskippingplugin istryfirst, whilePackage.setupruns after).sys.modules/sys.pathwhen no marks are applied to avoid polluting unrelated imports (e.g.src/nopeintest_does_not_put_src_on_path). When marks are applied we keep the import soPackage.setupdoes not need to re-execute__init__.py._pytestmark_applied.No new collection of
__init__.pyas a test file, so #6194 is not reintroduced.Why this approach
__init__.pyfiles. #6197 expectation (package-level marks propagate) without re-collecting__init__.py.PyobjMixinandFunctionDefinitionhandlepytestmark(viaget_unpacked_marks→own_markers/keywords).setupis too late for skip/xfail evaluation;collectis the earliest point where thePackagenode exists and its children will inherit.Testing
Reproduction after fix:
Nested package (outer skip propagates to subpackage): 2 skipped — pass.
xfailin__init__.py: 1 xfailed — pass.Empty package: 1 passed — pass.
src/nopepollution case: 1 passed — pass (noImportErrorregression).Pre-existing regression
test_skip_packagescenario (root__init__.pywithpytestmark = skip): 2 skipped — pass.Repository checks:
Documentation and release impact
changelog/14737.bugfix.rstif requested)Review notes
__init__.pyis imported to read marks; if it has side effects, it will be executed once during collection for packages with marks (kept), twice (collect + setup) for packages without marks that are deleted/restored. For pure-mark files this is harmless.pytest_collection_modifyitems), happy to move the logic there.