Skip to content

Commit 9b05f65

Browse files
authored
Recreate venv if python interpreter is missing (#216)
This fixes a bug where a cached venv might become broken due to python being upgraded and tox was unable to recreate it: ``` error: Failed to inspect Python interpreter from active virtual environment at `.tox/py314/bin/python3` Caused by: Broken symlink at `.tox/py314/bin/python3`, was the underlying Python interpreter removed? hint: Consider recreating the environment (e.g., with `uv venv`) py314: exit 2 (0.01 seconds) /home/runner/work/ansible-lint/ansible-lint> .tox/.tox/bin/uv pip install --reinstall --no-deps ansible-lint@/home/runner/work/ansible-lint/ansible-lint/.tox/.tmp/package/2/ansible_lint-25.6.2.dev4-0.editable-py3-none-any.whl pid=2959 ``` See: https://github.com/ansible/ansible-lint/actions/runs/15822605275/job/44605268272?pr=4637
1 parent d9027e8 commit 9b05f65

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

src/tox_uv/_installer.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ def post_process_install_command(self, cmd: Command) -> Command:
8787
return cmd
8888

8989
def install(self, arguments: Any, section: str, of_type: str) -> None: # noqa: ANN401
90+
# can happen if the original python was upgraded to a newer version and
91+
# the symlinks become orphan.
92+
if not self._env.env_python().resolve().is_file():
93+
msg = "existing venv is broken"
94+
raise Recreate(msg)
95+
9096
if isinstance(arguments, PythonDeps):
9197
self._install_requirement_file(arguments, section, of_type)
9298
elif isinstance(arguments, Sequence): # pragma: no branch

tests/test_tox_uv_installer.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,29 @@ def test_uv_install_with_resolution_strategy_and_pip_pre(tox_project: ToxProject
123123
"tomli>=2.0.1",
124124
"-v",
125125
]
126+
127+
128+
def test_uv_install_broken_venv(tox_project: ToxProjectCreator) -> None:
129+
"""Tests ability to detect that a venv a with broken symlink to python interpreter is recreated."""
130+
project = tox_project({
131+
"tox.ini": """
132+
[testenv]
133+
skip_install = true
134+
install = false
135+
commands = python3 --version
136+
"""
137+
})
138+
result = project.run("run", "-v")
139+
result.assert_success()
140+
assert "recreate env because existing venv is broken" not in result.out
141+
# break the environment
142+
bin_dir = project.path / ".tox" / "py" / "bin"
143+
bin_dir.mkdir(parents=True, exist_ok=True)
144+
for filename in ("python", "python3"):
145+
path = bin_dir / filename
146+
path.unlink()
147+
path.symlink_to("/broken-location")
148+
# run again and ensure we did run the repair bits
149+
result = project.run("run", "-v")
150+
result.assert_success()
151+
assert "recreate env because existing venv is broken" in result.out

0 commit comments

Comments
 (0)