Skip to content

Commit

Permalink
Fail on mismatched python spec attributes
Browse files Browse the repository at this point in the history
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] #477
[2] #841

Signed-off-by: Stephen Finucane <stephen@that.guru>
Closes: #2754
  • Loading branch information
stephenfin committed Jan 5, 2023
1 parent 36fe263 commit 79c86c7
Show file tree
Hide file tree
Showing 3 changed files with 4 additions and 1 deletion.
2 changes: 2 additions & 0 deletions 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``.
2 changes: 1 addition & 1 deletion src/tox/tox_env/python/api.py
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions tests/tox_env/python/test_python_api.py
Expand Up @@ -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"]),
Expand Down

0 comments on commit 79c86c7

Please sign in to comment.