"""App factory and lifespan.""" import logging from contextlib import asynccontextmanager from fastapi import FastAPI from app.api import health from app.config import Settings from app.db.engine import close_db_connection, init_db from app.logging_config import configure_logging @asynccontextmanager async def lifespan(app: FastAPI): """Application lifespan: startup and shutdown hooks. Handles database initialization, logging configuration, and cleanup on shutdown. """ configure_logging() logging.info("SlabUploader starting up") await init_db() yield logging.info("SlabUploader shutting down") await close_db_connection() def create_app(settings: Settings | None = None) -> FastAPI: """Create a fresh FastAPI app instance. Each call produces an independent app with its own database connection and cleared dependency overrides. This is the factory used by tests. Args: settings: Application settings. Uses env vars if None. Returns: Configured FastAPI application. """ if settings is None: settings = Settings() settings.validate() app = FastAPI(title="SlabUploader", version="0.1.0", lifespan=lifespan) app.include_router(health.router) return app