Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| from pathlib import Path | |
| from pydantic import BaseModel, Field, model_validator | |
| from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict, YamlConfigSettingsSource | |
| from pydantic_settings.sources import EnvSettingsSource | |
| from tracker.constants import DisplayDistanceUnit, DisplayWeightUnit | |
| _TRACKER_REPO_ROOT = Path(__file__).resolve().parent.parent | |
| _CONFIG_YAML_PATH = _TRACKER_REPO_ROOT / "config.yaml" | |
| class DashboardLogin(BaseModel): | |
| """Small, explicit dashboard account for HF/demo deployments.""" | |
| label: str | |
| email: str = Field(min_length=1) | |
| password: str = Field(min_length=1) | |
| role: str | None = None | |
| notes: list[str] = Field(default_factory=list) | |
| class TrackerConfig(BaseSettings): | |
| """Tracker app configuration: config.yaml first, then TRACKER_* environment overrides (HF Secrets).""" | |
| model_config = SettingsConfigDict(env_prefix="TRACKER_", extra="ignore") | |
| parser_data_dir: str | |
| tracker_db_path: str | |
| google_credentials_path: str | |
| google_token_path: str | |
| default_calendar_id: str | |
| chores_calendar_id: str | None = None | |
| workout_calendar_id: str | None = None | |
| tracker_app_url: str = "http://127.0.0.1:8020" | |
| host: str | |
| port: int | |
| active_program_id: int | None = None | |
| agent_profile_path: str = "agent_profile.yaml" | |
| agent_api_key: str | None = None | |
| dashboard_password: str | None = None | |
| dashboard_logins: list[DashboardLogin] = Field(default_factory=list) | |
| session_secret: str | None = None | |
| display_weight_unit: DisplayWeightUnit = DisplayWeightUnit.KG | |
| display_distance_unit: DisplayDistanceUnit = DisplayDistanceUnit.KM | |
| calibration_dumbbell_bench_lb_per_hand: float | None = None | |
| calibration_dumbbell_squat_lb_per_hand: float | None = None | |
| dumbbell_weight_quantum_lb: float = 5.0 | |
| def validate_dashboard_session(self) -> TrackerConfig: | |
| if self.dashboard_password or self.dashboard_logins: | |
| if not self.session_secret or len(self.session_secret) < 16: | |
| msg = ( | |
| "session_secret must be set to at least 16 characters when " | |
| "dashboard_password or dashboard_logins is set" | |
| ) | |
| raise ValueError(msg) | |
| return self | |
| def user_db_path(self) -> Path: | |
| return Path(self.parser_data_dir) / "user.db" | |
| def query_db_path(self) -> Path: | |
| return Path(self.parser_data_dir) / "web_query.db" | |
| def cache_db_path(self) -> Path: | |
| return Path(self.parser_data_dir) / "web_cache.db" | |
| def tracker_db_full_path(self) -> Path: | |
| path = Path(self.tracker_db_path) | |
| return path if path.is_absolute() else _TRACKER_REPO_ROOT / path | |
| def agent_profile_resolved_path(self) -> Path: | |
| path = Path(self.agent_profile_path) | |
| return path if path.is_absolute() else _TRACKER_REPO_ROOT / path | |
| def settings_customise_sources( | |
| cls, | |
| settings_cls: type[BaseSettings], | |
| init_settings: PydanticBaseSettingsSource, | |
| env_settings: PydanticBaseSettingsSource, | |
| dotenv_settings: PydanticBaseSettingsSource, | |
| file_secret_settings: PydanticBaseSettingsSource, | |
| ) -> tuple[PydanticBaseSettingsSource, ...]: | |
| return ( | |
| init_settings, | |
| EnvSettingsSource(settings_cls), | |
| YamlConfigSettingsSource(settings_cls, yaml_file=str(_CONFIG_YAML_PATH)), | |
| ) | |
| def load_config() -> TrackerConfig: | |
| return TrackerConfig() | |