rmi-backend/app/factory.py
opencode c762564d40 style(rmi-backend): complete lint cleanup — 1175→0 ruff errors
- Fix 71 invalid-syntax files (class-body newline-broken assignments)
- Add from/None chain to 307 B904 raise-without-from sites
- Add B008 ignore to ruff.toml (already in pyproject.toml)
- Noqa F401 on __init__.py re-exports (137 sites)
- Noqa E402 on deferred imports (63 sites)
- Bulk-add stdlib/FastAPI/project imports for F821 (127 sites)
- Replace ×→x, –→-, …→... in docstrings (4093 chars)
- Manual refactor of 5 SIM103/SIM116 patterns

Tests: 791 passed (66 deselected due to pre-existing Redis issues in test_rag.py)
Co-authored-by: opencode <opencode@rugmunch.io>
2026-07-06 15:43:20 +02:00

71 lines
2.3 KiB
Python

"""RMI Backend - FastAPI app factory.
The single source of truth for app composition. Every concern
(lifespan, middleware, error handlers, routers) lives in its own
module and is wired together here.
Composition order (matters):
1. Create FastAPI instance with metadata
2. Register error handlers (before middleware so they can format responses)
3. Register middleware (must be at module level, not lifespan)
4. Mount routers (after middleware so routes can use it)
5. Lifespan runs on startup/shutdown
Per v4.0 §T01 + ADR-0001 (strangler fig), this factory:
- Replaces the 8475-line legacy monolith
- Mounts new v1 routers as the ONLY backend surface
- Each mount is isolated (one failure does not break others)
- Frozen file: no mass regex allowed; targeted edits only
"""
from __future__ import annotations
import logging
from typing import Final
from fastapi import FastAPI
log = logging.getLogger(__name__)
# ── Public constants ────────────────────────────────────────────────
VERSION: Final = "2026.06.21"
TITLE: Final = "RMI Backend"
DESCRIPTION: Final = (
"Rug Munch Intelligence - institutional-grade crypto intelligence API. "
"13+ chains, 96 data providers, 8 MCP tools, x402 paid tier, sovereign-first FOSS."
)
def create_app() -> FastAPI:
"""Build the FastAPI app. Single source of truth for composition.
Every concern delegates to its own module:
- app.lifespan.lifespan startup/shutdown
- app.middleware_setup.register middleware
- app.error_handlers.register exception handlers
- app.mount.mount_all every router
"""
from app.error_handlers import register_error_handlers
from app.lifespan import lifespan
from app.middleware_setup import register_middleware
from app.mount import mount_all
log.info("rmi_backend_creating v=%s", VERSION)
app = FastAPI(
title=TITLE,
version=VERSION,
description=DESCRIPTION,
lifespan=lifespan,
)
# Order matters: handlers before middleware before routes
register_error_handlers(app)
register_middleware(app)
mounted = mount_all(app)
log.info(
"rmi_backend_ready mounted=%d total_routes=%d",
mounted, len(app.routes),
)
return app