feat(config): add Pydantic config models, tests, docs and infra notes
This commit is contained in:
66
src/server/models/config.py
Normal file
66
src/server/models/config.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from typing import List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class SchedulerConfig(BaseModel):
|
||||
enabled: bool = Field(
|
||||
default=True, description="Whether the scheduler is enabled"
|
||||
)
|
||||
interval_minutes: int = Field(
|
||||
default=60, ge=1, description="Scheduler interval in minutes"
|
||||
)
|
||||
|
||||
# ge=1 on the Field enforces a positive interval; no custom validator
|
||||
# is required.
|
||||
|
||||
|
||||
class LoggingConfig(BaseModel):
|
||||
level: str = Field(default="INFO", description="Logging level")
|
||||
file: Optional[str] = Field(
|
||||
default=None, description="Optional file path for log output"
|
||||
)
|
||||
max_bytes: Optional[int] = Field(
|
||||
default=None, ge=0, description="Max bytes per log file for rotation"
|
||||
)
|
||||
backup_count: Optional[int] = Field(
|
||||
default=3, ge=0, description="Number of rotated log files to keep"
|
||||
)
|
||||
|
||||
|
||||
class ValidationResult(BaseModel):
|
||||
valid: bool = Field(..., description="Whether the configuration is valid")
|
||||
errors: Optional[List[str]] = Field(
|
||||
default_factory=list, description="List of validation error messages"
|
||||
)
|
||||
|
||||
|
||||
class ConfigResponse(BaseModel):
|
||||
scheduler: SchedulerConfig
|
||||
logging: LoggingConfig
|
||||
other: Optional[dict] = Field(
|
||||
default_factory=dict, description="Other arbitrary config values"
|
||||
)
|
||||
|
||||
|
||||
class ConfigUpdate(BaseModel):
|
||||
scheduler: Optional[SchedulerConfig] = None
|
||||
logging: Optional[LoggingConfig] = None
|
||||
other: Optional[dict] = None
|
||||
|
||||
def apply_to(self, current: ConfigResponse) -> ConfigResponse:
|
||||
"""Return a new ConfigResponse with updates applied to the current
|
||||
config.
|
||||
"""
|
||||
# Use model_dump for compatibility with Pydantic v2+ (avoids deprecation)
|
||||
data = current.model_dump()
|
||||
if self.scheduler is not None:
|
||||
data["scheduler"] = self.scheduler.model_dump()
|
||||
if self.logging is not None:
|
||||
data["logging"] = self.logging.model_dump()
|
||||
if self.other is not None:
|
||||
# shallow merge
|
||||
merged = dict(current.other or {})
|
||||
merged.update(self.other)
|
||||
data["other"] = merged
|
||||
return ConfigResponse(**data)
|
||||
Reference in New Issue
Block a user