From fafce99fcb3d9943a10b219c16de299a82e8d491 Mon Sep 17 00:00:00 2001 From: Pavel Dikov <66369686+paveldikov@users.noreply.github.com> Date: Wed, 7 Aug 2024 18:17:29 +0100 Subject: [PATCH] fix(tox_env.python): do not process absolute paths to interpreter as PythonSpec (#3311) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bernát Gábor Co-authored-by: Bernát Gábor --- docs/changelog/3191.bugfix.rst | 1 + src/tox/tox_env/python/api.py | 4 +++- tests/tox_env/python/test_python_api.py | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/3191.bugfix.rst diff --git a/docs/changelog/3191.bugfix.rst b/docs/changelog/3191.bugfix.rst new file mode 100644 index 000000000..60c954d26 --- /dev/null +++ b/docs/changelog/3191.bugfix.rst @@ -0,0 +1 @@ +``base_python`` now accepts absolute paths to interpreter executable - by :user:`paveldikov`. diff --git a/src/tox/tox_env/python/api.py b/src/tox/tox_env/python/api.py index 1f9141790..8d07bc6a0 100644 --- a/src/tox/tox_env/python/api.py +++ b/src/tox/tox_env/python/api.py @@ -6,6 +6,7 @@ import re import sys from abc import ABC, abstractmethod +from pathlib import Path from typing import TYPE_CHECKING, Any, List, NamedTuple, cast from virtualenv.discovery.py_spec import PythonSpec @@ -14,7 +15,6 @@ from tox.tox_env.errors import Fail, Recreate, Skip if TYPE_CHECKING: - from pathlib import Path from tox.config.main import Config @@ -169,6 +169,8 @@ def _validate_base_python( if env_base_python is not None: spec_name = PythonSpec.from_string_spec(env_base_python) for base_python in base_pythons: + if Path(base_python).is_absolute(): + return [base_python] spec_base = PythonSpec.from_string_spec(base_python) if any( getattr(spec_base, key) != getattr(spec_name, key) diff --git a/tests/tox_env/python/test_python_api.py b/tests/tox_env/python/test_python_api.py index 8690cc838..048f398c2 100644 --- a/tests/tox_env/python/test_python_api.py +++ b/tests/tox_env/python/test_python_api.py @@ -1,5 +1,6 @@ from __future__ import annotations +import os import sys from typing import TYPE_CHECKING, Callable from unittest.mock import patch @@ -125,6 +126,24 @@ def test_base_python_env_no_conflict(env: str, base_python: list[str], ignore_co assert result is base_python +@pytest.mark.parametrize( + ("env", "base_python", "platform"), + [ + ("py312-unix", ["/opt/python312/bin/python"], "posix"), + ("py312-win", [r"C:\Program Files\Python312\python.exe"], "nt"), + ("py311-win", [r"\\a\python311\python.exe"], "nt"), + ("py310-win", [r"\\?\UNC\a\python310\python.exe"], "nt"), + ("py310", ["//a/python310/bin/python"], None), + ], + ids=lambda a: "|".join(a) if isinstance(a, list) else str(a), +) +def test_base_python_absolute(env: str, base_python: list[str], platform: str | None) -> None: + if platform and platform != os.name: + pytest.skip(f"Not applicable to this platform. ({platform} != {os.name})") + result = Python._validate_base_python(env, base_python, False) # noqa: SLF001 + assert result == base_python + + @pytest.mark.parametrize("ignore_conflict", [True, False]) @pytest.mark.parametrize( ("env", "base_python", "expected", "conflict"),