From 4eadad8358c32d86750958bd0b2a2809c3dcac4a Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 2 Sep 2025 16:26:48 +0200 Subject: [PATCH 1/4] Support dashes in test suite names --- .../split_tox_gh_actions.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/scripts/split_tox_gh_actions/split_tox_gh_actions.py b/scripts/split_tox_gh_actions/split_tox_gh_actions.py index 1c3435f43b..9e20b28eed 100755 --- a/scripts/split_tox_gh_actions/split_tox_gh_actions.py +++ b/scripts/split_tox_gh_actions/split_tox_gh_actions.py @@ -17,6 +17,7 @@ import configparser import hashlib +import re import sys from collections import defaultdict from functools import reduce @@ -25,6 +26,7 @@ from jinja2 import Environment, FileSystemLoader +VERSION_REGEX = re.compile(r"v{?[0-9.]+.*}?|latest") OUT_DIR = Path(__file__).resolve().parent.parent.parent / ".github" / "workflows" TOX_FILE = Path(__file__).resolve().parent.parent.parent / "tox.ini" @@ -207,10 +209,20 @@ def parse_tox(): line = line.strip().lower() try: - # parse tox environment definition - try: - (raw_python_versions, framework, framework_versions) = line.split("-") - except ValueError: + # Parse tox environment definitions. + # The format is pythonversions-integrationname-integrationversions. + # Some valid examples: + # {pyX.Y,pyX.Z}-integrationname-vA.B.C + # {pyX.Y,pyX.Z}-integrationname-v{A.B.C} + # {pyX.Y,pyX.Z}-integrationname + # No that integrationname can also contain dashes, which makes this a + # bit more annoying. + raw_python_versions = line.split("-")[0] + framework_versions = line.rsplit("-", maxsplit=1)[-1] + framework = line[ + len(raw_python_versions) + 1 : -(len(framework_versions) + 1) + ] + if not VERSION_REGEX.match(framework_versions): (raw_python_versions, framework) = line.split("-") framework_versions = [] From 65858234e1dbc59f981c3d1a76bc88fb0d8c36b8 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 3 Sep 2025 09:35:30 +0200 Subject: [PATCH 2/4] actually fail --- scripts/split_tox_gh_actions/split_tox_gh_actions.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/split_tox_gh_actions/split_tox_gh_actions.py b/scripts/split_tox_gh_actions/split_tox_gh_actions.py index 9e20b28eed..1b997ec92f 100755 --- a/scripts/split_tox_gh_actions/split_tox_gh_actions.py +++ b/scripts/split_tox_gh_actions/split_tox_gh_actions.py @@ -204,6 +204,8 @@ def parse_tox(): py_versions_pinned = defaultdict(set) py_versions_latest = defaultdict(set) + parsed_correctly = True + for line in lines: # normalize lines line = line.strip().lower() @@ -237,6 +239,10 @@ def parse_tox(): except ValueError: print(f"ERROR reading line {line}") + parsed_correctly = False + + if not parsed_correctly: + raise RuntimeError("Failed to parse tox.ini") py_versions_pinned = _normalize_py_versions(py_versions_pinned) py_versions_latest = _normalize_py_versions(py_versions_latest) From be9d63633a5edc411217f3b3ccda8488dd388572 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 3 Sep 2025 14:05:58 +0200 Subject: [PATCH 3/4] . --- .../split_tox_gh_actions.py | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/scripts/split_tox_gh_actions/split_tox_gh_actions.py b/scripts/split_tox_gh_actions/split_tox_gh_actions.py index 1b997ec92f..ca6a5dda51 100755 --- a/scripts/split_tox_gh_actions/split_tox_gh_actions.py +++ b/scripts/split_tox_gh_actions/split_tox_gh_actions.py @@ -26,7 +26,18 @@ from jinja2 import Environment, FileSystemLoader -VERSION_REGEX = re.compile(r"v{?[0-9.]+.*}?|latest") +TOXENV_REGEX = re.compile( + r""" + {?(?P(py\d+\.\d+,?)+)}? + -(?P[a-z](?:[a-z_]|-(?!v{?\d|latest))*[a-z0-9]) + (?:-( + (v{?(?P[0-9.]+[0-9a-z,.]*}?)) + | + (?Platest) + ))? +""", + re.VERBOSE, +) OUT_DIR = Path(__file__).resolve().parent.parent.parent / ".github" / "workflows" TOX_FILE = Path(__file__).resolve().parent.parent.parent / "tox.ini" @@ -211,33 +222,26 @@ def parse_tox(): line = line.strip().lower() try: - # Parse tox environment definitions. - # The format is pythonversions-integrationname-integrationversions. - # Some valid examples: - # {pyX.Y,pyX.Z}-integrationname-vA.B.C - # {pyX.Y,pyX.Z}-integrationname-v{A.B.C} - # {pyX.Y,pyX.Z}-integrationname - # No that integrationname can also contain dashes, which makes this a - # bit more annoying. - raw_python_versions = line.split("-")[0] - framework_versions = line.rsplit("-", maxsplit=1)[-1] - framework = line[ - len(raw_python_versions) + 1 : -(len(framework_versions) + 1) - ] - if not VERSION_REGEX.match(framework_versions): - (raw_python_versions, framework) = line.split("-") - framework_versions = [] + # parse tox environment definition + parsed = TOXENV_REGEX.match(line) + if not parsed: + print(f"ERROR reading line {line}") + raise ValueError("Failed to parse tox environment definition") + + groups = parsed.groupdict() + raw_python_versions = groups["py_versions"] + framework = groups["framework"] + framework_versions_latest = groups.get("framework_versions_latest") or False # collect python versions to test the framework in - raw_python_versions = set( - raw_python_versions.replace("{", "").replace("}", "").split(",") - ) - if "latest" in framework_versions: + raw_python_versions = set(raw_python_versions.split(",")) + if framework_versions_latest: py_versions_latest[framework] |= raw_python_versions else: py_versions_pinned[framework] |= raw_python_versions - except ValueError: + except Exception: + raise print(f"ERROR reading line {line}") parsed_correctly = False From 50614a52457decc05c2ab9703bf05595f78fe56f Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 3 Sep 2025 14:14:57 +0200 Subject: [PATCH 4/4] . --- scripts/split_tox_gh_actions/split_tox_gh_actions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/split_tox_gh_actions/split_tox_gh_actions.py b/scripts/split_tox_gh_actions/split_tox_gh_actions.py index ca6a5dda51..cf83e0a3fe 100755 --- a/scripts/split_tox_gh_actions/split_tox_gh_actions.py +++ b/scripts/split_tox_gh_actions/split_tox_gh_actions.py @@ -241,7 +241,6 @@ def parse_tox(): py_versions_pinned[framework] |= raw_python_versions except Exception: - raise print(f"ERROR reading line {line}") parsed_correctly = False