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).
This commit is contained in:
Abdessamad Derraz
2026-04-01 13:17:55 +02:00
parent a2d30557e4
commit 0a272dc4e9
56 changed files with 5115 additions and 2679 deletions

View File

@@ -2,6 +2,7 @@
Auto-detects *_targets_scraper.py files and exposes their scrapers.
"""
from __future__ import annotations
import importlib

View File

@@ -6,6 +6,7 @@ Sources (batocera-linux/batocera.linux):
- package/batocera/emulationstation/batocera-es-system/es_systems.yml
-- emulator requireAnyOf flag mapping
"""
from __future__ import annotations
import argparse
@@ -35,23 +36,23 @@ _HEADERS = {
"Accept": "application/vnd.github.v3+json",
}
_TARGET_FLAG_RE = re.compile(r'^(BR2_PACKAGE_BATOCERA_TARGET_\w+)=y', re.MULTILINE)
_TARGET_FLAG_RE = re.compile(r"^(BR2_PACKAGE_BATOCERA_TARGET_\w+)=y", re.MULTILINE)
# Matches: select BR2_PACKAGE_FOO (optional: if CONDITION)
# Condition may span multiple lines (backslash continuation)
_SELECT_RE = re.compile(
r'^\s+select\s+(BR2_PACKAGE_\w+)' # package being selected
r'(?:\s+if\s+((?:[^\n]|\\\n)+?))?' # optional "if CONDITION" (may continue with \)
r'(?:\s*#[^\n]*)?$', # optional trailing comment
r"^\s+select\s+(BR2_PACKAGE_\w+)" # package being selected
r"(?:\s+if\s+((?:[^\n]|\\\n)+?))?" # optional "if CONDITION" (may continue with \)
r"(?:\s*#[^\n]*)?$", # optional trailing comment
re.MULTILINE,
)
# Meta-flag definition: "if COND\n\tconfig DERIVED_FLAG\n\t...\nendif"
_META_BLOCK_RE = re.compile(
r'^if\s+((?:[^\n]|\\\n)+?)\n' # condition (may span lines via \)
r'(?:.*?\n)*?' # optional lines before the config
r'\s+config\s+(BR2_PACKAGE_\w+)' # derived flag name
r'.*?^endif', # end of block
r"^if\s+((?:[^\n]|\\\n)+?)\n" # condition (may span lines via \)
r"(?:.*?\n)*?" # optional lines before the config
r"\s+config\s+(BR2_PACKAGE_\w+)" # derived flag name
r".*?^endif", # end of block
re.MULTILINE | re.DOTALL,
)
@@ -80,7 +81,7 @@ def _fetch_json(url: str) -> list | dict | None:
def _normalise_condition(raw: str) -> str:
"""Strip backslash-continuations and collapse whitespace."""
return re.sub(r'\\\n\s*', ' ', raw).strip()
return re.sub(r"\\\n\s*", " ", raw).strip()
def _tokenise(condition: str) -> list[str]:
@@ -89,14 +90,16 @@ def _tokenise(condition: str) -> list[str]:
return token_re.findall(condition)
def _check_condition(tokens: list[str], pos: int, active: frozenset[str]) -> tuple[bool, int]:
def _check_condition(
tokens: list[str], pos: int, active: frozenset[str]
) -> tuple[bool, int]:
"""Recursive descent check of a Kconfig boolean expression."""
return _check_or(tokens, pos, active)
def _check_or(tokens: list[str], pos: int, active: frozenset[str]) -> tuple[bool, int]:
left, pos = _check_and(tokens, pos, active)
while pos < len(tokens) and tokens[pos] == '||':
while pos < len(tokens) and tokens[pos] == "||":
pos += 1
right, pos = _check_and(tokens, pos, active)
left = left or right
@@ -105,7 +108,7 @@ def _check_or(tokens: list[str], pos: int, active: frozenset[str]) -> tuple[bool
def _check_and(tokens: list[str], pos: int, active: frozenset[str]) -> tuple[bool, int]:
left, pos = _check_not(tokens, pos, active)
while pos < len(tokens) and tokens[pos] == '&&':
while pos < len(tokens) and tokens[pos] == "&&":
pos += 1
right, pos = _check_not(tokens, pos, active)
left = left and right
@@ -113,24 +116,26 @@ def _check_and(tokens: list[str], pos: int, active: frozenset[str]) -> tuple[boo
def _check_not(tokens: list[str], pos: int, active: frozenset[str]) -> tuple[bool, int]:
if pos < len(tokens) and tokens[pos] == '!':
if pos < len(tokens) and tokens[pos] == "!":
pos += 1
val, pos = _check_atom(tokens, pos, active)
return not val, pos
return _check_atom(tokens, pos, active)
def _check_atom(tokens: list[str], pos: int, active: frozenset[str]) -> tuple[bool, int]:
def _check_atom(
tokens: list[str], pos: int, active: frozenset[str]
) -> tuple[bool, int]:
if pos >= len(tokens):
return True, pos
tok = tokens[pos]
if tok == '(':
if tok == "(":
pos += 1
val, pos = _check_or(tokens, pos, active)
if pos < len(tokens) and tokens[pos] == ')':
if pos < len(tokens) and tokens[pos] == ")":
pos += 1
return val, pos
if tok.startswith('BR2_'):
if tok.startswith("BR2_"):
pos += 1
return tok in active, pos
if tok.startswith('"'):
@@ -170,7 +175,9 @@ def _parse_meta_flags(text: str) -> list[tuple[str, str]]:
return results
def _expand_flags(primary_flag: str, meta_rules: list[tuple[str, str]]) -> frozenset[str]:
def _expand_flags(
primary_flag: str, meta_rules: list[tuple[str, str]]
) -> frozenset[str]:
"""Given a board's primary flag, expand to all active derived flags.
Iterates until stable (handles chained derivations like X86_64_ANY -> X86_ANY).
@@ -194,7 +201,7 @@ def _parse_selects(text: str) -> list[tuple[str, str]]:
results: list[tuple[str, str]] = []
for m in _SELECT_RE.finditer(text):
pkg = m.group(1)
cond = _normalise_condition(m.group(2) or '')
cond = _normalise_condition(m.group(2) or "")
results.append((pkg, cond))
return results
@@ -261,7 +268,8 @@ class Scraper(BaseTargetScraper):
if not data or not isinstance(data, list):
return []
return [
item["name"] for item in data
item["name"]
for item in data
if isinstance(item, dict)
and item.get("name", "").startswith("batocera-")
and item.get("name", "").endswith(".board")

View File

@@ -4,6 +4,7 @@ Sources:
SteamOS: dragoonDorise/EmuDeck -functions/EmuScripts/*.sh
Windows: EmuDeck/emudeck-we -functions/EmuScripts/*.ps1
"""
from __future__ import annotations
import argparse
@@ -20,8 +21,12 @@ from . import BaseTargetScraper
PLATFORM_NAME = "emudeck"
STEAMOS_API = "https://api.github.com/repos/dragoonDorise/EmuDeck/contents/functions/EmuScripts"
WINDOWS_API = "https://api.github.com/repos/EmuDeck/emudeck-we/contents/functions/EmuScripts"
STEAMOS_API = (
"https://api.github.com/repos/dragoonDorise/EmuDeck/contents/functions/EmuScripts"
)
WINDOWS_API = (
"https://api.github.com/repos/EmuDeck/emudeck-we/contents/functions/EmuScripts"
)
# Map EmuDeck script names to emulator profile keys
# Script naming: emuDeckDolphin.sh -> dolphin
@@ -70,8 +75,8 @@ def _list_emuscripts(api_url: str) -> list[str]:
def _script_to_core(filename: str) -> str | None:
"""Convert EmuScripts filename to core profile key."""
# Strip extension and emuDeck prefix
name = re.sub(r'\.(sh|ps1)$', '', filename, flags=re.IGNORECASE)
name = re.sub(r'^emuDeck', '', name, flags=re.IGNORECASE)
name = re.sub(r"\.(sh|ps1)$", "", filename, flags=re.IGNORECASE)
name = re.sub(r"^emuDeck", "", name, flags=re.IGNORECASE)
if not name:
return None
key = name.lower()
@@ -86,8 +91,9 @@ class Scraper(BaseTargetScraper):
def __init__(self, url: str = "https://github.com/dragoonDorise/EmuDeck"):
super().__init__(url=url)
def _fetch_cores_for_target(self, api_url: str, label: str,
arch: str = "x86_64") -> list[str]:
def _fetch_cores_for_target(
self, api_url: str, label: str, arch: str = "x86_64"
) -> list[str]:
print(f" fetching {label} EmuScripts...", file=sys.stderr)
scripts = _list_emuscripts(api_url)
cores: list[str] = []
@@ -99,7 +105,7 @@ class Scraper(BaseTargetScraper):
seen.add(core)
cores.append(core)
# Detect RetroArch presence (provides all libretro cores)
name = re.sub(r'\.(sh|ps1)$', '', script, flags=re.IGNORECASE)
name = re.sub(r"\.(sh|ps1)$", "", script, flags=re.IGNORECASE)
if name.lower() in ("emudeckretroarch", "retroarch_maincfg"):
has_retroarch = True
@@ -112,15 +118,18 @@ class Scraper(BaseTargetScraper):
seen.add(c)
cores.append(c)
print(f" {label}: {standalone_count} standalone + "
f"{len(cores) - standalone_count} via RetroArch = {len(cores)} total",
file=sys.stderr)
print(
f" {label}: {standalone_count} standalone + "
f"{len(cores) - standalone_count} via RetroArch = {len(cores)} total",
file=sys.stderr,
)
return sorted(cores)
@staticmethod
def _load_retroarch_cores(arch: str) -> list[str]:
"""Load RetroArch target cores for given architecture."""
import os
target_path = os.path.join("platforms", "targets", "retroarch.yml")
if not os.path.exists(target_path):
return []
@@ -157,9 +166,7 @@ class Scraper(BaseTargetScraper):
def main() -> None:
parser = argparse.ArgumentParser(
description="Scrape EmuDeck emulator targets"
)
parser = argparse.ArgumentParser(description="Scrape EmuDeck emulator targets")
parser.add_argument("--dry-run", action="store_true", help="Show target summary")
parser.add_argument("--output", "-o", help="Output YAML file")
args = parser.parse_args()

View File

@@ -16,6 +16,7 @@ Buildbot structure varies by platform:
- ps2: playstation/ps2/latest/ -> *_libretro_ps2.elf.zip
- vita: bundles only (VPK) - no individual cores
"""
from __future__ import annotations
import argparse
@@ -64,7 +65,9 @@ RECIPE_TARGETS: list[tuple[str, str, str]] = [
("playstation/vita", "playstation-vita", "armv7"),
]
RECIPE_BASE_URL = "https://raw.githubusercontent.com/libretro/libretro-super/master/recipes/"
RECIPE_BASE_URL = (
"https://raw.githubusercontent.com/libretro/libretro-super/master/recipes/"
)
# Match any href containing _libretro followed by a platform-specific extension
# Covers: .so.zip, .dll.zip, .dylib.zip, .nro.zip, .dol.zip, .rpx.zip,
@@ -75,7 +78,7 @@ _HREF_RE = re.compile(
)
# Extract core name: everything before _libretro
_CORE_NAME_RE = re.compile(r'^(.+?)_libretro')
_CORE_NAME_RE = re.compile(r"^(.+?)_libretro")
class Scraper(BaseTargetScraper):
@@ -180,12 +183,16 @@ def main() -> None:
data = scraper.fetch_targets()
total_cores = sum(len(t["cores"]) for t in data["targets"].values())
print(f"\n{len(data['targets'])} targets, {total_cores} total core entries",
file=sys.stderr)
print(
f"\n{len(data['targets'])} targets, {total_cores} total core entries",
file=sys.stderr,
)
if args.dry_run:
for name, info in sorted(data["targets"].items()):
print(f" {name:30s} {info['architecture']:10s} {len(info['cores']):>4d} cores")
print(
f" {name:30s} {info['architecture']:10s} {len(info['cores']):>4d} cores"
)
return
if args.output:

View File

@@ -4,6 +4,7 @@ Source: https://github.com/RetroPie/RetroPie-Setup/tree/master/scriptmodules/lib
Parses rp_module_id and rp_module_flags from each scriptmodule to determine
which platforms each core supports.
"""
from __future__ import annotations
import argparse