Complete worked example
python
import os
from typing import Literal
from pydantic import Field, ValidationError
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_prefix="LESSON_API_", env_file=None)
mode: Literal["local", "test"] = "local"
page_size: int = Field(default=10, ge=1, le=20)
def inspect_example(request):
keys = ["LESSON_API_MODE", "LESSON_API_PAGE_SIZE"]
before = {key: os.environ.get(key) for key in keys}
try:
for key in keys:
os.environ.pop(key, None)
for key, value in request.get("env", {}).items():
assert key in ("MODE", "PAGE_SIZE")
os.environ["LESSON_API_" + key] = value
try:
settings = Settings(_env_file=None, _secrets_dir=None,
**request.get("init", {}))
return {"value": settings.model_dump()}
except ValidationError as error:
return {"error": sorted({e["type"] for e in error.errors()})}
finally:
for key, value in before.items():
if value is None:
os.environ.pop(key, None)
else:
os.environ[key] = value- Reasoning
- The inspection helper temporarily sets only the two teaching environment keys and restores their previous values in a finally block. It then creates Settings with the explicitly declared sources and optional initialization values. An environment page size of "5" becomes integer 5, and an explicit initialization page size can override the environment value. A mode outside the declared Literal vocabulary fails validation. The helper does not clear the complete process environment or print it. Those details matter even in a small fixture: isolation should protect unrelated settings rather than merely hoping that a developer computer contains no sensitive variables.