Files
libretro/scripts/export_native.py
Abdessamad Derraz 0a272dc4e9 chore: lint and format entire codebase
Run ruff check --fix: remove unused imports (F401), fix f-strings
without placeholders (F541), remove unused variables (F841), fix
duplicate dict key (F601).

Run isort --profile black: normalize import ordering across all files.

Run ruff format: apply consistent formatting (black-compatible) to
all 58 Python files.

3 intentional E402 remain (imports after require_yaml() must execute
after yaml is available).
2026-04-01 13:17:55 +02:00

130 lines
3.6 KiB
Python

"""Export truth data to native platform formats."""
from __future__ import annotations
import argparse
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
import yaml
from common import list_registered_platforms, load_platform_config
from exporter import discover_exporters
OUTPUT_FILENAMES: dict[str, str] = {
"retroarch": "System.dat",
"lakka": "System.dat",
"retropie": "System.dat",
"batocera": "batocera-systems",
"recalbox": "es_bios.xml",
"retrobat": "batocera-systems.json",
"emudeck": "checkBIOS.sh",
"retrodeck": "component_manifest.json",
"romm": "known_bios_files.json",
}
def output_path(platform: str, output_dir: str) -> str:
"""Return the full output path for a platform's native export.
Each platform gets its own subdirectory to avoid filename collisions
(e.g. retroarch, lakka, retropie all produce System.dat).
"""
filename = OUTPUT_FILENAMES.get(platform, f"{platform}_bios.dat")
plat_dir = Path(output_dir) / platform
plat_dir.mkdir(parents=True, exist_ok=True)
return str(plat_dir / filename)
def run(
platforms: list[str],
truth_dir: str,
output_dir: str,
platforms_dir: str,
) -> int:
"""Export truth to native formats, return exit code."""
exporters = discover_exporters()
errors = 0
for platform in sorted(platforms):
exporter_cls = exporters.get(platform)
if not exporter_cls:
print(f" SKIP {platform}: no exporter available")
continue
truth_file = Path(truth_dir) / f"{platform}.yml"
if not truth_file.exists():
print(f" SKIP {platform}: {truth_file} not found")
continue
with open(truth_file) as f:
truth_data = yaml.safe_load(f) or {}
scraped: dict | None = None
try:
scraped = load_platform_config(platform, platforms_dir)
except (FileNotFoundError, OSError):
pass
dest = output_path(platform, output_dir)
exporter = exporter_cls()
exporter.export(truth_data, dest, scraped_data=scraped)
issues = exporter.validate(truth_data, dest)
if issues:
print(f" WARN {platform}: {len(issues)} validation issue(s)")
for issue in issues:
print(f" {issue}")
errors += 1
else:
print(f" OK {platform} -> {dest}")
return 1 if errors else 0
def main() -> None:
parser = argparse.ArgumentParser(
description="Export truth data to native platform formats.",
)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--all", action="store_true", help="export all platforms")
group.add_argument("--platform", help="export a single platform")
parser.add_argument(
"--output-dir",
default="dist/upstream",
help="output directory",
)
parser.add_argument(
"--truth-dir",
default="dist/truth",
help="truth YAML directory",
)
parser.add_argument(
"--platforms-dir",
default="platforms",
help="platform configs directory",
)
parser.add_argument(
"--include-archived",
action="store_true",
help="include archived platforms",
)
args = parser.parse_args()
if args.all:
platforms = list_registered_platforms(
args.platforms_dir,
include_archived=args.include_archived,
)
else:
platforms = [args.platform]
code = run(platforms, args.truth_dir, args.output_dir, args.platforms_dir)
sys.exit(code)
if __name__ == "__main__":
main()