diff --git a/scripts/common.py b/scripts/common.py index a9a2484e..0cc1805a 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -487,6 +487,21 @@ def canonical_target_name( return found.pop() if len(found) == 1 else target +def truth_target_dir( + output_dir: str, platforms: list[str], target: str, platforms_dir: str = "platforms" +) -> str: + """Where a target-narrowed truth model is written and read. + + Slugged from the name the target is filed under: `nx`, `switch` and + `nintendo-switch` wrote three copies of one model, and a run under one + alias left the others stale beside it. generate_truth writes here and + the pipeline's diff reads here, so both call this. + """ + named = canonical_target_name(platforms, target, platforms_dir) + slug = re.sub(r"[^a-z0-9]+", "-", named.strip().lower()).strip("-") + return os.path.join(output_dir, slug or "target") + + def load_target_config( platform_name: str, target: str, diff --git a/scripts/generate_truth.py b/scripts/generate_truth.py index 5ce44b76..5d33bbfe 100644 --- a/scripts/generate_truth.py +++ b/scripts/generate_truth.py @@ -10,7 +10,6 @@ from __future__ import annotations import argparse import os -import re import sys sys.path.insert(0, os.path.dirname(__file__)) @@ -21,6 +20,7 @@ from common import ( load_platform_config, load_target_config, require_yaml, + truth_target_dir, write_text_atomic, yaml_load, ) @@ -94,8 +94,9 @@ def main(argv: list[str] | None = None) -> None: # compared a narrowed model against the whole scrape. output_dir = args.output_dir if args.target: - slug = re.sub(r"[^a-z0-9]+", "-", args.target.strip().lower()).strip("-") - output_dir = os.path.join(output_dir, slug or "target") + output_dir = truth_target_dir( + output_dir, platforms, args.target, args.platforms_dir + ) os.makedirs(output_dir, exist_ok=True) for name in platforms: diff --git a/scripts/pipeline.py b/scripts/pipeline.py index fd1c469c..88b06cf7 100644 --- a/scripts/pipeline.py +++ b/scripts/pipeline.py @@ -41,7 +41,13 @@ if sys.version_info < (3, 12): sys.exit(f"pipeline.py needs Python 3.12 or newer, this is {sys.version.split()[0]}") sys.path.insert(0, str(Path(__file__).parent)) -from common import ArtifactLockBusy, artifact_lock, hold_artifact_lock +from common import ( + ArtifactLockBusy, + artifact_lock, + hold_artifact_lock, + list_registered_platforms, + truth_target_dir, +) def run(cmd: list[str], label: str) -> tuple[bool, str]: @@ -253,9 +259,12 @@ def _truth_steps(args: argparse.Namespace, results: dict) -> bool: # the whole scrape. truth_dir = Path(args.output_dir) / "truth" if args.target: - truth_dir = truth_dir / re.sub( - r"[^a-z0-9]+", "-", args.target.strip().lower() - ).strip("-") + # generate_truth --all writes every registered platform's model. + truth_dir = Path(truth_target_dir( + str(truth_dir), + list_registered_platforms("platforms", include_archived=True), + args.target, + )) if args.with_truth or args.with_export: truth_cmd = [ diff --git a/tests/test_target_names.py b/tests/test_target_names.py index fee198ea..d916c08f 100644 --- a/tests/test_target_names.py +++ b/tests/test_target_names.py @@ -107,6 +107,31 @@ class EachPlatformNamesTheTargetItsOwnWay(unittest.TestCase): self.assertNotIn("args.target = canonical_target_name(", source) +class OneTruthModelPerTarget(unittest.TestCase): + """generate_truth slugged the typed name: --target nx, switch and + nintendo-switch wrote three copies of one model, and the pipeline's diff + rebuilt the same slug by hand to find it.""" + + def test_aliases_share_a_directory(self): + from common import list_registered_platforms, truth_target_dir # noqa: PLC0415 + + platforms = list_registered_platforms( + str(REPO_ROOT / "platforms"), include_archived=True + ) + dirs = { + truth_target_dir("truth", platforms, alias, str(REPO_ROOT / "platforms")) + for alias in ("nx", "switch", "nintendo-switch") + } + self.assertEqual(dirs, {str(Path("truth") / "nintendo-switch")}) + + def test_writer_and_reader_call_one_function(self): + for module in ("generate_truth.py", "pipeline.py"): + source = (REPO_ROOT / "scripts" / module).read_text() + with self.subTest(module=module): + self.assertIn("truth_target_dir(", source) + self.assertNotIn('re.sub(\n r"[^a-z0-9]+"', source) + + class TheListingCountsWhatTheFilterUses(unittest.TestCase): """--list-targets showed Batocera x86_64 with 198 cores; --target x86_64 filters on 187 once _overrides.yml removes machine variants and launchers."""