refactor: derive the milestone bounds from the registry

The highest supported milestone was spelled out in six places across four
files: range(1, 7) and default="m6" in test_cli.py, the same pair in
test_milestones_dosboxx.py, and through=6 in both registry.py and suite.py.
Registering M7 meant finding all six, and missing one failed silently.

Derive MAX_MILESTONE and MILESTONES from CASES instead, and move the mN
selector parser to registry.milestone_number so the pytest module stops
carrying its own copy. Adding cases for a new milestone is now enough for
ferro-test to accept --through/--only for it.

No behaviour change: MAX_MILESTONE evaluates to 6, ferro-test still advertises
{m1..m6} with default m6, and the case snapshot is unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BScg8CF1sAAM2zVHAu5zvW
This commit is contained in:
2026-08-16 22:11:36 +09:00
co-authored by Claude Opus 5
parent c25312135d
commit 4ad3e3097b
3 changed files with 23 additions and 19 deletions
+16 -1
View File
@@ -187,7 +187,22 @@ CASES: list[Case] = [
"okstatic", "oktemp", "oktrim", "okwcall")],
]
def all_cases(*, through: int = 6, only: int | None = None) -> list[Case]:
MAX_MILESTONE: int = max(case.milestone for case in CASES)
MILESTONES: tuple[str, ...] = tuple(f"m{number}"
for number in range(1, MAX_MILESTONE + 1))
def milestone_number(name: str) -> int:
"""Parse an ``mN`` selector against the milestones the registry knows about."""
if not name.startswith("m") or not name[1:].isdigit():
raise ValueError(f"invalid milestone: {name}")
value = int(name[1:])
if value not in range(1, MAX_MILESTONE + 1):
raise ValueError(f"unsupported milestone: {name}")
return value
def all_cases(*, through: int = MAX_MILESTONE, only: int | None = None) -> list[Case]:
if only is not None:
return [case for case in CASES if case.milestone == only]
return [case for case in CASES if case.milestone <= through]
+4 -5
View File
@@ -7,9 +7,7 @@ import sys
from pathlib import Path
from .dosboxx import DosboxError, setup
MILESTONES = tuple(f"m{number}" for number in range(1, 7))
from .registry import MAX_MILESTONE, MILESTONES
def main() -> int:
@@ -23,8 +21,9 @@ def main() -> int:
help="confirm acceptance of the Sybase Open Watcom Public License")
run = commands.add_parser("run", help="build once and run milestone pytest cases")
selection = run.add_mutually_exclusive_group()
selection.add_argument("--through", choices=MILESTONES, default="m6",
help="run cumulatively through this milestone (default: m6)")
selection.add_argument("--through", choices=MILESTONES, default=f"m{MAX_MILESTONE}",
help="run cumulatively through this milestone "
f"(default: m{MAX_MILESTONE})")
selection.add_argument("--only", choices=MILESTONES,
help="run only this milestone's cases")
run.add_argument("-v", "--verbose", action="store_true", help="show every pytest case")
+3 -13
View File
@@ -6,23 +6,13 @@ import warnings
import pytest
from ferrolang_vm.dosboxx import SuiteRun, run_suite
from ferrolang_vm.registry import all_cases
from ferrolang_vm.registry import MAX_MILESTONE, all_cases, milestone_number
from ferrolang_vm.suite import Case
def _number(name: str) -> int:
if not name.startswith("m") or not name[1:].isdigit():
raise ValueError(f"invalid milestone: {name}")
value = int(name[1:])
if value not in range(1, 7):
raise ValueError(f"unsupported milestone: {name}")
return value
ONLY = os.environ.get("FERRO_TEST_ONLY")
CASES = all_cases(
through=_number(os.environ.get("FERRO_TEST_THROUGH", "m6")),
only=_number(ONLY) if ONLY else None,
through=milestone_number(os.environ.get("FERRO_TEST_THROUGH", f"m{MAX_MILESTONE}")),
only=milestone_number(ONLY) if ONLY else None,
)