From e9da4d72ed7e55b379a1b6bb4506801cf0124b5e Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Sun, 18 Oct 2026 02:55:45 +0200 Subject: [PATCH] fix: write one truth model per target, not alias generate_truth named a narrowed model's directory after the target as typed, so three aliases of one target wrote three copies, and the pipeline rebuilt the slug by hand to diff it. One function now names the directory from the canonical target for both. --- scripts/common.py | 15 +++++++++++++++ scripts/generate_truth.py | 7 ++++--- scripts/pipeline.py | 17 +++++++++++++---- tests/test_target_names.py | 25 +++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 7 deletions(-) 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."""