mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-10 18:59:56 +00:00
feat(core): read .jsonc data files (strip C-style comments) (feedpak-spec §8)
feedpak-spec §8 (FEP #3 / PR #13) allows .jsonc files (JSON with C-style // line and /* */ block comments) anywhere .json is specified. A Reader MUST strip comments before parsing. Core's sloppak/feedpak readers parsed every side file with bare json.loads, so a .jsonc arrangement / notation / drum_tab / song_timeline / lyrics / keys would fail to load. - lib/jsonc.py (new): shared parse_jsonc(text) + load_json(path). String-aware regex (mirrors the spec reference validator in feedpak-spec/tools/validate.py) — keeps comment-like text inside JSON string literals. load_json auto-detects .jsonc by suffix; plain .json goes straight through json.loads. - lib/sloppak.py: import load_json; replace the 6 json.loads(...read_text...) side-file read sites (arrangement, notation, drum_tab, song_timeline, lyrics, keys) with load_json(<path>). Removed the now-unused `import json`. - scripts/lift_keys_notation.py: import load_json; replace the 3 read sites (song_timeline, arrangement beats fallback, arrangement lift). `import json` stays (json.dumps write at the notation sidecar emit). Additive (MINOR) change: older readers parse .jsonc as plain JSON and ignore comments via the spec's forward-compatibility rules, so no existing pack needs regeneration. Tests: tests/test_sloppak_jsonc_load.py (16 tests) — parse_jsonc unit cases (line/block/multiline/string-boundary/malformed/plain), and end-to-end loads for all 6 side-file types via .jsonc with comments, plus the lift helper reading .jsonc song_timeline + .jsonc arrangement beats, plus the string-boundary preservation rule through the full loader. 122 sloppak/lift tests pass.
This commit is contained in:
@@ -60,6 +60,8 @@ import yaml # noqa: E402
|
||||
|
||||
import notation as notation_mod # noqa: E402, F401 (re-exported for tests)
|
||||
|
||||
from jsonc import load_json # noqa: E402
|
||||
|
||||
# The wire→notation heuristic core lives in ``lib/notation_lift.py`` so it can
|
||||
# be reused in-process (e.g. by the Arrangement Editor's notation save path)
|
||||
# rather than being copy-pasted out of this one-time CLI. Re-exported here so
|
||||
@@ -114,7 +116,7 @@ def _load_song_beats(pak: Path, manifest: dict) -> list[dict]:
|
||||
st_path = _safe_child(pak, st_rel)
|
||||
if st_path is not None and st_path.is_file():
|
||||
try:
|
||||
data = json.loads(st_path.read_text(encoding="utf-8"))
|
||||
data = load_json(st_path)
|
||||
# An empty beats list is not an authoritative timeline — fall
|
||||
# through to the arrangement JSONs rather than ending up with
|
||||
# zero downbeats and skipping the whole sloppak.
|
||||
@@ -134,7 +136,7 @@ def _load_song_beats(pak: Path, manifest: dict) -> list[dict]:
|
||||
if arr_path is None or not arr_path.is_file():
|
||||
continue
|
||||
try:
|
||||
data = json.loads(arr_path.read_text(encoding="utf-8"))
|
||||
data = load_json(arr_path)
|
||||
except (OSError, ValueError):
|
||||
continue
|
||||
if isinstance(data, dict):
|
||||
@@ -219,7 +221,7 @@ def lift_sloppak(pak: Path, *, dry_run: bool = False) -> list[str]:
|
||||
continue
|
||||
|
||||
try:
|
||||
arr_data = json.loads(arr_path.read_text(encoding="utf-8"))
|
||||
arr_data = load_json(arr_path)
|
||||
except (OSError, ValueError) as e:
|
||||
log.warning("%s/%s: unreadable arrangement JSON (%s) — skipped",
|
||||
pak.name, arr_id, e)
|
||||
|
||||
Reference in New Issue
Block a user