From 79c86c7c2a690face2b95a84ac4f0b2c17269f90 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 4 Jan 2023 16:51:32 +0000 Subject: [PATCH 1/2] Fail on mismatched python spec attributes The following is intended to be a correct tox configuration: [tox] min_version = 4.1 env_list = py{38,39,310,311},docs [testenv] base_python = python3.8 [testenv:docs] commands = sphinx-build ... The goal of this is to use 'python3.8' (i.e. the value of '[testenv] base_python') for all environments except those with specific 'pyXX' factors in them. This helps eliminate issues where environments that do not specify a 'pyXX' factor run with different Python versions in different environments. An earlier bug, #477 [1], prevented us from doing this. Due to #477, the interpreter version indicated by '[testenv] base_python' (or rather '[testenv] basepython' - the underscore-separated variant was only introduced in tox 4) would override the value indicated by the 'pyXX' factor. This was resolved with a PR, #841 [2], which started warning users if they were unintentionally running against the wrong interpreter and introduced the 'ignore_basepython_conflict' value to opt into the correct behavior. Unfortunately, this has been partially broken in the move to tox 4. While the above configuration still works, the following no longer does: [tox] min_version = 4.1 env_list = py{38,39,310,311},docs [testenv] base_python = python3 [testenv:docs] commands = sphinx-build ... This configuration was common back during the move from Python 2 to Python 3. It ensured that 'python3' was used for all testenvs that did not request an explicit Python version via a factor or their own 'base_python' version. While it's no longer necessary, it is still quite common. Currently, running with this configuration will result in 'python3' being used for every environment, rather than e.g. 'python3.8' for a testenv with the 'py38' factor. This is clearly incorrect. This issue stems from an errant bit of logic. When comparing interpreter versions as part of the '_validate_base_python', we ignore various attributes if they are unset on either '[testenv] base_python' or the 'pyXX' factor. This allows e.g. 'python3' to match 'python3.8', since the minor version is unset for the '[testenv] base_python' value, 'python3'. The fix is simple: while we can ignore unset attributes for factor-derived versions (to allow a 'py3' factor to work with e.g. 'base_python = python3.8'), we should insist on them for 'base_python'-derived versions. [1] https://github.com/tox-dev/tox/issues/477 [2] https://github.com/tox-dev/tox/pull/841 Signed-off-by: Stephen Finucane Closes: #2754 --- docs/changelog/2754.bugfix.rst | 2 ++ src/tox/tox_env/python/api.py | 2 +- tests/tox_env/python/test_python_api.py | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/2754.bugfix.rst diff --git a/docs/changelog/2754.bugfix.rst b/docs/changelog/2754.bugfix.rst new file mode 100644 index 000000000..922aaff09 --- /dev/null +++ b/docs/changelog/2754.bugfix.rst @@ -0,0 +1,2 @@ +Setting ``[testenv] basepython = python3`` will no longer override the Python +interpreter version requested by a factor, such as ``py311``. diff --git a/src/tox/tox_env/python/api.py b/src/tox/tox_env/python/api.py index 9a8ff6ce3..58e73ca21 100644 --- a/src/tox/tox_env/python/api.py +++ b/src/tox/tox_env/python/api.py @@ -154,7 +154,7 @@ def _validate_base_python(env_name: str, base_pythons: list[str], ignore_base_py if any( getattr(spec_base, key) != getattr(spec_name, key) for key in ("implementation", "major", "minor", "micro", "architecture") - if getattr(spec_base, key) is not None and getattr(spec_name, key) is not None + if getattr(spec_name, key) is not None ): msg = f"env name {env_name} conflicting with base python {base_python}" if ignore_base_python_conflict: diff --git a/tests/tox_env/python/test_python_api.py b/tests/tox_env/python/test_python_api.py index 0520ff173..b11c4376c 100644 --- a/tests/tox_env/python/test_python_api.py +++ b/tests/tox_env/python/test_python_api.py @@ -95,6 +95,7 @@ def test_base_python_env_no_conflict(env: str, base_python: list[str], ignore_co ("py3", ["py2"], ["py2"]), ("py38", ["py39"], ["py39"]), ("py38", ["py38", "py39"], ["py39"]), + ("py38", ["python3"], ["python3"]), ("py310", ["py38", "py39"], ["py38", "py39"]), ("py3.11.1", ["py3.11.2"], ["py3.11.2"]), ("py3-64", ["py3-32"], ["py3-32"]), From cf5ec8410b31b1baccc6c51c58ff7a4ba4a352ca Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 5 Jan 2023 17:38:39 +0000 Subject: [PATCH 2/2] Address nits in changelog Signed-off-by: Stephen Finucane --- docs/changelog/2754.bugfix.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/changelog/2754.bugfix.rst b/docs/changelog/2754.bugfix.rst index 922aaff09..d948067fb 100644 --- a/docs/changelog/2754.bugfix.rst +++ b/docs/changelog/2754.bugfix.rst @@ -1,2 +1,2 @@ -Setting ``[testenv] basepython = python3`` will no longer override the Python -interpreter version requested by a factor, such as ``py311``. +Setting ``[testenv] basepython = python3`` will no longer override the Python interpreter version requested by a factor, +such as ``py311`` - by :user:`stephenfin`.