Spaces:
Runtime error
Runtime error
| # app/main.py | |
| import logging | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI, Request, status | |
| from fastapi.responses import JSONResponse | |
| from fastapi.middleware.gzip import GZipMiddleware | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from app.core.config import APP_NAME # For logger naming | |
| from app.core.logging import configure_logging # Import the new logging configuration | |
| from app.core.exceptions import ServiceError, ModelNotDownloadedError # Import custom exceptions | |
| # Import your routers | |
| # Adjust these imports if your router file names or structure are different | |
| from app.routers import ( | |
| grammar, tone, voice, inclusive_language, | |
| readability, paraphrase, translate, synonyms, rewrite, analyze | |
| ) | |
| # Configure logging at the very beginning | |
| configure_logging() | |
| logger = logging.getLogger(f"{APP_NAME}.main") | |
| async def lifespan(app: FastAPI): | |
| """ | |
| Context manager for application startup and shutdown events. | |
| Models are now lazily loaded, so no explicit loading here. | |
| """ | |
| logger.info("Application starting up...") | |
| # Any other global startup tasks can go here | |
| yield | |
| logger.info("Application shutting down...") | |
| # Any global shutdown tasks can go here (e.g., closing database connections) | |
| app = FastAPI( | |
| title="Writing Assistant API (Local)", | |
| description="Local API for the desktop Writing Assistant application, providing various NLP functionalities.", | |
| version="0.1.0", | |
| lifespan=lifespan, | |
| ) | |
| # --- Middleware Setup --- | |
| app.add_middleware(GZipMiddleware, minimum_size=500) | |
| # CORS Middleware for local development/desktop app scenarios | |
| # Allows all origins for local testing. Restrict as needed for deployment. | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], # Adjust this for specific origins in a web deployment | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # --- Global Exception Handlers --- | |
| async def service_error_handler(request: Request, exc: ServiceError): | |
| """ | |
| Handles custom ServiceError exceptions, returning a structured JSON response. | |
| """ | |
| logger.error(f"Service Error caught for path {request.url.path}: {exc.detail}", exc_info=True) | |
| return JSONResponse( | |
| status_code=exc.status_code, | |
| content=exc.to_dict(), # Use the to_dict method from ServiceError | |
| ) | |
| async def model_not_downloaded_error_handler(request: Request, exc: ModelNotDownloadedError): | |
| """ | |
| Handles ModelNotDownloadedError exceptions, informing the client a model is missing. | |
| """ | |
| logger.warning(f"Model Not Downloaded Error caught for path {request.url.path}: Model '{exc.model_id}' is missing for feature '{exc.feature_name}'.") | |
| return JSONResponse( | |
| status_code=exc.status_code, | |
| content=exc.to_dict(), # Use the to_dict method from ModelNotDownloadedError | |
| ) | |
| async def general_exception_handler(request: Request, exc: Exception): | |
| """ | |
| Handles all other unhandled exceptions, returning a generic server error. | |
| """ | |
| logger.exception(f"Unhandled exception caught for path {request.url.path}: {exc}") # Use logger.exception to log traceback | |
| return JSONResponse( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| content={ | |
| "detail": "An unexpected internal server error occurred.", | |
| "error_type": "InternalServerError", | |
| }, | |
| ) | |
| # --- Include Routers --- | |
| # Note: You will need to create/update these files in app/routers/ | |
| # if they don't exist or don't match the new async service methods. | |
| for router, tag in [ | |
| (grammar.router, "Grammar"), | |
| (tone.router, "Tone"), | |
| (voice.router, "Voice"), | |
| (inclusive_language.router, "Inclusive Language"), | |
| (readability.router, "Readability"), | |
| (rewrite.router, "Rewrite"), | |
| (analyze.router, "Analyze"), | |
| (paraphrase.router, "Paraphrasing"), | |
| (translate.router, "Translation"), | |
| (synonyms.router, "Synonyms") | |
| ]: | |
| app.include_router(router, tags=[tag]) | |
| # --- Root Endpoint --- | |
| async def root(): | |
| """ | |
| Root endpoint for health check. | |
| """ | |
| return {"message": "Writing Assistant API is running!"} |