Skip to content

Commit

Permalink
Avoid cache collision between wheel and editable wheel builds (#3035)
Browse files Browse the repository at this point in the history
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bernát Gábor <bgabor8@bloomberg.net>
  • Loading branch information
3 people committed Jun 17, 2023
1 parent 6de9c2e commit ce0cc62
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 48 deletions.
18 changes: 9 additions & 9 deletions .pre-commit-config.yaml
Expand Up @@ -4,35 +4,35 @@ repos:
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.0.272"
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/tox-dev/tox-ini-fmt
rev: "1.3.0"
rev: "1.3.1"
hooks:
- id: tox-ini-fmt
args: ["-p", "fix"]
- repo: https://github.com/tox-dev/pyproject-fmt
rev: "0.11.2"
rev: "0.12.0"
hooks:
- id: pyproject-fmt
additional_dependencies: ["tox>=4.6"]
additional_dependencies: ["tox>=4.6.1"]
- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v3.0.0-alpha.9-for-vscode"
hooks:
- id: prettier
args: ["--print-width=120", "--prose-wrap=always"]
- repo: https://github.com/asottile/blacken-docs
rev: 1.13.0
rev: 1.14.0
hooks:
- id: blacken-docs
additional_dependencies: [black==23.3]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.0.272"
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
hooks:
Expand Down
1 change: 1 addition & 0 deletions docs/changelog/3035.bugfix.rst
@@ -0,0 +1 @@
Avoid cache collision between editable wheel build and normal wheel build -- by :user:`f3flight`.
64 changes: 32 additions & 32 deletions pyproject.toml
Expand Up @@ -56,16 +56,16 @@ dependencies = [
"packaging>=23.1",
"platformdirs>=3.5.3",
"pluggy>=1",
"pyproject-api>=1.5.1",
"pyproject-api>=1.5.2",
'tomli>=2.0.1; python_version < "3.11"',
'typing-extensions>=4.6.3; python_version < "3.8"',
"virtualenv>=20.23",
"virtualenv>=20.23.1",
]
optional-dependencies.docs = [
"furo>=2023.5.20",
"sphinx>=7.0.1",
"sphinx-argparse-cli>=1.11",
"sphinx-autodoc-typehints!=1.23.4,>=1.23",
"sphinx-argparse-cli>=1.11.1",
"sphinx-autodoc-typehints!=1.23.4,>=1.23.2",
"sphinx-copybutton>=0.5.2",
"sphinx-inline-tabs>=2023.4.21",
"sphinxcontrib-towncrier>=0.2.1a0",
Expand All @@ -75,7 +75,7 @@ optional-dependencies.testing = [
"build[virtualenv]>=0.10",
"covdefaults>=2.3",
"detect-test-pollution>=1.1.1",
"devpi-process>=0.3",
"devpi-process>=0.3.1",
"diff-cover>=7.6",
"distlib>=0.3.6",
"flaky>=3.7",
Expand All @@ -84,10 +84,10 @@ optional-dependencies.testing = [
"psutil>=5.9.5",
"pytest>=7.3.2",
"pytest-cov>=4.1",
"pytest-mock>=3.10",
"pytest-mock>=3.11.1",
"pytest-xdist>=3.3.1",
"re-assert>=1.1",
'time-machine>=2.9; implementation_name != "pypy"',
'time-machine>=2.10; implementation_name != "pypy"',
"wheel>=0.40",
]
urls.Documentation = "https://tox.wiki"
Expand All @@ -106,6 +106,31 @@ version.source = "vcs"
[tool.black]
line-length = 120

[tool.ruff]
select = ["ALL"]
line-length = 120
target-version = "py37"
isort = {known-first-party = ["tox", "tests"], required-imports = ["from __future__ import annotations"]}
ignore = [
"INP001", # no implicit namespaces here
"D", # ignore documentation for now
"ANN401", # Dynamically typed expressions (typing.Any) are disallowed in `arg`"
"ANN101", # Missing type annotation for `self` in method
"ANN102", # Missing type annotation for `cls` in classmethod"
"D203", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible
"D212", # `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible
"S104", # Possible binding to all interface
]
[tool.ruff.per-file-ignores]
"tests/**/*.py" = [
"S101", # asserts allowed in tests...
"FBT", # don"t care about booleans as positional arguments in tests
"INP001", # no implicit namespace
"D", # don"t care about documentation in tests
"S603", # `subprocess` call: check for execution of untrusted input
"PLR2004", # Magic value used in comparison, consider replacing with a constant variable
]

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--tb=auto -ra --showlocals --no-success-flaky-report"
Expand Down Expand Up @@ -152,28 +177,3 @@ title_format = false
issue_format = ":issue:`{issue}`"
template = "docs/changelog/template.jinja2"
# possible types, all default: feature, bugfix, doc, removal, misc

[tool.ruff]
select = ["ALL"]
line-length = 120
target-version = "py37"
isort = {known-first-party = ["tox", "tests"], required-imports = ["from __future__ import annotations"]}
ignore = [
"INP001", # no implicit namespaces here
"D", # ignore documentation for now
"ANN401", # Dynamically typed expressions (typing.Any) are disallowed in `arg`"
"ANN101", # Missing type annotation for `self` in method
"ANN102", # Missing type annotation for `cls` in classmethod"
"D203", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible
"D212", # `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible
"S104", # Possible binding to all interface
]
[tool.ruff.per-file-ignores]
"tests/**/*.py" = [
"S101", # asserts allowed in tests...
"FBT", # don"t care about booleans as positional arguments in tests
"INP001", # no implicit namespace
"D", # don"t care about documentation in tests
"S603", # `subprocess` call: check for execution of untrusted input
"PLR2004", # Magic value used in comparison, consider replacing with a constant variable
]
14 changes: 7 additions & 7 deletions src/tox/tox_env/python/virtual_env/package/pyproject.py
Expand Up @@ -331,13 +331,13 @@ def __init__(self, root: Path, env: Pep517VirtualEnvPackager) -> None:
self._tox_env = env
self._backend_executor_: LocalSubProcessPep517Executor | None = None
into: dict[str, Any] = {}
pkg_cache = cached(
into,
key=lambda *args, **kwargs: "wheel" if "wheel_directory" in kwargs else "sdist", # noqa: ARG005
)
self.build_wheel = pkg_cache(self.build_wheel) # type: ignore[method-assign]
self.build_sdist = pkg_cache(self.build_sdist) # type: ignore[method-assign]
self.build_editable = pkg_cache(self.build_editable) # type: ignore[method-assign]

for build_type in ("editable", "sdist", "wheel"): # wrap build methods in a cache wrapper

def key(*args: Any, bound_return: str = build_type, **kwargs: Any) -> str: # noqa: ARG001
return bound_return

setattr(self, f"build_{build_type}", cached(into, key=key)(getattr(self, f"build_{build_type}")))

@property
def backend_cmd(self) -> Sequence[str]:
Expand Down
10 changes: 10 additions & 0 deletions tests/demo_pkg_inline/build.py
Expand Up @@ -117,6 +117,16 @@ def get_requires_for_build_wheel(config_settings: dict[str, str] | None = None)
return [] # pragma: no cover # only executed in non-host pythons


if os.environ.get("BACKEND_HAS_EDITABLE"):

def build_editable(
wheel_directory: str,
config_settings: dict[str, str] | None = None,
metadata_directory: str | None = None,
) -> str:
return build_wheel(wheel_directory, config_settings, metadata_directory)


def build_sdist(sdist_directory: str, config_settings: dict[str, str] | None = None) -> str: # noqa: ARG001
result = f"{name}-{version}.tar.gz" # pragma: win32 cover
with tarfile.open(str(Path(sdist_directory) / result), "w:gz") as tar: # pragma: win32 cover
Expand Down
31 changes: 31 additions & 0 deletions tests/tox_env/python/virtual_env/package/test_package_pyproject.py
Expand Up @@ -263,3 +263,34 @@ def test_project_package_with_deps(tox_project: ToxProjectCreator, demo_pkg_setu
else:
assert found_calls[0] == (".pkg", "install_requires")
assert found_calls[1] == (".pkg", "install_deps")


def test_pyproject_build_editable_and_wheel(tox_project: ToxProjectCreator, demo_pkg_inline: Path) -> None:
# test that build wheel and build editable are cached separately

ini = """
[testenv:.pkg]
set_env= BACKEND_HAS_EDITABLE=1
[testenv:a,b]
package = editable
[testenv:c,d]
package = wheel
"""
proj = tox_project({"tox.ini": ini}, base=demo_pkg_inline)
execute_calls = proj.patch_execute(lambda r: 0 if "install" in r.run_id else None)

result = proj.run("r", "-e", "a,b,c,d", "--notest", "--workdir", str(proj.path / ".tox"))

result.assert_success()
found_calls = [(i[0][0].conf.name, i[0][3].run_id) for i in execute_calls.call_args_list]
assert found_calls == [
(".pkg", "_optional_hooks"),
(".pkg", "get_requires_for_build_wheel"),
(".pkg", "build_editable"),
("a", "install_package"),
("b", "install_package"),
(".pkg", "build_wheel"),
("c", "install_package"),
("d", "install_package"),
(".pkg", "_exit"),
]

0 comments on commit ce0cc62

Please sign in to comment.