generated from john/python-template
uvicorn startup
This commit is contained in:
@@ -0,0 +1,20 @@
|
|||||||
|
import uvicorn
|
||||||
|
|
||||||
|
from .config import LOGGING_CONFIG
|
||||||
|
from .config import get_settings
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
settings = get_settings()
|
||||||
|
uvicorn.run(
|
||||||
|
"transcription.app:create_app",
|
||||||
|
factory=True,
|
||||||
|
host=settings.server.host,
|
||||||
|
port=settings.server.port,
|
||||||
|
log_level=LOGGING_CONFIG.get("root", {}).get("level", "info").lower(),
|
||||||
|
reload=settings.server.reload,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -16,6 +16,7 @@ from fastapi.staticfiles import StaticFiles
|
|||||||
|
|
||||||
from .api.errors import register_error_handlers
|
from .api.errors import register_error_handlers
|
||||||
from .api.health import router as health_router
|
from .api.health import router as health_router
|
||||||
|
from .config import Settings
|
||||||
from .config import configure_logging
|
from .config import configure_logging
|
||||||
from .config import get_settings
|
from .config import get_settings
|
||||||
from .db import create_all
|
from .db import create_all
|
||||||
@@ -73,14 +74,14 @@ async def _recover_stale_processing_jobs(app: FastAPI) -> None:
|
|||||||
logger.warning("Recovered %s stale processing job(s) at startup", recovered)
|
logger.warning("Recovered %s stale processing job(s) at startup", recovered)
|
||||||
|
|
||||||
|
|
||||||
def create_app() -> FastAPI:
|
def create_app(settings: Settings | None = None) -> FastAPI:
|
||||||
"""Create and configure the FastAPI application."""
|
"""Create and configure the FastAPI application."""
|
||||||
app = FastAPI(title="Transcription", lifespan=_lifespan)
|
app = FastAPI(title="Transcription", lifespan=_lifespan)
|
||||||
settings = get_settings()
|
active_settings = settings or get_settings()
|
||||||
app.state.settings = settings
|
app.state.settings = active_settings
|
||||||
app.mount(
|
app.mount(
|
||||||
"/uploads",
|
"/uploads",
|
||||||
StaticFiles(directory=settings.upload_dir, check_dir=False),
|
StaticFiles(directory=active_settings.upload_dir, check_dir=False),
|
||||||
name="uploads",
|
name="uploads",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -92,6 +93,10 @@ def create_app() -> FastAPI:
|
|||||||
async def ui_redirect() -> RedirectResponse:
|
async def ui_redirect() -> RedirectResponse:
|
||||||
return RedirectResponse(url="/ui/upload", status_code=status.HTTP_307_TEMPORARY_REDIRECT)
|
return RedirectResponse(url="/ui/upload", status_code=status.HTTP_307_TEMPORARY_REDIRECT)
|
||||||
|
|
||||||
|
@app.get("/healthz")
|
||||||
|
def health() -> dict[str, str]:
|
||||||
|
return {"status": "ok"}
|
||||||
|
|
||||||
register_error_handlers(app)
|
register_error_handlers(app)
|
||||||
register_pages(app)
|
register_pages(app)
|
||||||
app.include_router(health_router)
|
app.include_router(health_router)
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ are resolved by the provider adapters, not here.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import logging.config
|
import logging.config
|
||||||
from contextvars import ContextVar
|
|
||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
|
from functools import cache
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from pydantic import ConfigDict
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
from pydantic_settings import BaseSettings
|
from pydantic_settings import BaseSettings
|
||||||
from pydantic_settings import SettingsConfigDict
|
from pydantic_settings import SettingsConfigDict
|
||||||
@@ -22,13 +24,26 @@ class Provider(StrEnum):
|
|||||||
OPENROUTER = "openrouter"
|
OPENROUTER = "openrouter"
|
||||||
|
|
||||||
|
|
||||||
|
class ServerSettings(BaseModel):
|
||||||
|
model_config = ConfigDict(frozen=True)
|
||||||
|
|
||||||
|
host: str = "0.0.0.0"
|
||||||
|
port: int = 8000
|
||||||
|
log_level: Literal["critical", "error", "warning", "info", "debug", "trace"] = "info"
|
||||||
|
reload: bool = False
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
model_config = SettingsConfigDict(
|
model_config = SettingsConfigDict(
|
||||||
env_file=".env",
|
env_file=".env",
|
||||||
env_file_encoding="utf-8",
|
env_file_encoding="utf-8",
|
||||||
extra="ignore",
|
extra="ignore",
|
||||||
|
cli_parse_args=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# --- NiceGUI Server ---
|
||||||
|
server: ServerSettings = Field(default_factory=ServerSettings)
|
||||||
|
|
||||||
# --- AI provider ---
|
# --- AI provider ---
|
||||||
provider: Provider = Provider.OPENROUTER
|
provider: Provider = Provider.OPENROUTER
|
||||||
openrouter_api_key: str
|
openrouter_api_key: str
|
||||||
@@ -64,15 +79,9 @@ class Settings(BaseSettings):
|
|||||||
return self.environment in {"development", "test"}
|
return self.environment in {"development", "test"}
|
||||||
|
|
||||||
|
|
||||||
_settings: ContextVar[Settings | None] = ContextVar("settings", default=None)
|
@cache
|
||||||
|
|
||||||
|
|
||||||
def get_settings(**kwargs) -> Settings:
|
def get_settings(**kwargs) -> Settings:
|
||||||
settings = _settings.get()
|
return Settings(**kwargs)
|
||||||
if settings is None:
|
|
||||||
settings = Settings(**kwargs) # pyright: ignore[reportCallIssue]
|
|
||||||
_settings.set(settings)
|
|
||||||
return settings
|
|
||||||
|
|
||||||
|
|
||||||
LOGGING_CONFIG: dict[str, object] = {
|
LOGGING_CONFIG: dict[str, object] = {
|
||||||
|
|||||||
Reference in New Issue
Block a user