app_config: reject non-object config.json sections with AppConfigError
Claude-Session: https://claude.ai/code/session_01VPNF37MP9Kuv62B1VBrZ1b
This commit is contained in:
@@ -66,6 +66,8 @@ class AppConfig:
|
||||
|
||||
|
||||
def _check_keys(section: Dict[str, Any], known: set, where: str) -> None:
|
||||
if not isinstance(section, dict):
|
||||
raise AppConfigError(f"config.json: {where} must be a JSON object")
|
||||
unknown = sorted(set(section) - known)
|
||||
if unknown:
|
||||
raise AppConfigError(
|
||||
@@ -141,6 +143,8 @@ def load_app_config(path: str = CONFIG_PATH) -> AppConfig:
|
||||
app.scan_timeframes = [Timeframe[n] for n in names]
|
||||
|
||||
pair_section = raw.get("pairs", {})
|
||||
if not isinstance(pair_section, dict):
|
||||
raise AppConfigError('config.json: "pairs" must be a JSON object')
|
||||
for symbol, overrides in pair_section.items():
|
||||
if symbol not in PAIR_INFO:
|
||||
raise AppConfigError(
|
||||
|
||||
+16
@@ -2661,6 +2661,22 @@ def _():
|
||||
assert telegram_channel_id(app) == ""
|
||||
|
||||
|
||||
@test("app_config: non-object sections raise AppConfigError")
|
||||
def _():
|
||||
for payload in (
|
||||
{"telegram": None},
|
||||
{"telegram": "oops"},
|
||||
{"scanning": 5},
|
||||
{"pairs": ["oops"]},
|
||||
{"pairs": {"XAU/USD": ["blocked_hours_utc"]}},
|
||||
):
|
||||
try:
|
||||
load_app_config(_write_json(payload))
|
||||
assert False, f"should have raised for {payload}"
|
||||
except AppConfigError:
|
||||
pass
|
||||
|
||||
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
# SUMMARY
|
||||
# ══════════════════════════════════════════════════════════════════════
|
||||
|
||||
Reference in New Issue
Block a user