diff --git a/tools/ci/version_support.py b/tools/ci/version_support.py index 9f47e70a9..d2a77b002 100644 --- a/tools/ci/version_support.py +++ b/tools/ci/version_support.py @@ -38,6 +38,11 @@ def _expand_half_open_minor_range(spec: str) -> list[str]: return [] major_min, minor_min = map(int, min_match.group(1).split(".")) major_max, minor_max = map(int, max_match.group(1).split(".")) + if major_min != major_max: + raise ValueError( + f"Version constraint '{spec}' spans major versions " + f"({major_min} -> {major_max}); only single-major ranges are supported." + ) versions = [] major, minor = major_min, minor_min while (major, minor) < (major_max, minor_max): diff --git a/ultraplot/tests/test_core_versions.py b/ultraplot/tests/test_core_versions.py index 352c71d8c..95e0e3d09 100644 --- a/ultraplot/tests/test_core_versions.py +++ b/ultraplot/tests/test_core_versions.py @@ -4,6 +4,8 @@ import re from pathlib import Path +import pytest + ROOT = Path(__file__).resolve().parents[2] PYPROJECT = ROOT / "pyproject.toml" MAIN_WORKFLOW = ROOT / ".github" / "workflows" / "main.yml" @@ -67,3 +69,12 @@ def test_publish_workflow_python_is_supported(): match = re.search(r'python-version:\s*"(\d+\.\d+)"', text) assert match is not None assert match.group(1) in supported + + +def test_expand_half_open_minor_range_rejects_cross_major_constraints(): + """ + Cross-major constraints (e.g. ">=3.10,<4.0") must raise ValueError immediately. + """ + version_support = _load_version_support() + with pytest.raises(ValueError, match=r"spans major versions \(3 -> 4\)"): + version_support._expand_half_open_minor_range(">=3.10,<4.0")