Application settings in one module¶
The environment and the flags are read in one module of the package, settings.py, through a
pydantic_settings.BaseSettings subclass. The rest of the code gets the values from
get_settings().
What to read¶
Settingsreads the variables with the prefixAPP_and the.envfile.case_sensitive=FalsebindsAPP_DEBUGandapp_debugto the same field.extra="ignore"ignores the entries of the.envfile that the class does not declare; the variables of the process that it does not declare are ignored in any case.get_settingsis cached withlru_cache: the settings are built and validated once per process. A test callsget_settings.cache_clear()after it changes the environment.- An endpoint takes the settings with
Depends(get_settings), and a test replaces them withapp.dependency_overrides[get_settings]. A module that callsget_settings()when it is imported keeps the first settings and cannot be overridden.
What to adapt¶
- The fields and the prefix are an example. Declare the variables of your package, with their types and defaults.
- Each layer or package has its own
settings.py.
References¶
code/app/settings.py:11-23¶
the settings class: prefix, .env file, case-insensitive names and typed fields
class Settings(BaseSettings):
"""The variables of the package, read with the prefix `APP_` from the environment and `.env`."""
model_config = SettingsConfigDict(
env_prefix="APP_",
env_file=".env",
case_sensitive=False,
extra="ignore",
)
debug: bool = False
log_level: str = "INFO"
database_url: str = Field(default="sqlite:///./app.db")
code/app/settings.py:26-29¶
the function that the rest of the code calls: cached, so the settings are built once
@lru_cache
def get_settings() -> Settings:
"""Return the settings of the process, built and validated once."""
return Settings()
code/app/api/v1/routers/status.py¶
an endpoint takes the settings as a dependency, so a test replaces them with app.dependency_overrides[get_settings]
"""An endpoint that reads the settings through a dependency, so a test can replace them."""
from typing import Annotated
from fastapi import APIRouter, Depends
from app.api.v1.schemas.responses.status import StatusResponse
from app.settings import Settings, get_settings
router = APIRouter()
@router.get("/status")
def read_status(settings: Annotated[Settings, Depends(get_settings)]) -> StatusResponse:
"""Say whether the service runs in debug mode."""
return StatusResponse(debug=settings.debug)
https://fastapi.tiangolo.com/advanced/settings/#settings-and-testing¶
replacing the settings in a test with dependency_overrides
Cited by¶
settings-module(BTCONF001)- CES-76