Skip to content

Commit

Permalink
Always pass the Python implementation to uv's -p argument (#143)
Browse files Browse the repository at this point in the history
* Demonstrate #142

* Always pass the Python implementation to uv

Doing so ensures that uv cannot find an unexpected implementation
(like PyPy) that matches based solely on the language version.

Fixes #142
  • Loading branch information
kurtmckee authored Dec 20, 2024
1 parent afa0150 commit 75dcdc1
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/tox_uv/_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,13 @@ def create_python_env(self) -> None:
elif (base.major, base.minor) == sys.version_info[:2] and (sys.implementation.name.lower() == imp):
version_spec = sys.executable
else:
uv_imp = "" if (imp and imp == "cpython") else imp
uv_imp = imp or ""
if not base.major:
version_spec = f"{uv_imp or ''}"
version_spec = uv_imp
elif not base.minor:
version_spec = f"{uv_imp or ''}{base.major}"
version_spec = f"{uv_imp}{base.major}"
else:
version_spec = f"{uv_imp or ''}{base.major}.{base.minor}"
version_spec = f"{uv_imp}{base.major}.{base.minor}"

cmd: list[str] = [self.uv, "venv", "-p", version_spec, "--allow-existing"]
if self.options.verbosity > 3: # noqa: PLR2004
Expand Down
36 changes: 36 additions & 0 deletions tests/test_tox_uv_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,42 @@ def test_uv_venv_spec_pypy(
assert f"-p {expected_uv_pypy} " in stdout


@pytest.mark.parametrize(
("implementation", "expected_implementation", "expected_name"),
[
("", "cpython", "cpython"),
("py", "cpython", "cpython"),
("pypy", "pypy", "pypy"),
],
)
def test_uv_venv_spec_full_implementation(
tox_project: ToxProjectCreator,
implementation: str,
expected_implementation: str,
expected_name: str,
) -> None:
"""Validate that Python implementations are explicitly passed to uv's `-p` argument.
This test ensures that uv searches for the target Python implementation and version,
even if another implementation -- with the same language version --
is found on the path first.
This prevents a regression to a bug that occurred when PyPy 3.10 was on the PATH
and tox was invoked with `tox -e py3.10`:
uv was invoked with `-p 3.10` and found PyPy 3.10, not CPython 3.10.
"""

project = tox_project({})
result = project.run("run", "-vve", f"{implementation}9.99")

# Verify that uv was invoked with the full Python implementation and version.
assert f" -p {expected_implementation}9.99 " in result.out

# Verify that uv interpreted the `-p` argument as a Python spec, not an executable.
# This confirms that tox-uv is passing recognizable, usable `-p` arguments to uv.
assert f"no interpreter found for {expected_name} 9.99" in result.err.lower()


@pytest.fixture
def other_interpreter_exe() -> pathlib.Path: # pragma: no cover
"""Returns an interpreter executable path that is not the exact same as `sys.executable`.
Expand Down

0 comments on commit 75dcdc1

Please sign in to comment.