Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 59 additions & 4 deletions office/tests/test_python_support_contract.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Cross-file contract for the Python versions advertised by Inkspan Office."""

import json
from pathlib import Path
import re
import tomllib
Expand Down Expand Up @@ -32,6 +33,44 @@ def _workflow_job_block(workflow: str, job_name: str) -> str:
return f" {job_name}:\n{match.group('body')}"


def _office_matrix_python_versions(office_job: str) -> tuple[tuple[str, ...], ...]:
"""Resolve every Python minor set the Office job can select, in declared order.

The workflow may declare the matrix as a literal YAML/JSON sequence or as an
expression that selects between ``fromJSON`` payloads per event. Both forms
are resolved to their values so this contract asserts the supported minors
rather than the syntax that happens to express them.
"""

value_match = re.search(
r"(?m)^\s*python-version:[ \t]*(?P<value>\S.*?)\s*$", office_job
)
assert value_match is not None, (
"the office job declares no python-version matrix entry"
)
matrix_value = value_match.group("value")

payloads = re.findall(r"fromJSON\(\s*'(\[.*?\])'\s*\)", matrix_value) or [
matrix_value
]
declared: list[tuple[str, ...]] = []
for payload in payloads:
try:
versions = json.loads(payload)
except json.JSONDecodeError as error:
raise AssertionError(
f"the office python-version matrix is not resolvable to a "
f"version list; observed {matrix_value!r}"
) from error
assert isinstance(versions, list) and versions, (
f"the office python-version matrix must resolve to a non-empty "
f"list; observed {payload!r}"
)
declared.append(tuple(str(version) for version in versions))

return tuple(declared)


def test_python_support_range_matches_classifiers_and_ci_matrix() -> None:
"""Require package metadata and the Office CI job to cover the same minors."""

Expand All @@ -50,10 +89,26 @@ def test_python_support_range_matches_classifiers_and_ci_matrix() -> None:
office_job = _workflow_job_block(workflow, "office")
assert "runs-on: ubuntu-24.04" in office_job
assert "runs-on: ubuntu-latest" not in office_job
matrix_match = re.search(r'python-version:\s*\[([^\]]+)\]', office_job)
assert matrix_match is not None
matrix_versions = tuple(re.findall(r'"(3\.\d+)"', matrix_match.group(1)))
assert matrix_versions == SUPPORTED_PYTHON_VERSIONS
declared_matrices = _office_matrix_python_versions(office_job)
for declared in declared_matrices:
unsupported = tuple(
version
for version in declared
if version not in SUPPORTED_PYTHON_VERSIONS
)
assert not unsupported, (
f"the office python-version matrix declares unsupported entries "
f"{unsupported!r} in {declared!r}"
)

assert declared_matrices[-1] == SUPPORTED_PYTHON_VERSIONS, (
f"the exhaustive office python-version matrix must cover every "
f"supported minor in order; observed {declared_matrices[-1]!r}"
)
assert SUPPORTED_PYTHON_VERSIONS[-1] in declared_matrices[0], (
f"the office python-version matrix used for pull requests must include "
f"the newest supported minor; observed {declared_matrices[0]!r}"
)


def test_python_support_documentation_matches_the_fixed_ci_environment() -> None:
Expand Down
Loading