fix: 3 post-refactor bugs (COMMANDER_META, PRECON_INDEX, startup)
Task 1: Move BUILTIN_COMMANDERS + load_commander_meta() to shared.py
Fix import_routes.py to use _shared.COMMANDER_META (module ref)
Task 2: Rewrite precon.py to use _shared.PRECON_INDEX (module ref)
Task 3: Add @app.on_event('startup') safety net for uvicorn --reload
This commit is contained in:
1 parent
36077c94ab
commit
8a6fbfaa8a
4 files changed
+55
-49
No files matched your search
+15
-38
@@ -99,6 +99,8 @@ from routes.shared import (
|
||||
# EDHREC cache
|
||||
_edhrec_cache, _EDHREC_CACHE_TTL,
|
||||
_edhrec_cache_get, _edhrec_cache_set,
|
||||
# Commander meta
|
||||
load_commander_meta, BUILTIN_COMMANDERS,
|
||||
)
|
||||
|
||||
# Route modules
|
||||
@@ -151,6 +153,18 @@ app.include_router(import_router)
|
||||
app.include_router(lab_router)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def _on_startup():
|
||||
"""Safety net: ensure DB and precon index are initialized even when
|
||||
main() is bypassed (e.g. uvicorn lab_api:app --reload)."""
|
||||
import routes.shared as _shared
|
||||
_shared.init_collection_db()
|
||||
if not _shared.PRECON_INDEX:
|
||||
_shared.download_precon_database()
|
||||
if not _shared.COMMANDER_META:
|
||||
_shared.load_commander_meta()
|
||||
|
||||
|
||||
# ══════════════════════════════════════════════════════════════
|
||||
# In-Memory State (used by remaining endpoints)
|
||||
# ══════════════════════════════════════════════════════════════
|
||||
@@ -619,29 +633,6 @@ async def get_card_edhrec(cardId: int):
|
||||
return result
|
||||
|
||||
|
||||
# ══════════════════════════════════════════════════════════════
|
||||
# Commander Meta Mapping (loaded at startup)
|
||||
# ══════════════════════════════════════════════════════════════
|
||||
|
||||
BUILTIN_COMMANDERS = {
|
||||
"Edgar Markov": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["W","B","R"]}],
|
||||
"Atraxa, Praetors' Voice": [{"source": "edhrec", "archetype": "midrange", "colorIdentity": ["W","U","B","G"]}],
|
||||
"Korvold, Fae-Cursed King": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["B","R","G"]}],
|
||||
"Muldrotha, the Gravetide": [{"source": "edhrec", "archetype": "midrange", "colorIdentity": ["U","B","G"]}],
|
||||
"The Ur-Dragon": [{"source": "edhrec", "archetype": "midrange", "colorIdentity": ["W","U","B","R","G"]}],
|
||||
"Yuriko, the Tiger's Shadow": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["U","B"]}],
|
||||
"Krenko, Mob Boss": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["R"]}],
|
||||
"Meren of Clan Nel Toth": [{"source": "edhrec", "archetype": "midrange", "colorIdentity": ["B","G"]}],
|
||||
"Prossh, Skyraider of Kher": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["B","R","G"]}],
|
||||
"Kaalia of the Vast": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["W","B","R"]}],
|
||||
"Talrand, Sky Summoner": [{"source": "edhrec", "archetype": "control", "colorIdentity": ["U"]}],
|
||||
"Omnath, Locus of Creation": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["W","U","R","G"]}],
|
||||
"Teysa Karlov": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["W","B"]}],
|
||||
"Lathril, Blade of the Elves": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["B","G"]}],
|
||||
"Breya, Etherium Shaper": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["W","U","B","R"]}],
|
||||
}
|
||||
|
||||
|
||||
# ══════════════════════════════════════════════════════════════
|
||||
# Python Simulator API
|
||||
# ══════════════════════════════════════════════════════════════
|
||||
@@ -4405,21 +4396,7 @@ def resolve_forge_decks_dir() -> str:
|
||||
return ""
|
||||
|
||||
|
||||
def load_commander_meta():
|
||||
"""Load commander meta mapping from file or use builtins."""
|
||||
global COMMANDER_META
|
||||
meta_path = Path(__file__).parent / "commander-meta.json"
|
||||
if meta_path.exists():
|
||||
try:
|
||||
with open(meta_path, "r", encoding="utf-8") as f:
|
||||
COMMANDER_META = json.load(f)
|
||||
log.info(f" Meta: Loaded {len(COMMANDER_META)} commanders from {meta_path}")
|
||||
return
|
||||
except Exception as e:
|
||||
log.warning(f" WARNING: Failed to load commander-meta.json: {e}")
|
||||
|
||||
COMMANDER_META = BUILTIN_COMMANDERS
|
||||
log.info(f" Meta: {len(COMMANDER_META)} built-in commanders")
|
||||
# load_commander_meta() is now in routes/shared.py
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -15,8 +15,8 @@ from typing import Optional
|
||||
from fastapi import APIRouter, HTTPException, BackgroundTasks
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
import routes.shared as _shared
|
||||
from routes.shared import (
|
||||
COMMANDER_META,
|
||||
ImportUrlRequest,
|
||||
ImportTextRequest,
|
||||
MetaFetchRequest,
|
||||
@@ -74,7 +74,7 @@ async def import_from_text(req: ImportTextRequest):
|
||||
async def list_meta_commanders():
|
||||
"""List available commanders in the meta mapping."""
|
||||
commanders = []
|
||||
for name, entries in COMMANDER_META.items():
|
||||
for name, entries in _shared.COMMANDER_META.items():
|
||||
entry = entries[0] if entries else {}
|
||||
commanders.append({
|
||||
"name": name,
|
||||
@@ -90,7 +90,7 @@ async def search_meta_commanders(q: str = ""):
|
||||
"""Search commanders by partial name match."""
|
||||
query = q.lower()
|
||||
matches = []
|
||||
for name, entries in COMMANDER_META.items():
|
||||
for name, entries in _shared.COMMANDER_META.items():
|
||||
if query in name.lower():
|
||||
entry = entries[0] if entries else {}
|
||||
matches.append({
|
||||
|
||||
+3
-8
@@ -15,13 +15,8 @@ from pathlib import Path
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from routes.shared import (
|
||||
CFG,
|
||||
PRECON_INDEX,
|
||||
PRECON_DIR,
|
||||
download_precon_database,
|
||||
log,
|
||||
)
|
||||
import routes.shared as _shared # module reference, not value import
|
||||
from routes.shared import CFG, PRECON_DIR, download_precon_database, log
|
||||
|
||||
router = APIRouter(tags=["precon"])
|
||||
|
||||
@@ -29,7 +24,7 @@ router = APIRouter(tags=["precon"])
|
||||
@router.get("/api/lab/precons")
|
||||
async def list_precons():
|
||||
"""List all available precon decks."""
|
||||
return {"precons": PRECON_INDEX}
|
||||
return {"precons": _shared.PRECON_INDEX} # reads current value every call
|
||||
|
||||
|
||||
@router.post("/api/lab/precons/install")
|
||||
|
||||
@@ -148,6 +148,40 @@ class BatchState:
|
||||
active_batches: dict[str, BatchState] = {}
|
||||
COMMANDER_META: dict = {}
|
||||
|
||||
BUILTIN_COMMANDERS: dict = {
|
||||
"Edgar Markov": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["W","B","R"]}],
|
||||
"Atraxa, Praetors' Voice": [{"source": "edhrec", "archetype": "midrange", "colorIdentity": ["W","U","B","G"]}],
|
||||
"Korvold, Fae-Cursed King": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["B","R","G"]}],
|
||||
"Muldrotha, the Gravetide": [{"source": "edhrec", "archetype": "midrange", "colorIdentity": ["U","B","G"]}],
|
||||
"The Ur-Dragon": [{"source": "edhrec", "archetype": "midrange", "colorIdentity": ["W","U","B","R","G"]}],
|
||||
"Yuriko, the Tiger's Shadow": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["U","B"]}],
|
||||
"Krenko, Mob Boss": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["R"]}],
|
||||
"Meren of Clan Nel Toth": [{"source": "edhrec", "archetype": "midrange", "colorIdentity": ["B","G"]}],
|
||||
"Prossh, Skyraider of Kher": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["B","R","G"]}],
|
||||
"Kaalia of the Vast": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["W","B","R"]}],
|
||||
"Talrand, Sky Summoner": [{"source": "edhrec", "archetype": "control", "colorIdentity": ["U"]}],
|
||||
"Omnath, Locus of Creation": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["W","U","R","G"]}],
|
||||
"Teysa Karlov": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["W","B"]}],
|
||||
"Lathril, Blade of the Elves": [{"source": "edhrec", "archetype": "aggro", "colorIdentity": ["B","G"]}],
|
||||
"Breya, Etherium Shaper": [{"source": "edhrec", "archetype": "combo", "colorIdentity": ["W","U","B","R"]}],
|
||||
}
|
||||
|
||||
|
||||
def load_commander_meta() -> None:
|
||||
"""Load commander meta mapping from file or fall back to builtins."""
|
||||
global COMMANDER_META
|
||||
meta_path = Path(__file__).parent.parent / "commander-meta.json"
|
||||
if meta_path.exists():
|
||||
try:
|
||||
with open(meta_path, "r", encoding="utf-8") as f:
|
||||
COMMANDER_META = json.load(f)
|
||||
log.info(f" Meta: Loaded {len(COMMANDER_META)} commanders from {meta_path}")
|
||||
return
|
||||
except Exception as e:
|
||||
log.warning(f" WARNING: Failed to load commander-meta.json: {e}")
|
||||
COMMANDER_META = BUILTIN_COMMANDERS
|
||||
log.info(f" Meta: {len(COMMANDER_META)} built-in commanders")
|
||||
|
||||
|
||||
# ══════════════════════════════════════════════════════════════
|
||||
# Pydantic Models
|
||||
|
||||
Reference in new issue
Block a user