mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-09-11 05:54:33 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ede9baeb97 | ||
|
|
e572a0a2f5 |
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
next root-level module can't ship broken.
|
next root-level module can't ship broken.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- **`routers/` — extracting `server.py`'s route layer, cheapest-first (R3).** Each PR moves a cohesive route group into a `fastapi.APIRouter` under `lib/routers/`, mounted with `app.include_router(...)` at its original site (FastAPI matches in registration order; the full route table stays byte-identical). Bodies are verbatim — only the decorator receiver (`@app` → `@router`) and singleton reads (`meta_db` → `appstate.meta_db`, resolved at call time) change. So far: `audio_effects` (5 routes), `artist_aliases` (5 routes — the Tidy-up/P4 alias overrides). The next cut is picked by a dependency-closure scan that ranks groups by how many `monkeypatch.setattr(server, …)` targets they'd drag along.
|
||||||
- **`routers/` — the first extracted route module (R3).** The five audio-effects mapping
|
- **`routers/` — the first extracted route module (R3).** The five audio-effects mapping
|
||||||
endpoints move out of `server.py` into `lib/routers/audio_effects.py` as a
|
endpoints move out of `server.py` into `lib/routers/audio_effects.py` as a
|
||||||
`fastapi.APIRouter`, mounted with `app.include_router(...)` **at the point in the file
|
`fastapi.APIRouter`, mounted with `app.include_router(...)` **at the point in the file
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ without a *signed* exemption" is unenforceable.
|
|||||||
## Planned, NOT exempt (owned by split plans — listed so nothing falls between states)
|
## Planned, NOT exempt (owned by split plans — listed so nothing falls between states)
|
||||||
|
|
||||||
core `static/app.js` (11,852) · `static/highway.js` (4,168, whole file) · `server.py`
|
core `static/app.js` (11,852) · `static/highway.js` (4,168, whole file) · `server.py`
|
||||||
(9,386 — was 14,037; ratcheted by the R3 `MetadataDB` + `AudioEffectsMappingDB`
|
(9,337 — was 14,037; ratcheted by the R3 `MetadataDB` + `AudioEffectsMappingDB`
|
||||||
extractions and the first `routers/` module) ·
|
extractions and the first two `routers/` modules) ·
|
||||||
`lib/metadata_db.py` (4,373 — new in R3; the `MetadataDB` class alone is 4,018 lines
|
`lib/metadata_db.py` (4,373 — new in R3; the `MetadataDB` class alone is 4,018 lines
|
||||||
and is a monolith in its own right, to be split per-table once the router train
|
and is a monolith in its own right, to be split per-table once the router train
|
||||||
lands) · `static/v3/songs.js` (4,134) · `static/capabilities/audio-session.js`
|
lands) · `static/v3/songs.js` (4,134) · `static/capabilities/audio-session.js`
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
"""Artist aliases / Tidy-up (P4) — canonicalize messy artist tags at DISPLAY
|
||||||
|
("ACDC" -> "AC/DC") without touching feedpak files or the scanner-derived
|
||||||
|
songs.artist. All DB-only.
|
||||||
|
|
||||||
|
Extracted verbatim from ``server.py`` (R3); only the decorator receiver
|
||||||
|
(``@app`` -> ``@router``) and the singleton read (``meta_db`` ->
|
||||||
|
``appstate.meta_db``) changed. The read stays a module attribute so a re-imported
|
||||||
|
``server`` re-publishes a fresh DB into the seam — see ``appstate.py``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from fastapi import APIRouter
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
import appstate
|
||||||
|
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/artist-aliases")
|
||||||
|
def list_artist_aliases():
|
||||||
|
"""Existing raw→canonical overrides (the Tidy-up 'current merges' list)."""
|
||||||
|
return {"aliases": appstate.meta_db.list_artist_aliases()}
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/artists/raw")
|
||||||
|
def list_raw_artists(limit: int = 2000):
|
||||||
|
"""Distinct RAW artist names + song counts + current canonical — the Tidy-up
|
||||||
|
picker (you merge raw variants into one canonical)."""
|
||||||
|
return {"artists": appstate.meta_db.raw_artists(limit)}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/api/artist-aliases")
|
||||||
|
def set_artist_alias(data: dict):
|
||||||
|
"""Upsert one override: {raw_name, canonical_name, mb_artist_id?}. A self-alias
|
||||||
|
(raw == canonical) clears the row instead (un-merge)."""
|
||||||
|
raw = (data.get("raw_name") or "").strip()
|
||||||
|
canon = (data.get("canonical_name") or "").strip()
|
||||||
|
if not raw or not canon:
|
||||||
|
return JSONResponse({"error": "raw_name and canonical_name are required"}, 400)
|
||||||
|
result = appstate.meta_db.set_artist_alias(raw, canon, (data.get("mb_artist_id") or None))
|
||||||
|
if not result.get("ok"):
|
||||||
|
# Would form a cycle (raw → … → raw) — refuse rather than corrupt the chain.
|
||||||
|
return JSONResponse(
|
||||||
|
{"error": "alias would create a cycle", "raw_name": raw, "canonical_name": canon},
|
||||||
|
409)
|
||||||
|
return {"ok": True, "raw_name": raw, "canonical_name": result.get("canonical_name", canon)}
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/api/artist-aliases/merge")
|
||||||
|
def merge_artist_aliases(data: dict):
|
||||||
|
"""Merge several raw artist variants into one canonical:
|
||||||
|
{raw_names: [...], canonical_name}. The canonical's own self-alias is skipped.
|
||||||
|
Returns {merged: N}."""
|
||||||
|
canon = (data.get("canonical_name") or "").strip()
|
||||||
|
raws = data.get("raw_names")
|
||||||
|
if not canon:
|
||||||
|
return JSONResponse({"error": "canonical_name is required"}, 400)
|
||||||
|
if not isinstance(raws, list) or not raws:
|
||||||
|
return JSONResponse({"error": "raw_names must be a non-empty array"}, 400)
|
||||||
|
n = appstate.meta_db.merge_artists(raws, canon)
|
||||||
|
return {"merged": n, "canonical_name": canon}
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/api/artist-aliases/{raw_name:path}")
|
||||||
|
def delete_artist_alias(raw_name: str):
|
||||||
|
"""Remove one override so that raw artist stands on its own again."""
|
||||||
|
appstate.meta_db.remove_artist_alias(raw_name)
|
||||||
|
return {"ok": True}
|
||||||
@@ -71,7 +71,7 @@ from audio_effects_db import AudioEffectsMappingDB
|
|||||||
# Lives in lib/ because that is the one core dir every packaging path copies.
|
# Lives in lib/ because that is the one core dir every packaging path copies.
|
||||||
import appstate
|
import appstate
|
||||||
# Extracted route modules. They import `appstate`, never `server` — one-way graph.
|
# Extracted route modules. They import `appstate`, never `server` — one-way graph.
|
||||||
from routers import audio_effects
|
from routers import audio_effects, artist_aliases
|
||||||
import sloppak as sloppak_mod
|
import sloppak as sloppak_mod
|
||||||
import drums as drums_mod
|
import drums as drums_mod
|
||||||
import notation as notation_mod
|
import notation as notation_mod
|
||||||
@@ -4847,59 +4847,9 @@ def list_tags():
|
|||||||
|
|
||||||
|
|
||||||
# ── Artist aliases / Tidy-up (P4) ────────────────────────────────────────────
|
# ── Artist aliases / Tidy-up (P4) ────────────────────────────────────────────
|
||||||
# Canonicalize messy artist tags at DISPLAY ("ACDC" → "AC/DC") without touching
|
# Mounted here, where these routes used to be defined (FastAPI matches in
|
||||||
# the feedpak files or the scanner-derived songs.artist. All DB-only.
|
# registration order). Implementation in lib/routers/artist_aliases.py.
|
||||||
|
app.include_router(artist_aliases.router)
|
||||||
@app.get("/api/artist-aliases")
|
|
||||||
def list_artist_aliases():
|
|
||||||
"""Existing raw→canonical overrides (the Tidy-up 'current merges' list)."""
|
|
||||||
return {"aliases": meta_db.list_artist_aliases()}
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/artists/raw")
|
|
||||||
def list_raw_artists(limit: int = 2000):
|
|
||||||
"""Distinct RAW artist names + song counts + current canonical — the Tidy-up
|
|
||||||
picker (you merge raw variants into one canonical)."""
|
|
||||||
return {"artists": meta_db.raw_artists(limit)}
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/artist-aliases")
|
|
||||||
def set_artist_alias(data: dict):
|
|
||||||
"""Upsert one override: {raw_name, canonical_name, mb_artist_id?}. A self-alias
|
|
||||||
(raw == canonical) clears the row instead (un-merge)."""
|
|
||||||
raw = (data.get("raw_name") or "").strip()
|
|
||||||
canon = (data.get("canonical_name") or "").strip()
|
|
||||||
if not raw or not canon:
|
|
||||||
return JSONResponse({"error": "raw_name and canonical_name are required"}, 400)
|
|
||||||
result = meta_db.set_artist_alias(raw, canon, (data.get("mb_artist_id") or None))
|
|
||||||
if not result.get("ok"):
|
|
||||||
# Would form a cycle (raw → … → raw) — refuse rather than corrupt the chain.
|
|
||||||
return JSONResponse(
|
|
||||||
{"error": "alias would create a cycle", "raw_name": raw, "canonical_name": canon},
|
|
||||||
409)
|
|
||||||
return {"ok": True, "raw_name": raw, "canonical_name": result.get("canonical_name", canon)}
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/artist-aliases/merge")
|
|
||||||
def merge_artist_aliases(data: dict):
|
|
||||||
"""Merge several raw artist variants into one canonical:
|
|
||||||
{raw_names: [...], canonical_name}. The canonical's own self-alias is skipped.
|
|
||||||
Returns {merged: N}."""
|
|
||||||
canon = (data.get("canonical_name") or "").strip()
|
|
||||||
raws = data.get("raw_names")
|
|
||||||
if not canon:
|
|
||||||
return JSONResponse({"error": "canonical_name is required"}, 400)
|
|
||||||
if not isinstance(raws, list) or not raws:
|
|
||||||
return JSONResponse({"error": "raw_names must be a non-empty array"}, 400)
|
|
||||||
n = meta_db.merge_artists(raws, canon)
|
|
||||||
return {"merged": n, "canonical_name": canon}
|
|
||||||
|
|
||||||
|
|
||||||
@app.delete("/api/artist-aliases/{raw_name:path}")
|
|
||||||
def delete_artist_alias(raw_name: str):
|
|
||||||
"""Remove one override so that raw artist stands on its own again."""
|
|
||||||
meta_db.remove_artist_alias(raw_name)
|
|
||||||
return {"ok": True}
|
|
||||||
|
|
||||||
|
|
||||||
# ── Artist pages (launch charrette PR-B) ──────────────────────────────────────
|
# ── Artist pages (launch charrette PR-B) ──────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user