Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert to supporting simple Python factors #2849

Merged
merged 5 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/ISSUE_TEMPLATE/feature-request.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ assignees: ""

## Alternative Solutions

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

## Additional context

Expand Down
12 changes: 2 additions & 10 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,10 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.py }}
- name: Pick environment to run
run: |
import os; import platform; import sys; from pathlib import Path
env = f'TOXENV=py{"" if platform.python_implementation() == "CPython" else "py"}3{sys.version_info.minor}'
print(f"Picked: {env} for {sys.version} based of {sys.executable}")
with Path(os.environ["GITHUB_ENV"]).open("ta") as file_handler:
file_handler.write(env)
shell: python
- name: Setup test suite
run: tox r -vv --notest
run: tox r -e py${{ matrix.py }} -vv --notest
- name: Run test suite
run: tox r --skip-pkg-install
run: tox r -e py${{ matrix.py }} --skip-pkg-install
env:
CI_RUN: "yes"
DIFF_AGAINST: HEAD
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ repos:
hooks:
- id: rst-backticks
- repo: https://github.com/tox-dev/tox-ini-fmt
rev: "0.5.2"
rev: "0.6.0"
hooks:
- id: tox-ini-fmt
args: ["-p", "fix"]
Expand All @@ -69,7 +69,7 @@ repos:
- "@prettier/plugin-xml@2.2"
args: ["--print-width=120", "--prose-wrap=always"]
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.32.2
rev: v0.33.0
hooks:
- id: markdownlint
- repo: local
Expand Down
6 changes: 6 additions & 0 deletions docs/changelog/2848.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
tox has reverted support for Python factors that include PATCH release info (e.g. ``py3.10.1``), build architecture
(e.g. ``pypy3-64``) or do not define a ``py`` prefix or other supported prefix (e.g. ``3.10``). These complex factors
were initially supported with the release of tox 4.0 but has proven complicated to support. Instead, the simple factors
supported by tox 3 e.g. (``py310``, ``pypy3``) or period-separated equivalent (``py3.10``) introduced in tox 4 should be
used. Users who wish to specify more specific Python version information should configure the :ref:`base_python` setting
- by :user:`stephenfin`.
18 changes: 9 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[build-system]
build-backend = "hatchling.build"
requires = ["hatchling>=1.12", "hatch-vcs>=0.3"]
requires = ["hatchling>=1.12.2", "hatch-vcs>=0.3"]

[project]
name = "tox"
Expand All @@ -22,24 +22,24 @@ maintainers = [
]
requires-python = ">=3.7"
dependencies = [
"cachetools>=5.2",
"cachetools>=5.2.1",
"chardet>=5.1",
"colorama>=0.4.6",
"packaging>=22",
"packaging>=23",
"platformdirs>=2.6.2",
"pluggy>=1",
"pyproject-api>=1.2.1",
"pyproject-api>=1.4",
'tomli>=2.0.1; python_version < "3.11"',
"virtualenv>=20.17.1",
"filelock>=3.9",
'importlib-metadata>=5.2; python_version < "3.8"',
'importlib-metadata>=6; python_version < "3.8"',
'typing-extensions>=4.4; python_version < "3.8"',
]
optional-dependencies.docs = [
"furo>=2022.12.7",
"sphinx>=6",
"sphinx-argparse-cli>=1.10",
"sphinx-autodoc-typehints>=1.19.5",
"sphinx>=6.1.3",
"sphinx-argparse-cli>=1.11",
"sphinx-autodoc-typehints>=1.20.1",
"sphinx-copybutton>=0.5.1",
"sphinx-inline-tabs>=2022.1.2b11",
"sphinxcontrib-towncrier>=0.2.1a0",
Expand All @@ -53,7 +53,7 @@ optional-dependencies.testing = [
"distlib>=0.3.6",
"flaky>=3.7",
"hatch-vcs>=0.3",
"hatchling>=1.12",
"hatchling>=1.12.2",
"psutil>=5.9.4",
"pytest>=7.2",
"pytest-cov>=4",
Expand Down
17 changes: 13 additions & 4 deletions src/tox/tox_env/python/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
from __future__ import annotations

import logging
import re
import sys
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Any, List, NamedTuple, cast

from packaging.tags import INTERPRETER_SHORT_NAMES
from virtualenv.discovery.py_spec import PythonSpec

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


PY_FACTORS_RE = re.compile(
r"""
^(?!py$) # don't match 'py' as it doesn't provide any info
(?P<impl>py|pypy|cpython|jython|rustpython|ironpython) # the interpeter; most users will simply use 'py'
(?P<version>[2-9]\.?[0-9]?[0-9]?)?$ # the version; one of: MAJORMINOR, MAJOR.MINOR
""",
re.VERBOSE,
)


class Python(ToxEnv, ABC):
def __init__(self, create_args: ToxEnvCreateArgs) -> None:
self._base_python: PythonInfo | None = None
Expand Down Expand Up @@ -131,9 +141,8 @@ def default_base_python(self, conf: Config, env_name: str | None) -> list[str]:
def extract_base_python(cls, env_name: str) -> str | None:
candidates: list[str] = []
for factor in env_name.split("-"):
spec = PythonSpec.from_string_spec(factor)
impl = spec.implementation or "python"
if impl.lower() in INTERPRETER_SHORT_NAMES and env_name is not None and spec.path is None:
match = PY_FACTORS_RE.match(factor)
if match:
candidates.append(factor)
if candidates:
if len(candidates) > 1:
Expand Down
37 changes: 31 additions & 6 deletions tests/tox_env/python/test_python_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,36 @@ def test_diff_msg_no_diff() -> None:
assert Python._diff_msg({}, {}) == "python "


@pytest.mark.parametrize(
("env", "base_python"),
[
("py3", "py3"),
("py311", "py311"),
("py3.12", "py3.12"),
("pypy2", "pypy2"),
("rustpython3", "rustpython3"),
("cpython3.8", "cpython3.8"),
("ironpython2.7", "ironpython2.7"),
("functional-py310", "py310"),
("bar-pypy2-foo", "pypy2"),
("py", None),
("django-32", None),
("eslint-8.3", None),
("py-310", None),
("py3000", None),
("4.foo", None),
("310", None),
("5", None),
("2000", None),
("4000", None),
],
ids=lambda a: "|".join(a) if isinstance(a, list) else str(a),
)
def test_extract_base_python(env: str, base_python: str | None) -> None:
result = Python.extract_base_python(env)
assert result == base_python


@pytest.mark.parametrize("ignore_conflict", [True, False])
@pytest.mark.parametrize(
("env", "base_python"),
Expand All @@ -89,16 +119,14 @@ def test_base_python_env_no_conflict(env: str, base_python: list[str], ignore_co
@pytest.mark.parametrize(
("env", "base_python", "expected", "conflict"),
[
("cpython", ["pypy"], "cpython", ["pypy"]),
("pypy", ["cpython"], "pypy", ["cpython"]),
("pypy2", ["pypy3"], "pypy2", ["pypy3"]),
("py3", ["py2"], "py3", ["py2"]),
("py38", ["py39"], "py38", ["py39"]),
("py38", ["py38", "py39"], "py38", ["py39"]),
("py38", ["python3"], "py38", ["python3"]),
("py310", ["py38", "py39"], "py310", ["py38", "py39"]),
("py3.11.1", ["py3.11.2"], "py3.11.1", ["py3.11.2"]),
("py3-64", ["py3-32"], "py3-64", ["py3-32"]),
("py3.11", ["py310"], "py3.11", ["py310"]),
("py310-magic", ["py39"], "py310", ["py39"]),
],
ids=lambda a: "|".join(a) if isinstance(a, list) else str(a),
Expand All @@ -110,9 +138,6 @@ def test_base_python_env_conflict(
conflict: list[str],
ignore_conflict: bool,
) -> None:
if env == "py3-64":
raise pytest.skip("bug #2657")

if ignore_conflict:
result = Python._validate_base_python(env, base_python, ignore_conflict)
assert result == [expected]
Expand Down
12 changes: 6 additions & 6 deletions tests/tox_env/python/virtual_env/test_virtualenv_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ def virtualenv_opt(monkeypatch: MonkeyPatch, mocker: MockerFixture) -> VirtualEn

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

conf = result.env_conf("py")
conf = result.env_conf("py3")
assert conf["system_site_packages"] is False
assert conf["always_copy"] is False
assert conf["download"] is False
Expand All @@ -46,7 +46,7 @@ def test_virtualenv_default_settings(tox_project: ToxProjectCreator, virtualenv_
assert virtualenv_opt.download is False
assert virtualenv_opt.copies is False
assert virtualenv_opt.no_periodic_update is True
assert virtualenv_opt.python == ["py"]
assert virtualenv_opt.python == ["py3"]
assert virtualenv_opt.try_first_with == [str(sys.executable), str(proj.path / "a")]


Expand All @@ -60,10 +60,10 @@ def test_virtualenv_flipped_settings(
)
monkeypatch.setenv("VIRTUALENV_CLEAR", "0")

result = proj.run("r", "-e", "py")
result = proj.run("r", "-e", "py3")
result.assert_success()

conf = result.env_conf("py")
conf = result.env_conf("py3")
assert conf["system_site_packages"] is True
assert conf["always_copy"] is True
assert conf["download"] is True
Expand All @@ -72,7 +72,7 @@ def test_virtualenv_flipped_settings(
assert virtualenv_opt.system_site is True
assert virtualenv_opt.download is True
assert virtualenv_opt.copies is True
assert virtualenv_opt.python == ["py"]
assert virtualenv_opt.python == ["py3"]


def test_virtualenv_env_ignored_if_set(
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ description = do a release, required posarg of the version number
skip_install = true
deps =
gitpython>=3.1.30
packaging>=22
packaging>=23
towncrier>=22.12
commands =
python {toxinidir}/tasks/release.py --version {posargs}
Expand Down