mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-28 13:01:38 +00:00
* stash some changes * add more robust testing * mypy * point PR at V5 * introduce spec file * codespell * test fix * fix workflow environment setup * fix workflow environment setup * fix workflow environment setup * add pyyaml to dependencies * split lint jobs * fix workflow environment setup * fix workflow environment setup * workflow env setup * workflow env setup * clean up code comments * add auth hook entrypoints * codespell * add codegen feature * codespell * move _unpack into dispatchers for consistency with codegen packages * surface nested models in the response * fix missing coverage in CI * socrata updates * test fix * detect plotly output * add --include and --exclude flags from generate-extension command * cap test matrix at python 3.14 * no useless comments * platform controller command description split * merge URL overloads from path params * exclude none and unset from model dump --------- Co-authored-by: deeleeramone <> Co-authored-by: Copilot <copilot@github.com>
48 lines
1.5 KiB
Python
48 lines
1.5 KiB
Python
"""Shared response unwrapping used by both the HTTP dispatcher and codegen."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json as _json
|
|
import re as _re
|
|
from typing import Any
|
|
|
|
_BARE_ASTERISK = _re.compile(r":\s*\*\s*(?=[,}\]])")
|
|
|
|
|
|
def safe_json_loads(text: str) -> Any:
|
|
"""Parse JSON text, sanitizing common upstream quirks first."""
|
|
try:
|
|
return _json.loads(text)
|
|
except ValueError:
|
|
sanitized = _BARE_ASTERISK.sub(": null", text)
|
|
return _json.loads(sanitized)
|
|
|
|
|
|
def unpack_response(
|
|
payload: Any,
|
|
) -> tuple[list[dict[str, Any]], dict[str, Any]]:
|
|
"""Split a raw API payload into (rows, metadata)."""
|
|
if isinstance(payload, list):
|
|
if len(payload) == 1:
|
|
return unpack_response(payload[0])
|
|
rows = [r for r in payload if isinstance(r, dict)]
|
|
if rows:
|
|
return rows, {}
|
|
return [{"value": r} for r in payload], {}
|
|
if not isinstance(payload, dict):
|
|
return [{"value": payload}], {}
|
|
list_keys = [k for k, v in payload.items() if isinstance(v, list)]
|
|
if len(list_keys) == 1:
|
|
key = list_keys[0]
|
|
items = payload[key]
|
|
rows = [r for r in items if isinstance(r, dict)]
|
|
if not rows and items:
|
|
rows = [{"value": r} for r in items]
|
|
metadata = {k: v for k, v in payload.items() if k != key}
|
|
return rows, metadata
|
|
if len(payload) == 1:
|
|
only_value = next(iter(payload.values()))
|
|
if isinstance(only_value, (list, dict)):
|
|
return unpack_response(only_value)
|
|
return [payload], {}
|