mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-24 04:39:06 -05:00
78 lines
2.8 KiB
Python
78 lines
2.8 KiB
Python
"""A standalone app's paths are the folders its code opens below data_root.
|
|
|
|
The site prints data_root joined to each entry's standalone destination, so a
|
|
frontend's layout written there (Batocera's bios/switch/) sends the reader to a
|
|
folder the app never reads. A frontend folder name is allowed only where the
|
|
app's own code joins that folder to its data root.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
FRONTEND_FOLDERS = ("bios/", "switch/", "system/")
|
|
|
|
# Profiles whose code reads one of those folders below its data root.
|
|
CODE_READS = {
|
|
# BIOS folder of the data directory, the PCSX2 layout it carries
|
|
# (aethersx2 profile notes, AetherSX2-release MacOS/AetherSX2).
|
|
"aethersx2": {"bios/"},
|
|
# BIOS_FOLDER under gui_data_folder() (src/core/fds.c:305, src/core/cheat.c:105).
|
|
"punes": {"bios/"},
|
|
# KeysDir "system" under BaseDirPath
|
|
# (src/Ryujinx.Common/Configuration/AppDataManager.cs:17, 229).
|
|
"ryujinx": {"system/"},
|
|
"kenji-nx": {"system/"},
|
|
# PathSystem is the system folder beside DOSBoxPure.cfg (main.cpp:2032-2039).
|
|
"dosbox-pure-unleashed": {"system/"},
|
|
}
|
|
|
|
|
|
def _standalone_profiles() -> dict[str, dict]:
|
|
profiles = {}
|
|
for path in sorted((REPO_ROOT / "emulators").glob("*.yml")):
|
|
with path.open(encoding="utf-8") as fh:
|
|
profile = yaml.safe_load(fh)
|
|
if isinstance(profile, dict) and profile.get("data_root") \
|
|
and profile.get("type") == "standalone":
|
|
profiles[path.stem] = profile
|
|
return profiles
|
|
|
|
|
|
def _destination(entry: dict) -> str:
|
|
return str(entry.get("standalone_path") or entry.get("path") or "")
|
|
|
|
|
|
class StandaloneDestinations(unittest.TestCase):
|
|
def test_no_frontend_folder_below_data_root(self):
|
|
wrong = []
|
|
for name, profile in _standalone_profiles().items():
|
|
allowed = CODE_READS.get(name, set())
|
|
for entry in profile.get("files") or []:
|
|
if not isinstance(entry, dict):
|
|
continue
|
|
dest = _destination(entry)
|
|
for folder in FRONTEND_FOLDERS:
|
|
if dest.startswith(folder) and folder not in allowed:
|
|
wrong.append(f"{name}: {entry.get('name')} at {dest}")
|
|
self.assertEqual(wrong, [])
|
|
|
|
def test_every_allowed_folder_is_read(self):
|
|
profiles = _standalone_profiles()
|
|
unused = []
|
|
for name, folders in CODE_READS.items():
|
|
dests = [_destination(e) for e in profiles.get(name, {}).get("files") or []
|
|
if isinstance(e, dict)]
|
|
unused += [f"{name}: {folder}" for folder in sorted(folders)
|
|
if not any(d.startswith(folder) for d in dests)]
|
|
self.assertEqual(unused, [])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|