Initial commit

This commit is contained in:
kfj001 committed 2026-09-06 10:18:26 -07:00
commit 5f2db08b43
100 files changed
+16985

No files matched your search

+84
View File
@@ -0,0 +1,84 @@
"""`dashboard` CLI subcommand (spec §5, task t_b38e9af2).
Wires the dashboard server into the shared `scraper/cli.py` ADDITIVELY +
DEFENSIVELY, mirroring parser/correlate/analyze (the guarded `register()`
pattern): `cli.py` calls `register(sub)` inside a try/except and adds its
handler without touching any sibling handler. The `dashboard` name does not
collide.
This is the CLI/app entry point per the task contract. The server itself lives
in `scraper/dashboard/server.py`; this module just parses flags and calls
`server.serve(...)`.
"""
from __future__ import annotations
import logging
from .. import relational
from . import server as _server
log = logging.getLogger("scraper.dashboard_cli")
def _already_registered(sub, name: str) -> bool:
actions = getattr(sub, "_choices_actions", [])
return any(getattr(a, "name", None) == name for a in actions)
def register(sub) -> None:
"""Register the `dashboard` subcommand (guarded — skip if a sibling owns it)."""
if _already_registered(sub, "dashboard"):
return
pd = sub.add_parser(
"dashboard",
help="serve the legislative dashboard (API + static UI)",
description=("Serve the legislative dashboard. Reads the relational DB "
"(bills/committees/members + bill_tags) and serves the "
"API_CONTRACT.md endpoints + the static frontend."),
)
pd.add_argument("--host", default="127.0.0.1",
help="bind host (default 127.0.0.1)")
pd.add_argument("--port", type=int, default=8000,
help="bind port (default 8000)")
pd.add_argument("--db", default=relational.DEFAULT_DB,
help="SQLite path (default db/daily_file.sqlite)")
pd.add_argument("--prefs", default="out/prefs.json",
help="preferences JSON file (default out/prefs.json)")
pd.add_argument("--auth", default="out/auth.json",
help="local-auth JSON file (default out/auth.json)")
pd.add_argument("--no-static", dest="static", action="store_false",
help="API only, no static frontend")
pd.add_argument("--log", action="store_true",
help="log HTTP requests to stderr")
pd.set_defaults(func=handle_dashboard)
def handle_dashboard(args) -> int:
"""CLI handler for the `dashboard` subcommand."""
return _server.serve(
host=args.host,
port=args.port,
db_path=args.db,
prefs_path=args.prefs,
auth_path=args.auth,
serve_static=getattr(args, "static", True),
log_on=getattr(args, "log", False),
)
def main(argv=None) -> int:
"""Direct invocation: `python -m scraper.dashboard_cli`."""
import argparse
p = argparse.ArgumentParser(
prog="scraper.dashboard_cli",
description="Serve the legislative dashboard.")
sub = p.add_subparsers(dest="command", required=True)
register(sub)
args = p.parse_args(argv)
return args.func(args)
if __name__ == "__main__":
import sys
sys.exit(main())