verbose live UI + tool-level SSE events + Groq default + regression tests
This commit is contained in:
57
api/tools/schema.py
Normal file
57
api/tools/schema.py
Normal file
@@ -0,0 +1,57 @@
|
||||
"""Warehouse schema retrieval.
|
||||
|
||||
Physical layer via SQLAlchemy's Inspector against the active dataset's
|
||||
Postgres schema; semantic layer (table/column descriptions, metric catalog)
|
||||
from YAML files under `api/datasets/<name>/`.
|
||||
|
||||
Cached on first call — the schema is stable for a process's lifetime.
|
||||
Restart the api to pick up a dataset switch or YAML edits.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from functools import lru_cache
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import inspect
|
||||
|
||||
from api.config import get_settings
|
||||
from api.datasets import read_yaml
|
||||
from api.tools.db import get_engine
|
||||
from api.tools.types import Column, Metric, SchemaContext, Table
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def load_schema() -> SchemaContext:
|
||||
dataset = get_settings().dataset
|
||||
docs = read_yaml(dataset, "schema_docs.yaml")
|
||||
metrics_yaml = read_yaml(dataset, "metrics.yaml")
|
||||
|
||||
# Postgres schema name comes from the dataset id; the schema_docs file
|
||||
# can override it, but normally they match.
|
||||
schema_name: str = docs.get("schema", dataset)
|
||||
table_descs: dict[str, dict[str, Any]] = docs.get("tables", {}) or {}
|
||||
|
||||
insp = inspect(get_engine())
|
||||
tables: dict[str, Table] = {
|
||||
name: Table(
|
||||
name=name,
|
||||
description=(desc := table_descs.get(name, {})).get("description"),
|
||||
columns=[
|
||||
Column.from_inspector(c, (desc.get("columns") or {}).get(c["name"]))
|
||||
for c in insp.get_columns(name, schema=schema_name)
|
||||
],
|
||||
)
|
||||
for name in insp.get_table_names(schema=schema_name)
|
||||
}
|
||||
|
||||
metrics: dict[str, Metric] = {
|
||||
name: Metric.from_spec(name, spec)
|
||||
for name, spec in (metrics_yaml.get("metrics", {}) or {}).items()
|
||||
}
|
||||
|
||||
return SchemaContext(schema=schema_name, tables=tables, metrics=metrics)
|
||||
|
||||
|
||||
def get_metric(name: str) -> Metric | None:
|
||||
return load_schema().metrics.get(name)
|
||||
Reference in New Issue
Block a user