diff --git a/scripts/common.py b/scripts/common.py index 0cc1805a..c50687e4 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -494,8 +494,9 @@ def truth_target_dir( 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. + alias left the others stale beside it. Called per platform, since two + platforms can file one name differently (Lakka builds an image named + switch). generate_truth writes here and diff_truth reads here. """ named = canonical_target_name(platforms, target, platforms_dir) slug = re.sub(r"[^a-z0-9]+", "-", named.strip().lower()).strip("-") diff --git a/scripts/diff_truth.py b/scripts/diff_truth.py index 53b93af6..27138681 100644 --- a/scripts/diff_truth.py +++ b/scripts/diff_truth.py @@ -21,6 +21,7 @@ from common import ( load_platform_config, native_layer, require_yaml, + truth_target_dir, yaml_load, ) from truth import diff_platform_truth @@ -174,6 +175,11 @@ def main() -> None: ) parser.add_argument("--truth-dir", default="dist/truth") parser.add_argument("--platforms-dir", default="platforms") + parser.add_argument( + "--target", + help="read the models generate_truth --target wrote, each under the " + "target as its platform files it", + ) args = parser.parse_args() if args.all: @@ -188,9 +194,13 @@ def main() -> None: compared = 0 for platform in platforms: - truth = _load_truth(args.truth_dir, platform) + truth_dir = ( + truth_target_dir(args.truth_dir, [platform], args.target, args.platforms_dir) + if args.target else args.truth_dir + ) + truth = _load_truth(truth_dir, platform) if truth is None: - print(f"skip {platform}: no truth YAML in {args.truth_dir}/", file=sys.stderr) + print(f"skip {platform}: no truth YAML in {truth_dir}/", file=sys.stderr) continue try: diff --git a/scripts/generate_truth.py b/scripts/generate_truth.py index 1df87dcb..259812c4 100644 --- a/scripts/generate_truth.py +++ b/scripts/generate_truth.py @@ -92,15 +92,16 @@ def main(argv: list[str] | None = None) -> None: # A target-narrowed model is a different artifact: written under the # platform's own name it overwrote the full one, and diff_truth then - # compared a narrowed model against the whole scrape. - output_dir = args.output_dir - if args.target: - output_dir = truth_target_dir( - output_dir, platforms, args.target, args.platforms_dir - ) - os.makedirs(output_dir, exist_ok=True) - + # compared a narrowed model against the whole scrape. Its directory is + # the target as this platform files it, as the packs are named: Lakka's + # switch is its own image, RetroArch's is nintendo-switch. for name in platforms: + output_dir = args.output_dir + if args.target: + output_dir = truth_target_dir( + output_dir, [name], args.target, args.platforms_dir + ) + os.makedirs(output_dir, exist_ok=True) # Resolve target cores target_cores: set[str] | None = None if args.target: diff --git a/scripts/pipeline.py b/scripts/pipeline.py index af78a9d8..f9fd27f9 100644 --- a/scripts/pipeline.py +++ b/scripts/pipeline.py @@ -45,9 +45,7 @@ from common import ( ArtifactLockBusy, artifact_lock, hold_artifact_lock, - list_registered_platforms, load_data_dir_registry, - truth_target_dir, ) from refresh_data_dirs import hold_data_dirs @@ -256,17 +254,9 @@ def _truth_steps(args: argparse.Namespace, results: dict) -> bool: """Steps 2c to 2e: truth model, its diff, the native export.""" all_ok = True # Step 2c: Generate truth YAMLs - # A targeted run writes its model in a subdirectory of its own, and the - # diff has to read the same one or it compares a narrowed model against - # the whole scrape. + # A targeted run writes each platform's model under the target as that + # platform files it; the diff is told the target and reads the same place. truth_dir = Path(args.output_dir) / "truth" - if args.target: - # 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 = [ @@ -293,6 +283,8 @@ def _truth_steps(args: argparse.Namespace, results: dict) -> bool: if args.with_truth or args.with_export: diff_cmd = [sys.executable, "scripts/diff_truth.py", "--all"] diff_cmd.extend(["--truth-dir", str(truth_dir)]) + if args.target: + diff_cmd.extend(["--target", args.target]) ok, _ = run(diff_cmd, "2d diff truth") results["diff_truth"] = ok all_ok = all_ok and ok diff --git a/tests/test_target_names.py b/tests/test_target_names.py index d916c08f..146496a3 100644 --- a/tests/test_target_names.py +++ b/tests/test_target_names.py @@ -113,23 +113,28 @@ class OneTruthModelPerTarget(unittest.TestCase): 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 + from common import truth_target_dir # noqa: PLC0415 - platforms = list_registered_platforms( - str(REPO_ROOT / "platforms"), include_archived=True - ) + platforms = str(REPO_ROOT / "platforms") dirs = { - truth_target_dir("truth", platforms, alias, str(REPO_ROOT / "platforms")) + truth_target_dir("truth", ["retroarch"], alias, platforms) for alias in ("nx", "switch", "nintendo-switch") } self.assertEqual(dirs, {str(Path("truth") / "nintendo-switch")}) + # Lakka builds an image named switch: its own target, its own model. + self.assertEqual( + truth_target_dir("truth", ["lakka"], "switch", platforms), + str(Path("truth") / "switch"), + ) def test_writer_and_reader_call_one_function(self): - for module in ("generate_truth.py", "pipeline.py"): + for module in ("generate_truth.py", "diff_truth.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) + pipeline = (REPO_ROOT / "scripts" / "pipeline.py").read_text() + self.assertIn('diff_cmd.extend(["--target", args.target])', pipeline) class TheListingCountsWhatTheFilterUses(unittest.TestCase):