import os from granian.cli import cli as granian_cli from pydantic import BaseModel, Field from pydantic_settings import BaseSettings, SettingsConfigDict class WorkersSettings(BaseModel): per_core: int = Field(1, ge=1) max: int | None = Field(None, ge=1) exact: int | None = Field(None, ge=1) @property def count(self) -> int: # usage of "or" operator: values here are not allowed to be 0 base = self.exact or (self.per_core * (os.cpu_count() or 1)) return min(base, self.max or base) class BindSettings(BaseModel): host: str = "0.0.0.0" port: int = 8000 class Settings(BaseSettings): model_config = SettingsConfigDict( env_prefix="ADVENT22__", env_nested_delimiter="__", ) workers: WorkersSettings = WorkersSettings() bind: BindSettings = BindSettings() def start(): os.environ["ADVENT22__PRODUCTION_MODE"] = "true" settings = Settings() granian_cli( [ "--host", settings.bind.host, "--port", settings.bind.port, "--workers", settings.workers.count, "--interface", "asgi", "--loop", "uvloop", "--process-name", "advent22", # app "advent22_api.app:app", ], auto_envvar_prefix="GRANIAN", standalone_mode=False, )