Skip to content

Commit 9f89f51

Browse files
stephenfingaborbernatpre-commit-ci[bot]
authored
Revert to supporting simple Python factors (#2849)
Co-authored-by: Bernát Gábor <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Fixes #2657 Fixes #2848
1 parent 34b79a2 commit 9f89f51

File tree

9 files changed

+72
-39
lines changed

9 files changed

+72
-39
lines changed

.github/ISSUE_TEMPLATE/feature-request.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ assignees: ""
1818

1919
## Alternative Solutions
2020

21-
<!-- Have you tried to workaround the problem using tox or other tools? Or a different approach to solving this issue? Please elaborate here. -->
21+
<!-- Have you tried to workaround the problem using tox or other tools? Or a different approach to solving this issue?
22+
Please elaborate here. -->
2223

2324
## Additional context
2425

.github/workflows/check.yml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,10 @@ jobs:
4040
uses: actions/setup-python@v4
4141
with:
4242
python-version: ${{ matrix.py }}
43-
- name: Pick environment to run
44-
run: |
45-
import os; import platform; import sys; from pathlib import Path
46-
env = f'TOXENV=py{"" if platform.python_implementation() == "CPython" else "py"}3{sys.version_info.minor}'
47-
print(f"Picked: {env} for {sys.version} based of {sys.executable}")
48-
with Path(os.environ["GITHUB_ENV"]).open("ta") as file_handler:
49-
file_handler.write(env)
50-
shell: python
5143
- name: Setup test suite
52-
run: tox r -vv --notest
44+
run: tox r -e py${{ matrix.py }} -vv --notest
5345
- name: Run test suite
54-
run: tox r --skip-pkg-install
46+
run: tox r -e py${{ matrix.py }} --skip-pkg-install
5547
env:
5648
CI_RUN: "yes"
5749
DIFF_AGAINST: HEAD

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ repos:
4343
hooks:
4444
- id: rst-backticks
4545
- repo: https://github.com/tox-dev/tox-ini-fmt
46-
rev: "0.5.2"
46+
rev: "0.6.0"
4747
hooks:
4848
- id: tox-ini-fmt
4949
args: ["-p", "fix"]
@@ -69,7 +69,7 @@ repos:
6969
- "@prettier/[email protected]"
7070
args: ["--print-width=120", "--prose-wrap=always"]
7171
- repo: https://github.com/igorshubovych/markdownlint-cli
72-
rev: v0.32.2
72+
rev: v0.33.0
7373
hooks:
7474
- id: markdownlint
7575
- repo: local

docs/changelog/2848.bugfix.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
tox has reverted support for Python factors that include PATCH release info (e.g. ``py3.10.1``), build architecture
2+
(e.g. ``pypy3-64``) or do not define a ``py`` prefix or other supported prefix (e.g. ``3.10``). These complex factors
3+
were initially supported with the release of tox 4.0 but has proven complicated to support. Instead, the simple factors
4+
supported by tox 3 e.g. (``py310``, ``pypy3``) or period-separated equivalent (``py3.10``) introduced in tox 4 should be
5+
used. Users who wish to specify more specific Python version information should configure the :ref:`base_python` setting
6+
- by :user:`stephenfin`.

pyproject.toml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[build-system]
22
build-backend = "hatchling.build"
3-
requires = ["hatchling>=1.12", "hatch-vcs>=0.3"]
3+
requires = ["hatchling>=1.12.2", "hatch-vcs>=0.3"]
44

55
[project]
66
name = "tox"
@@ -22,24 +22,24 @@ maintainers = [
2222
]
2323
requires-python = ">=3.7"
2424
dependencies = [
25-
"cachetools>=5.2",
25+
"cachetools>=5.2.1",
2626
"chardet>=5.1",
2727
"colorama>=0.4.6",
28-
"packaging>=22",
28+
"packaging>=23",
2929
"platformdirs>=2.6.2",
3030
"pluggy>=1",
31-
"pyproject-api>=1.2.1",
31+
"pyproject-api>=1.4",
3232
'tomli>=2.0.1; python_version < "3.11"',
3333
"virtualenv>=20.17.1",
3434
"filelock>=3.9",
35-
'importlib-metadata>=5.2; python_version < "3.8"',
35+
'importlib-metadata>=6; python_version < "3.8"',
3636
'typing-extensions>=4.4; python_version < "3.8"',
3737
]
3838
optional-dependencies.docs = [
3939
"furo>=2022.12.7",
40-
"sphinx>=6",
41-
"sphinx-argparse-cli>=1.10",
42-
"sphinx-autodoc-typehints>=1.19.5",
40+
"sphinx>=6.1.3",
41+
"sphinx-argparse-cli>=1.11",
42+
"sphinx-autodoc-typehints>=1.20.1",
4343
"sphinx-copybutton>=0.5.1",
4444
"sphinx-inline-tabs>=2022.1.2b11",
4545
"sphinxcontrib-towncrier>=0.2.1a0",
@@ -53,7 +53,7 @@ optional-dependencies.testing = [
5353
"distlib>=0.3.6",
5454
"flaky>=3.7",
5555
"hatch-vcs>=0.3",
56-
"hatchling>=1.12",
56+
"hatchling>=1.12.2",
5757
"psutil>=5.9.4",
5858
"pytest>=7.2",
5959
"pytest-cov>=4",

src/tox/tox_env/python/api.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
from __future__ import annotations
55

66
import logging
7+
import re
78
import sys
89
from abc import ABC, abstractmethod
910
from pathlib import Path
1011
from typing import Any, List, NamedTuple, cast
1112

12-
from packaging.tags import INTERPRETER_SHORT_NAMES
1313
from virtualenv.discovery.py_spec import PythonSpec
1414

1515
from tox.config.main import Config
@@ -47,6 +47,16 @@ def version_dot(self) -> str:
4747
return f"{self.version_info.major}.{self.version_info.minor}"
4848

4949

50+
PY_FACTORS_RE = re.compile(
51+
r"""
52+
^(?!py$) # don't match 'py' as it doesn't provide any info
53+
(?P<impl>py|pypy|cpython|jython|rustpython|ironpython) # the interpeter; most users will simply use 'py'
54+
(?P<version>[2-9]\.?[0-9]?[0-9]?)?$ # the version; one of: MAJORMINOR, MAJOR.MINOR
55+
""",
56+
re.VERBOSE,
57+
)
58+
59+
5060
class Python(ToxEnv, ABC):
5161
def __init__(self, create_args: ToxEnvCreateArgs) -> None:
5262
self._base_python: PythonInfo | None = None
@@ -131,9 +141,8 @@ def default_base_python(self, conf: Config, env_name: str | None) -> list[str]:
131141
def extract_base_python(cls, env_name: str) -> str | None:
132142
candidates: list[str] = []
133143
for factor in env_name.split("-"):
134-
spec = PythonSpec.from_string_spec(factor)
135-
impl = spec.implementation or "python"
136-
if impl.lower() in INTERPRETER_SHORT_NAMES and env_name is not None and spec.path is None:
144+
match = PY_FACTORS_RE.match(factor)
145+
if match:
137146
candidates.append(factor)
138147
if candidates:
139148
if len(candidates) > 1:

tests/tox_env/python/test_python_api.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,36 @@ def test_diff_msg_no_diff() -> None:
7171
assert Python._diff_msg({}, {}) == "python "
7272

7373

74+
@pytest.mark.parametrize(
75+
("env", "base_python"),
76+
[
77+
("py3", "py3"),
78+
("py311", "py311"),
79+
("py3.12", "py3.12"),
80+
("pypy2", "pypy2"),
81+
("rustpython3", "rustpython3"),
82+
("cpython3.8", "cpython3.8"),
83+
("ironpython2.7", "ironpython2.7"),
84+
("functional-py310", "py310"),
85+
("bar-pypy2-foo", "pypy2"),
86+
("py", None),
87+
("django-32", None),
88+
("eslint-8.3", None),
89+
("py-310", None),
90+
("py3000", None),
91+
("4.foo", None),
92+
("310", None),
93+
("5", None),
94+
("2000", None),
95+
("4000", None),
96+
],
97+
ids=lambda a: "|".join(a) if isinstance(a, list) else str(a),
98+
)
99+
def test_extract_base_python(env: str, base_python: str | None) -> None:
100+
result = Python.extract_base_python(env)
101+
assert result == base_python
102+
103+
74104
@pytest.mark.parametrize("ignore_conflict", [True, False])
75105
@pytest.mark.parametrize(
76106
("env", "base_python"),
@@ -89,16 +119,14 @@ def test_base_python_env_no_conflict(env: str, base_python: list[str], ignore_co
89119
@pytest.mark.parametrize(
90120
("env", "base_python", "expected", "conflict"),
91121
[
92-
("cpython", ["pypy"], "cpython", ["pypy"]),
93122
("pypy", ["cpython"], "pypy", ["cpython"]),
94123
("pypy2", ["pypy3"], "pypy2", ["pypy3"]),
95124
("py3", ["py2"], "py3", ["py2"]),
96125
("py38", ["py39"], "py38", ["py39"]),
97126
("py38", ["py38", "py39"], "py38", ["py39"]),
98127
("py38", ["python3"], "py38", ["python3"]),
99128
("py310", ["py38", "py39"], "py310", ["py38", "py39"]),
100-
("py3.11.1", ["py3.11.2"], "py3.11.1", ["py3.11.2"]),
101-
("py3-64", ["py3-32"], "py3-64", ["py3-32"]),
129+
("py3.11", ["py310"], "py3.11", ["py310"]),
102130
("py310-magic", ["py39"], "py310", ["py39"]),
103131
],
104132
ids=lambda a: "|".join(a) if isinstance(a, list) else str(a),
@@ -110,9 +138,6 @@ def test_base_python_env_conflict(
110138
conflict: list[str],
111139
ignore_conflict: bool,
112140
) -> None:
113-
if env == "py3-64":
114-
raise pytest.skip("bug #2657")
115-
116141
if ignore_conflict:
117142
result = Python._validate_base_python(env, base_python, ignore_conflict)
118143
assert result == [expected]

tests/tox_env/python/virtual_env/test_virtualenv_api.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ def virtualenv_opt(monkeypatch: MonkeyPatch, mocker: MockerFixture) -> VirtualEn
3333

3434
def test_virtualenv_default_settings(tox_project: ToxProjectCreator, virtualenv_opt: VirtualEnvOptions) -> None:
3535
proj = tox_project({"tox.ini": "[testenv]\npackage=skip"})
36-
result = proj.run("r", "-e", "py", "--discover", sys.executable, str(proj.path / "a"))
36+
result = proj.run("r", "-e", "py3", "--discover", sys.executable, str(proj.path / "a"))
3737
result.assert_success()
3838

39-
conf = result.env_conf("py")
39+
conf = result.env_conf("py3")
4040
assert conf["system_site_packages"] is False
4141
assert conf["always_copy"] is False
4242
assert conf["download"] is False
@@ -46,7 +46,7 @@ def test_virtualenv_default_settings(tox_project: ToxProjectCreator, virtualenv_
4646
assert virtualenv_opt.download is False
4747
assert virtualenv_opt.copies is False
4848
assert virtualenv_opt.no_periodic_update is True
49-
assert virtualenv_opt.python == ["py"]
49+
assert virtualenv_opt.python == ["py3"]
5050
assert virtualenv_opt.try_first_with == [str(sys.executable), str(proj.path / "a")]
5151

5252

@@ -60,10 +60,10 @@ def test_virtualenv_flipped_settings(
6060
)
6161
monkeypatch.setenv("VIRTUALENV_CLEAR", "0")
6262

63-
result = proj.run("r", "-e", "py")
63+
result = proj.run("r", "-e", "py3")
6464
result.assert_success()
6565

66-
conf = result.env_conf("py")
66+
conf = result.env_conf("py3")
6767
assert conf["system_site_packages"] is True
6868
assert conf["always_copy"] is True
6969
assert conf["download"] is True
@@ -72,7 +72,7 @@ def test_virtualenv_flipped_settings(
7272
assert virtualenv_opt.system_site is True
7373
assert virtualenv_opt.download is True
7474
assert virtualenv_opt.copies is True
75-
assert virtualenv_opt.python == ["py"]
75+
assert virtualenv_opt.python == ["py3"]
7676

7777

7878
def test_virtualenv_env_ignored_if_set(

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ description = do a release, required posarg of the version number
8383
skip_install = true
8484
deps =
8585
gitpython>=3.1.30
86-
packaging>=22
86+
packaging>=23
8787
towncrier>=22.12
8888
commands =
8989
python {toxinidir}/tasks/release.py --version {posargs}

0 commit comments

Comments
 (0)