CityTrack / Backend /core /config.py
0xarchit's picture
refactor backend for minor improvements
0888cf8
from functools import lru_cache
from pathlib import Path
from typing import Optional
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import field_validator
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
extra="ignore"
)
database_url: str
supabase_url: str
supabase_key: str
supabase_jwt_secret: str
supabase_bucket: str = "city-issues"
supabase_s3_endpoint: Optional[str] = None
supabase_s3_region: str = "ap-southeast-1"
supabase_s3_access_key: Optional[str] = None
supabase_s3_secret_key: Optional[str] = None
model_path: Path = Path("Backend/agents/vision/model.pt")
model_confidence_threshold: float = 0.25
model_input_size: int = 512
local_temp_dir: Path = Path("static/temp")
sla_critical_hours: int = 4
sla_high_hours: int = 12
sla_medium_hours: int = 48
sla_low_hours: int = 168
api_host: str = "0.0.0.0"
api_port: int = 8000
api_workers: int = 4
db_pool_size: int = 5
db_max_overflow: int = 5
db_pool_timeout: int = 30
db_pool_recycle: int = 1800
db_statement_cache_size: int = 0
db_prepared_statement_cache_size: int = 0
max_upload_size_mb: int = 10
allowed_extensions: set[str] = {"jpg", "jpeg", "png", "webp"}
duplicate_radius_meters: float = 50.0
debug: bool = False
resend_api_key: Optional[str] = None
google_client_id: Optional[str] = None
gemini_api_key: Optional[str] = None
google_client_secret: Optional[str] = None
project_id: Optional[str] = None
sender_email: str = "noreply@CityTrack.city"
admin_email: str = "admin@CityTrack.city"
frontend_url: Optional[str] = None
cors_origins: list[str] = []
jwt_algorithm: str = "HS256"
jwt_expire_hours: int = 24
@field_validator("database_url")
@classmethod
def validate_database_url(cls, v: str) -> str:
if not v.startswith("postgresql"):
raise ValueError("DATABASE_URL must be a PostgreSQL connection string")
return v
@field_validator("supabase_jwt_secret")
@classmethod
def validate_jwt_secret(cls, v: str) -> str:
if len(v) < 32:
raise ValueError("SUPABASE_JWT_SECRET must be at least 32 characters")
return v
@lru_cache
def get_settings() -> Settings:
return Settings()
settings = get_settings()