-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conditionally ignore collection of setuptools dirnames #12918
base: main
Are you sure you want to change the base?
Changes from all commits
ad1b157
b45dc40
c296f37
db9be29
9f312aa
22e4e95
961bb42
44d31b6
77c630e
9c61dd3
22d8879
d89d30f
8dee4e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Conditionally ignore collection of setuptools artifacts dirnames only if the | ||
directories reside inside a setuptools project, i.e. `setup.cfg` is present alongside | ||
a `setup.py` or a `pyproject.toml` with setuptools configuration inside. | ||
You can use the new `--collect-in-build` to force collection of ignored directories. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -1754,7 +1754,7 @@ passed multiple times. The expected format is ``name=value``. For example:: | |||||
[seq] matches any character in seq | ||||||
[!seq] matches any char not in seq | ||||||
|
||||||
Default patterns are ``'*.egg'``, ``'.*'``, ``'_darcs'``, ``'build'``, | ||||||
Default patterns are ``'*.egg'``, ``'.*'``, ``'_darcs'``, | ||||||
``'CVS'``, ``'dist'``, ``'node_modules'``, ``'venv'``, ``'{arch}'``. | ||||||
Setting a ``norecursedirs`` replaces the default. Here is an example of | ||||||
how to avoid certain directories: | ||||||
|
@@ -1776,6 +1776,9 @@ passed multiple times. The expected format is ``name=value``. For example:: | |||||
*must* override ``norecursedirs`` in addition to using the | ||||||
``--collect-in-virtualenv`` flag. | ||||||
|
||||||
Similarly, pytest will attempt to intelligently identify and igmore build | ||||||
artifacts of a setuptools project unless ``--collect-in-build`` is used. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
|
||||||
.. confval:: python_classes | ||||||
|
||||||
|
@@ -2163,6 +2166,8 @@ All the command-line flags can be obtained by running ``pytest --help``:: | |||||
--keep-duplicates Keep duplicate tests | ||||||
--collect-in-virtualenv | ||||||
Don't ignore tests in a local virtualenv directory | ||||||
--collect-in-build | ||||||
Don't ignore tests in a local build directory | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
--import-mode={prepend,append,importlib} | ||||||
Prepend/append to sys.path when importing test | ||||||
modules and conftest files. Default: prepend. | ||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -56,15 +56,13 @@ | |||||
def pytest_addoption(parser: Parser) -> None: | ||||||
parser.addini( | ||||||
"norecursedirs", | ||||||
"Directory patterns to avoid for recursion", | ||||||
"Directory patterns to avoid collecting (defaults to ignore build artifacts)", | ||||||
type="args", | ||||||
default=[ | ||||||
"*.egg", | ||||||
".*", | ||||||
"_darcs", | ||||||
"build", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that the description string above should mention that these are still conditionally excluded by default. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added |
||||||
"CVS", | ||||||
"dist", | ||||||
"node_modules", | ||||||
"venv", | ||||||
"{arch}", | ||||||
|
@@ -218,6 +216,13 @@ def pytest_addoption(parser: Parser) -> None: | |||||
default=False, | ||||||
help="Don't ignore tests in a local virtualenv directory", | ||||||
) | ||||||
group.addoption( | ||||||
"--collect-in-build", | ||||||
action="store_true", | ||||||
dest="collect_in_build", | ||||||
default=False, | ||||||
help="Don't ignore builds in a local build/dist artifacts directory", | ||||||
) | ||||||
group.addoption( | ||||||
"--import-mode", | ||||||
default="prepend", | ||||||
|
@@ -371,6 +376,50 @@ def pytest_runtestloop(session: Session) -> bool: | |||||
return True | ||||||
|
||||||
|
||||||
def _is_setuptools_in_pyproject_toml(toml: Path) -> bool: | ||||||
"""Attempt to decode a toml file into a dict, returning None if fails.""" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
if sys.version_info >= (3, 11): | ||||||
import tomllib | ||||||
else: | ||||||
import tomli as tomllib | ||||||
|
||||||
try: | ||||||
toml_text = toml.read_text(encoding="utf-8") | ||||||
parsed_toml = tomllib.loads(toml_text) | ||||||
build_system = parsed_toml.get("build-system", {}).get("requires") | ||||||
if "setuptools" in build_system: | ||||||
return True | ||||||
except tomllib.TOMLDecodeError: | ||||||
# Not a valid Toml, so no setuptools. | ||||||
pass | ||||||
|
||||||
return False | ||||||
|
||||||
|
||||||
def _in_build(path: Path) -> bool: | ||||||
"""Detect if ``path`` is the root of a buildsystem's artifacts | ||||||
by checking known dirnames patterns, and the presence of configuration in | ||||||
the parent dir by checking for a setup.py, setup.cfg, or pyproject.toml. | ||||||
""" | ||||||
if not path.is_dir(): | ||||||
return False | ||||||
|
||||||
setup_cfg = path.parent / "setup.cfg" | ||||||
if not setup_cfg.is_file(): | ||||||
return False | ||||||
|
||||||
if any(fnmatch_ex(pat, path) for pat in ("build", "dist")): | ||||||
setup_py = path.parent / "setup.py" | ||||||
if setup_py.is_file(): | ||||||
return True | ||||||
|
||||||
toml = path.parent / "pyproject.toml" | ||||||
if toml.is_file() and _is_setuptools_in_pyproject_toml(toml): | ||||||
return True | ||||||
|
||||||
return False | ||||||
|
||||||
|
||||||
def _in_venv(path: Path) -> bool: | ||||||
"""Attempt to detect if ``path`` is the root of a Virtual Environment by | ||||||
checking for the existence of the pyvenv.cfg file. | ||||||
|
@@ -422,6 +471,10 @@ def pytest_ignore_collect(collection_path: Path, config: Config) -> bool | None: | |||||
if not allow_in_venv and _in_venv(collection_path): | ||||||
return True | ||||||
|
||||||
allow_in_build = config.getoption("collect_in_build") | ||||||
if not allow_in_build and _in_build(collection_path): | ||||||
return True | ||||||
|
||||||
if collection_path.is_dir(): | ||||||
norecursepatterns = config.getini("norecursedirs") | ||||||
if any(fnmatch_ex(pat, collection_path) for pat in norecursepatterns): | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.