docs: add AI code generation requirements and comprehensive Google-style docstrings
- Add AI code generation requirements to AGENTS.md - Add module-level docstrings to all 46 Python modules - Add detailed Google-style docstrings to all classes and functions - Remove all inline comments following self-documenting code principle - Include Args, Returns, Raises sections in function docstrings - Add Attributes and Examples sections to class docstrings
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
"""Infrastructure configuration."""
|
||||
"""Infrastructure configuration.
|
||||
|
||||
This module re-exports all configuration classes and the global
|
||||
settings instance for application configuration.
|
||||
"""
|
||||
|
||||
from app.infrastructure.config.settings import (
|
||||
AppConfig,
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
"""Application settings with composition pattern."""
|
||||
"""Application settings with composition pattern.
|
||||
|
||||
This module defines the application configuration using pydantic-settings.
|
||||
Provides typed configuration for database, Keycloak, security, and app settings.
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
from functools import cached_property
|
||||
@@ -8,14 +12,38 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Environment(str, Enum):
|
||||
"""Application environment modes."""
|
||||
"""Application environment modes.
|
||||
|
||||
Defines the available deployment environments.
|
||||
Each environment may have different configuration defaults.
|
||||
|
||||
Attributes:
|
||||
DEV: Development environment with debug features.
|
||||
PROD: Production environment with strict security.
|
||||
|
||||
Example:
|
||||
>>> if settings.environment == Environment.PROD:
|
||||
... enable_strict_security()
|
||||
"""
|
||||
|
||||
DEV = "dev"
|
||||
PROD = "prod"
|
||||
|
||||
|
||||
class AppConfig(BaseSettings):
|
||||
"""Application configuration."""
|
||||
"""Application configuration.
|
||||
|
||||
Contains general application settings like name, host, and port.
|
||||
|
||||
Attributes:
|
||||
name: Application display name.
|
||||
debug: Debug mode flag.
|
||||
host: Server bind host.
|
||||
port: Server bind port.
|
||||
|
||||
Example:
|
||||
>>> config = AppConfig(name="My API", port=8000)
|
||||
"""
|
||||
|
||||
name: str = "Blog API"
|
||||
debug: bool = False
|
||||
@@ -30,14 +58,27 @@ class AppConfig(BaseSettings):
|
||||
|
||||
|
||||
class DBConfig(BaseSettings):
|
||||
"""Database configuration."""
|
||||
"""Database configuration.
|
||||
|
||||
Contains database connection settings. Supports both SQLite for
|
||||
development and PostgreSQL for production.
|
||||
|
||||
Attributes:
|
||||
url: Full database URL (optional, can build from components).
|
||||
echo: Enable SQL query logging.
|
||||
host: Database server host.
|
||||
port: Database server port.
|
||||
user: Database username.
|
||||
password: Database password.
|
||||
name: Database name.
|
||||
|
||||
Example:
|
||||
>>> db_config = DBConfig(host="localhost", name="blog")
|
||||
"""
|
||||
|
||||
# For dev: sqlite+aiosqlite:///./blog.db
|
||||
# For prod: postgresql+asyncpg://user:pass@host:port/db
|
||||
url: str | None = None
|
||||
echo: bool = False
|
||||
|
||||
# PostgreSQL-specific settings (used in prod)
|
||||
host: str = "localhost"
|
||||
port: int = 5432
|
||||
user: str = "postgres"
|
||||
@@ -53,7 +94,17 @@ class DBConfig(BaseSettings):
|
||||
@field_validator("url")
|
||||
@classmethod
|
||||
def validate_url(cls, v: str | None) -> str | None:
|
||||
"""Validate database URL if provided."""
|
||||
"""Validate database URL if provided.
|
||||
|
||||
Args:
|
||||
v: Database URL string to validate.
|
||||
|
||||
Returns:
|
||||
Validated URL string.
|
||||
|
||||
Raises:
|
||||
ValueError: If URL does not start with supported prefix.
|
||||
"""
|
||||
if v is None:
|
||||
return v
|
||||
if not any(v.startswith(prefix) for prefix in ("sqlite+", "postgresql+")):
|
||||
@@ -62,7 +113,20 @@ class DBConfig(BaseSettings):
|
||||
|
||||
|
||||
class KCConfig(BaseSettings):
|
||||
"""Keycloak configuration."""
|
||||
"""Keycloak configuration.
|
||||
|
||||
Contains Keycloak authentication server settings.
|
||||
|
||||
Attributes:
|
||||
server_url: Keycloak server base URL.
|
||||
realm: Keycloak realm name.
|
||||
client_id: OAuth client identifier.
|
||||
client_secret: OAuth client secret.
|
||||
token_cache_ttl: Token cache time-to-live in seconds.
|
||||
|
||||
Example:
|
||||
>>> kc = KCConfig(server_url="http://localhost:8080", realm="blog")
|
||||
"""
|
||||
|
||||
server_url: str = "http://localhost:8080"
|
||||
realm: str = "blog"
|
||||
@@ -71,7 +135,7 @@ class KCConfig(BaseSettings):
|
||||
default="",
|
||||
description="Keycloak client secret - must be set via env in production",
|
||||
)
|
||||
token_cache_ttl: int = 60 # seconds
|
||||
token_cache_ttl: int = 60
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
env_prefix="KC_",
|
||||
@@ -81,12 +145,26 @@ class KCConfig(BaseSettings):
|
||||
|
||||
@property
|
||||
def is_configured(self) -> bool:
|
||||
"""Check if Keycloak is properly configured."""
|
||||
"""Check if Keycloak is properly configured.
|
||||
|
||||
Returns:
|
||||
True if client_secret is set.
|
||||
"""
|
||||
return bool(self.client_secret)
|
||||
|
||||
|
||||
class SecurityConfig(BaseSettings):
|
||||
"""Security configuration."""
|
||||
"""Security configuration.
|
||||
|
||||
Contains security-related settings for JWT and authentication.
|
||||
|
||||
Attributes:
|
||||
secret_key: Secret key for JWT signing.
|
||||
access_token_expire_minutes: Token expiration time in minutes.
|
||||
|
||||
Example:
|
||||
>>> security = SecurityConfig(secret_key="super-secret-key")
|
||||
"""
|
||||
|
||||
secret_key: str = Field(
|
||||
default="", description="Secret key for JWT - must be set via env in production"
|
||||
@@ -101,17 +179,37 @@ class SecurityConfig(BaseSettings):
|
||||
|
||||
@property
|
||||
def is_configured(self) -> bool:
|
||||
"""Check if security is properly configured."""
|
||||
"""Check if security is properly configured.
|
||||
|
||||
Returns:
|
||||
True if secret_key is set.
|
||||
"""
|
||||
return bool(self.secret_key)
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
"""Application configuration settings with composition."""
|
||||
"""Application configuration settings with composition.
|
||||
|
||||
Main settings class that composes all sub-configurations.
|
||||
Validates production settings and provides computed properties.
|
||||
|
||||
Attributes:
|
||||
environment: Current deployment environment.
|
||||
app: Application configuration.
|
||||
db: Database configuration.
|
||||
kc: Keycloak configuration.
|
||||
security: Security configuration.
|
||||
|
||||
Raises:
|
||||
ValueError: If required production settings are missing.
|
||||
|
||||
Example:
|
||||
>>> settings = Settings()
|
||||
>>> print(settings.database_url)
|
||||
"""
|
||||
|
||||
# Environment mode
|
||||
environment: Environment = Environment.DEV
|
||||
|
||||
# Sub-configurations
|
||||
app: AppConfig = Field(default_factory=AppConfig)
|
||||
db: DBConfig = Field(default_factory=DBConfig)
|
||||
kc: KCConfig = Field(default_factory=KCConfig)
|
||||
@@ -125,7 +223,13 @@ class Settings(BaseSettings):
|
||||
)
|
||||
|
||||
def model_post_init(self, __context: object) -> None:
|
||||
"""Validate settings after initialization."""
|
||||
"""Validate settings after initialization.
|
||||
|
||||
Checks that required settings are configured for production mode.
|
||||
|
||||
Raises:
|
||||
ValueError: If required production settings are missing.
|
||||
"""
|
||||
if self.is_prod:
|
||||
if not self.security.is_configured:
|
||||
raise ValueError("SECURITY_SECRET_KEY must be set in production mode")
|
||||
@@ -136,14 +240,16 @@ class Settings(BaseSettings):
|
||||
def database_url(self) -> str:
|
||||
"""Get database URL based on environment.
|
||||
|
||||
- In dev: uses SQLite if no URL provided
|
||||
- In prod: uses PostgreSQL if no URL provided
|
||||
Returns configured URL or builds one from components.
|
||||
Uses SQLite for development, PostgreSQL for production.
|
||||
|
||||
Returns:
|
||||
Complete database URL string.
|
||||
"""
|
||||
if self.db.url:
|
||||
return self.db.url
|
||||
|
||||
if self.environment == Environment.PROD:
|
||||
# Build PostgreSQL URL from components
|
||||
return str(
|
||||
PostgresDsn.build(
|
||||
scheme="postgresql+asyncpg",
|
||||
@@ -155,19 +261,25 @@ class Settings(BaseSettings):
|
||||
)
|
||||
)
|
||||
|
||||
# Default dev SQLite URL
|
||||
return "sqlite+aiosqlite:///./blog.db"
|
||||
|
||||
@property
|
||||
def is_dev(self) -> bool:
|
||||
"""Check if running in development mode."""
|
||||
"""Check if running in development mode.
|
||||
|
||||
Returns:
|
||||
True if environment is DEV.
|
||||
"""
|
||||
return self.environment == Environment.DEV
|
||||
|
||||
@property
|
||||
def is_prod(self) -> bool:
|
||||
"""Check if running in production mode."""
|
||||
"""Check if running in production mode.
|
||||
|
||||
Returns:
|
||||
True if environment is PROD.
|
||||
"""
|
||||
return self.environment == Environment.PROD
|
||||
|
||||
|
||||
# Global settings instance
|
||||
settings = Settings()
|
||||
|
||||
Reference in New Issue
Block a user