Files
webber/src/shared/base.py
T
jpmschweitzerandClaude Opus 4.5 a61fbe5a88 feat: initial FastAPI boilerplate setup
Set up Webber - multi-agent AI development system with:

- Domain-based project structure (src/domains/, src/shared/)
- BaseController pattern with lazy router instantiation
- Pydantic Settings configuration with env file support
- Logger decorator with temporal benchmarking and trace IDs
- UserProvider singleton for request-scoped context
- Custom exception hierarchy
- Health endpoints (/, /health)

Dependencies (CVE checked 2026-01-09):
- FastAPI 0.128.0, Starlette 0.50.0, Uvicorn 0.40.0
- Pydantic 2.12.4, PydanticAI 1.40.0
- All packages at latest safe versions

Placeholder domains for future implementation:
- agents/ (explore, plan, task)
- tools/ (file, shell, search)
- auth/ (tatlock integration)

Port: 8086 (per CONTAINERS.md allocation)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 18:38:08 +01:00

75 lines
1.9 KiB
Python

"""
Base classes for controllers and schemas.
All domain controllers and Pydantic models should inherit from these.
"""
from abc import ABC, abstractmethod
from datetime import datetime
from typing import Any
from fastapi import APIRouter
from pydantic import BaseModel, ConfigDict
class BaseController(ABC):
"""
Base controller with lazy router instantiation.
All domain controllers inherit from this and implement create_router().
Usage:
class UsersController(BaseController):
def __init__(self):
super().__init__(prefix="/users", tags=["Users"])
def create_router(self) -> APIRouter:
router = APIRouter(prefix=self.prefix, tags=self.tags)
@router.get("/")
async def list_users():
return []
return router
users_controller = UsersController()
"""
def __init__(self, prefix: str, tags: list[str]):
self.prefix = prefix
self.tags = tags
self._router = None
@abstractmethod
def create_router(self) -> APIRouter:
"""Create and configure the FastAPI router with all routes."""
pass
@property
def router(self) -> APIRouter:
"""Lazy router instantiation."""
if self._router is None:
self._router = self.create_router()
return self._router
class BaseSchema(BaseModel):
"""
Base Pydantic model with standardized configuration.
All domain schemas should inherit from this.
"""
model_config = ConfigDict(
strict=False,
populate_by_name=True,
use_enum_values=True,
validate_assignment=True,
json_encoders={
datetime: lambda v: v.isoformat() if v else None
}
)
def dict_without_none(self) -> dict[str, Any]:
"""Return model as dict, excluding None values."""
return {k: v for k, v in self.model_dump().items() if v is not None}