viewer
¶
FastAPI dashboard for browsing a trendify.db in the browser.
HoverMode
¶
Bases: StrEnum
Tooltip behavior when hovering over the plot.
X_UNIFIED
class-attribute
instance-attribute
¶
Single tooltip showing all series at the hovered x value.
Y_UNIFIED
class-attribute
instance-attribute
¶
Single tooltip showing all series at the hovered y value.
InterpMode
¶
LineMode
¶
Bases: StrEnum
Controls whether traces are drawn as lines, markers, or both.
PlotConfig
¶
Bases: BaseModel
Complete serialisable state of a dashboard plot.
line_mode
class-attribute
instance-attribute
¶
line_mode: LineMode = LineMode.LINES_AND_MARKERS
Whether traces render as lines, markers, or both.
interp
class-attribute
instance-attribute
¶
interp: InterpMode = InterpMode.LINEAR
Interpolation method drawn between data points.
hover
class-attribute
instance-attribute
¶
Tooltip behavior on hover.
show_spike
class-attribute
instance-attribute
¶
show_spike: bool = True
Whether to draw spike lines from the hovered point to each axis.
max_points
class-attribute
instance-attribute
¶
Maximum number of data points per trace returned by the server. When the raw data exceeds this limit the server downsamples using uniform x-domain buckets (equal coverage across the x range regardless of variable point spacing). None disables downsampling and returns all points.
TagNode
¶
Bases: BaseModel
One node of the sidebar's nested tag hierarchy.
children
instance-attribute
¶
Nested tag nodes one level below this one.
has_records
instance-attribute
¶
has_records: bool
Whether records are tagged with this exact node's key, as opposed to only a
descendant's.
record_kinds
instance-attribute
¶
Kinds of records tagged with this exact node's key.
size_bytes
instance-attribute
¶
size_bytes: int
Total payload bytes of records tagged with this exact node's key (0 for a node with
no records of its own). Used by the viewer's background hydration to pick the largest
sibling tag at whatever level the user is currently browsing.
search_blob
¶
search_blob() -> str
Lowercase text of this node's label and every descendant's label, for substring search matching without needing to walk the tree again client-side.
Source code in src/trendify/viewer/tag_tree.py
| Python | |
|---|---|
subtree_kinds
¶
Union of this node's own record_kinds and every descendant's, so a folder can be
filtered by record type without needing to walk the tree again client-side (a folder
should stay visible under a "table" filter if any record anywhere inside it is a
table, even if the folder itself has no records of its own).
Source code in src/trendify/viewer/tag_tree.py
create_app
¶
create_app(
db_path: Path | str,
*,
show_db_path: bool = True,
cors_origins: Sequence[str] = (),
) -> FastAPI
Builds the dashboard FastAPI app for db_path.
The app runs on its own or mounted inside another FastAPI/Starlette app, either at a path
prefix (host.mount("/viz", create_app(db_path))) or on its own hostname, and needs nothing
from the host: no lifespan, no shared state. Pages and scripts build their URLs from the
prefix the app is mounted under, so they work wherever it is served.
All database and plot-building work runs on two dedicated worker threads
(app.state.runner for real requests and app.state.hydration_runner for background
prefetch, see routes.api), each with its own read-only RecordStore connection opened on
first use. A slow request therefore never blocks the event loop, which matters when that loop
is shared with a host site's other endpoints, and a prefetch never queues ahead of a click.
A SQLite connection belongs to the thread that opens it, which is why each one lives
entirely on its worker thread. The lifespan only closes those connections at shutdown; a
mounted app doesn't get one, and its connections then close with the interpreter.
This app is meant to run as a single process (each process would keep its own caches).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
db_path
|
Path | str
|
path to the |
required |
show_db_path
|
bool
|
show the server-side path of |
True
|
cors_origins
|
Sequence[str]
|
origins whose browser JavaScript may call this app's API
from another origin (an exact list; no wildcard is added for you). Empty by
default, which adds no CORS headers. Not needed to show the viewer in an |
()
|
Returns:
| Type | Description |
|---|---|
FastAPI
|
the configured app, ready for |
Source code in src/trendify/viewer/app.py
create_app_from_env
¶
create_app, reading db_path from the TRENDIFY_DB_PATH environment variable instead of
a direct argument.
This exists solely as a uvicorn ASGI factory target (uvicorn.run(..., factory=True)) for
trendify serve --reload: uvicorn's reload mode re-imports the app in a fresh subprocess on
every file change, so it needs an importable module:attribute string rather than a live app
instance; there is no other way to hand it a runtime value like db_path across that
re-import boundary.
Source code in src/trendify/viewer/app.py
build_tag_tree
¶
build_tag_tree(store: RecordStore) -> list[TagNode]
Walks store.tag_tree()'s flat, tuple-encoded tags into a nested TagNode hierarchy: a
tag ("a", "b") becomes a folder "a" containing a leaf "b". A tuple prefix (e.g. "a"
from that same tag) may never itself have been used as a real tag, so has_records is
tracked separately from children being non-empty, since a node can be a pure folder, a
pure leaf, or both at once.