krishnadhulipalla commited on
Commit
53b8def
·
verified ·
1 Parent(s): d0a4b52

Update backend/app/config/settings.py

Browse files
Files changed (1) hide show
  1. backend/app/config/settings.py +56 -10
backend/app/config/settings.py CHANGED
@@ -1,12 +1,48 @@
 
 
1
  from pathlib import Path
2
  from pydantic import Field
3
  from pydantic_settings import BaseSettings, SettingsConfigDict
 
4
 
5
  # Resolve repo root no matter where uvicorn is launched from
6
  REPO_ROOT = Path(__file__).resolve().parents[3]
7
 
 
 
 
 
 
 
 
 
 
 
8
  def _default_data_dir() -> Path:
9
- return (REPO_ROOT / "data").resolve()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  def _default_uploads_dir() -> Path:
12
  return (_default_data_dir() / "uploads").resolve()
@@ -27,11 +63,11 @@ class Settings(BaseSettings):
27
  OPENAI_MODEL_AGENT: str = "gpt-4o"
28
  OPENAI_MODEL_CLASSIFIER: str = "gpt-4o-mini"
29
 
30
- # Paths (env may override with absolute or relative; we resolve below)
31
  DATA_DIR: Path = Field(default_factory=_default_data_dir)
32
- REPORTS_DB: Path = Field(default_factory=lambda: _default_data_dir() / "pulsemaps_reports.db")
33
- SESSIONS_DB: Path = Field(default_factory=lambda: _default_data_dir() / "pulsemap_sessions.db")
34
- UPLOADS_DIR: Path = Field(default_factory=_default_uploads_dir)
35
  FRONTEND_DIST: Path = Field(default_factory=_default_frontend_dist)
36
 
37
  # Defaults
@@ -45,12 +81,22 @@ class Settings(BaseSettings):
45
  nvidia_api_key: str | None = None
46
 
47
  def ensure_dirs(self) -> None:
48
- # Resolve in case env provided relative strings
49
- self.DATA_DIR = self.DATA_DIR.resolve()
50
- self.UPLOADS_DIR = self.UPLOADS_DIR.resolve()
51
- # Create everything robustly
 
 
 
 
 
52
  self.DATA_DIR.mkdir(parents=True, exist_ok=True)
53
  self.UPLOADS_DIR.mkdir(parents=True, exist_ok=True)
54
 
 
 
 
 
 
55
  settings = Settings()
56
- settings.ensure_dirs()
 
1
+ # backend/app/config/settings.py
2
+ from __future__ import annotations
3
  from pathlib import Path
4
  from pydantic import Field
5
  from pydantic_settings import BaseSettings, SettingsConfigDict
6
+ import os, tempfile
7
 
8
  # Resolve repo root no matter where uvicorn is launched from
9
  REPO_ROOT = Path(__file__).resolve().parents[3]
10
 
11
+ def _try_writable(p: Path) -> Path | None:
12
+ try:
13
+ p.mkdir(parents=True, exist_ok=True)
14
+ t = p / ".write_test"
15
+ t.write_text("ok", encoding="utf-8")
16
+ t.unlink(missing_ok=True)
17
+ return p.resolve()
18
+ except Exception:
19
+ return None
20
+
21
  def _default_data_dir() -> Path:
22
+ """
23
+ HF Spaces:
24
+ - /data is writable & persisted across restarts
25
+ - /app is read-only (repo checkout)
26
+ Order:
27
+ 1) DATA_DIR env (if set)
28
+ 2) /data
29
+ 3) <repo>/data
30
+ 4) temp dir
31
+ """
32
+ candidates: list[Path] = []
33
+ env = os.getenv("DATA_DIR")
34
+ if env:
35
+ candidates.append(Path(env))
36
+ candidates.append(Path("/data"))
37
+ candidates.append(REPO_ROOT / "data")
38
+ candidates.append(Path(tempfile.gettempdir()) / "pulsemaps" / "data")
39
+
40
+ for p in candidates:
41
+ w = _try_writable(p)
42
+ if w:
43
+ return w
44
+ # As a last resort, raise a clear error
45
+ raise RuntimeError(f"No writable DATA_DIR found. Tried: {candidates!r}")
46
 
47
  def _default_uploads_dir() -> Path:
48
  return (_default_data_dir() / "uploads").resolve()
 
63
  OPENAI_MODEL_AGENT: str = "gpt-4o"
64
  OPENAI_MODEL_CLASSIFIER: str = "gpt-4o-mini"
65
 
66
+ # Paths
67
  DATA_DIR: Path = Field(default_factory=_default_data_dir)
68
+ REPORTS_DB: Path | None = None
69
+ SESSIONS_DB: Path | None = None
70
+ UPLOADS_DIR: Path | None = None
71
  FRONTEND_DIST: Path = Field(default_factory=_default_frontend_dist)
72
 
73
  # Defaults
 
81
  nvidia_api_key: str | None = None
82
 
83
  def ensure_dirs(self) -> None:
84
+ # Fill derived paths if not explicitly provided
85
+ if self.REPORTS_DB is None:
86
+ self.REPORTS_DB = self.DATA_DIR / "pulsemaps_reports.db"
87
+ if self.SESSIONS_DB is None:
88
+ self.SESSIONS_DB = self.DATA_DIR / "pulsemap_sessions.db"
89
+ if self.UPLOADS_DIR is None:
90
+ self.UPLOADS_DIR = self.DATA_DIR / "uploads"
91
+
92
+ # Create & resolve
93
  self.DATA_DIR.mkdir(parents=True, exist_ok=True)
94
  self.UPLOADS_DIR.mkdir(parents=True, exist_ok=True)
95
 
96
+ self.DATA_DIR = self.DATA_DIR.resolve()
97
+ self.REPORTS_DB = self.REPORTS_DB.resolve()
98
+ self.SESSIONS_DB = self.SESSIONS_DB.resolve()
99
+ self.UPLOADS_DIR = self.UPLOADS_DIR.resolve()
100
+
101
  settings = Settings()
102
+ settings.ensure_dirs()