Spaces:
Paused
Paused
Mirrowel
commited on
Commit
Β·
682bbea
1
Parent(s):
f925da4
fix(env): π use explicit .env path for PyInstaller compatibility
Browse filesReplaced hardcoded `Path.cwd() / ".env"` references with centralized `_get_env_file()` helper function across launcher_tui.py, main.py, and settings_tool.py.
- Adds `_get_env_file()` helper that detects PyInstaller frozen state
- When running as EXE, resolves .env relative to executable directory
- When running as script, resolves .env relative to current working directory
- Updates all `load_dotenv()` calls to use explicit path instead of relying on implicit cwd resolution
- Ensures consistent .env file location regardless of execution context
This fixes issues where the application couldn't locate the .env file when running as a PyInstaller bundle and the working directory differed from the executable location.
- src/proxy_app/launcher_tui.py +22 -8
- src/proxy_app/main.py +4 -4
- src/proxy_app/settings_tool.py +1 -1
src/proxy_app/launcher_tui.py
CHANGED
|
@@ -16,6 +16,20 @@ from dotenv import load_dotenv, set_key
|
|
| 16 |
console = Console()
|
| 17 |
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
def clear_screen():
|
| 20 |
"""
|
| 21 |
Cross-platform terminal clear that works robustly on both
|
|
@@ -74,7 +88,7 @@ class LauncherConfig:
|
|
| 74 |
@staticmethod
|
| 75 |
def update_proxy_api_key(new_key: str):
|
| 76 |
"""Update PROXY_API_KEY in .env only"""
|
| 77 |
-
env_file =
|
| 78 |
set_key(str(env_file), "PROXY_API_KEY", new_key)
|
| 79 |
load_dotenv(dotenv_path=env_file, override=True)
|
| 80 |
|
|
@@ -85,7 +99,7 @@ class SettingsDetector:
|
|
| 85 |
@staticmethod
|
| 86 |
def _load_local_env() -> dict:
|
| 87 |
"""Load environment variables from local .env file only"""
|
| 88 |
-
env_file =
|
| 89 |
env_dict = {}
|
| 90 |
if not env_file.exists():
|
| 91 |
return env_dict
|
|
@@ -271,7 +285,7 @@ class LauncherTUI:
|
|
| 271 |
self.console = Console()
|
| 272 |
self.config = LauncherConfig()
|
| 273 |
self.running = True
|
| 274 |
-
self.env_file =
|
| 275 |
# Load .env file to ensure environment variables are available
|
| 276 |
load_dotenv(dotenv_path=self.env_file, override=True)
|
| 277 |
|
|
@@ -428,7 +442,7 @@ class LauncherTUI:
|
|
| 428 |
elif choice == "4":
|
| 429 |
self.show_provider_settings_menu()
|
| 430 |
elif choice == "5":
|
| 431 |
-
load_dotenv(dotenv_path=
|
| 432 |
self.config = LauncherConfig() # Reload config
|
| 433 |
self.console.print("\n[green]β
Configuration reloaded![/green]")
|
| 434 |
elif choice == "6":
|
|
@@ -824,7 +838,7 @@ class LauncherTUI:
|
|
| 824 |
# Run the tool with from_launcher=True to skip duplicate loading screen
|
| 825 |
run_credential_tool(from_launcher=True)
|
| 826 |
# Reload environment after credential tool
|
| 827 |
-
load_dotenv(dotenv_path=
|
| 828 |
|
| 829 |
def launch_settings_tool(self):
|
| 830 |
"""Launch settings configuration tool"""
|
|
@@ -848,7 +862,7 @@ class LauncherTUI:
|
|
| 848 |
|
| 849 |
run_settings_tool()
|
| 850 |
# Reload environment after settings tool
|
| 851 |
-
load_dotenv(dotenv_path=
|
| 852 |
|
| 853 |
def show_about(self):
|
| 854 |
"""Display About page with project information"""
|
|
@@ -936,9 +950,9 @@ class LauncherTUI:
|
|
| 936 |
)
|
| 937 |
|
| 938 |
ensure_env_defaults()
|
| 939 |
-
load_dotenv(dotenv_path=
|
| 940 |
run_credential_tool()
|
| 941 |
-
load_dotenv(dotenv_path=
|
| 942 |
|
| 943 |
# Check again after credential tool
|
| 944 |
if not os.getenv("PROXY_API_KEY"):
|
|
|
|
| 16 |
console = Console()
|
| 17 |
|
| 18 |
|
| 19 |
+
def _get_env_file() -> Path:
|
| 20 |
+
"""
|
| 21 |
+
Get .env file path (lightweight - no heavy imports).
|
| 22 |
+
|
| 23 |
+
Returns:
|
| 24 |
+
Path to .env file - EXE directory if frozen, else current working directory
|
| 25 |
+
"""
|
| 26 |
+
if getattr(sys, "frozen", False):
|
| 27 |
+
# Running as PyInstaller EXE - use EXE's directory
|
| 28 |
+
return Path(sys.executable).parent / ".env"
|
| 29 |
+
# Running as script - use current working directory
|
| 30 |
+
return Path.cwd() / ".env"
|
| 31 |
+
|
| 32 |
+
|
| 33 |
def clear_screen():
|
| 34 |
"""
|
| 35 |
Cross-platform terminal clear that works robustly on both
|
|
|
|
| 88 |
@staticmethod
|
| 89 |
def update_proxy_api_key(new_key: str):
|
| 90 |
"""Update PROXY_API_KEY in .env only"""
|
| 91 |
+
env_file = _get_env_file()
|
| 92 |
set_key(str(env_file), "PROXY_API_KEY", new_key)
|
| 93 |
load_dotenv(dotenv_path=env_file, override=True)
|
| 94 |
|
|
|
|
| 99 |
@staticmethod
|
| 100 |
def _load_local_env() -> dict:
|
| 101 |
"""Load environment variables from local .env file only"""
|
| 102 |
+
env_file = _get_env_file()
|
| 103 |
env_dict = {}
|
| 104 |
if not env_file.exists():
|
| 105 |
return env_dict
|
|
|
|
| 285 |
self.console = Console()
|
| 286 |
self.config = LauncherConfig()
|
| 287 |
self.running = True
|
| 288 |
+
self.env_file = _get_env_file()
|
| 289 |
# Load .env file to ensure environment variables are available
|
| 290 |
load_dotenv(dotenv_path=self.env_file, override=True)
|
| 291 |
|
|
|
|
| 442 |
elif choice == "4":
|
| 443 |
self.show_provider_settings_menu()
|
| 444 |
elif choice == "5":
|
| 445 |
+
load_dotenv(dotenv_path=_get_env_file(), override=True)
|
| 446 |
self.config = LauncherConfig() # Reload config
|
| 447 |
self.console.print("\n[green]β
Configuration reloaded![/green]")
|
| 448 |
elif choice == "6":
|
|
|
|
| 838 |
# Run the tool with from_launcher=True to skip duplicate loading screen
|
| 839 |
run_credential_tool(from_launcher=True)
|
| 840 |
# Reload environment after credential tool
|
| 841 |
+
load_dotenv(dotenv_path=_get_env_file(), override=True)
|
| 842 |
|
| 843 |
def launch_settings_tool(self):
|
| 844 |
"""Launch settings configuration tool"""
|
|
|
|
| 862 |
|
| 863 |
run_settings_tool()
|
| 864 |
# Reload environment after settings tool
|
| 865 |
+
load_dotenv(dotenv_path=_get_env_file(), override=True)
|
| 866 |
|
| 867 |
def show_about(self):
|
| 868 |
"""Display About page with project information"""
|
|
|
|
| 950 |
)
|
| 951 |
|
| 952 |
ensure_env_defaults()
|
| 953 |
+
load_dotenv(dotenv_path=_get_env_file(), override=True)
|
| 954 |
run_credential_tool()
|
| 955 |
+
load_dotenv(dotenv_path=_get_env_file(), override=True)
|
| 956 |
|
| 957 |
# Check again after credential tool
|
| 958 |
if not os.getenv("PROXY_API_KEY"):
|
src/proxy_app/main.py
CHANGED
|
@@ -326,7 +326,7 @@ litellm_logger.propagate = False
|
|
| 326 |
logging.debug(f"Modules loaded in {_elapsed:.2f}s")
|
| 327 |
|
| 328 |
# Load environment variables from .env file
|
| 329 |
-
load_dotenv()
|
| 330 |
|
| 331 |
# --- Configuration ---
|
| 332 |
USE_EMBEDDING_BATCHER = False
|
|
@@ -1333,7 +1333,7 @@ if __name__ == "__main__":
|
|
| 1333 |
|
| 1334 |
ensure_env_defaults()
|
| 1335 |
# Reload environment variables after ensure_env_defaults creates/updates .env
|
| 1336 |
-
load_dotenv(override=True)
|
| 1337 |
run_credential_tool()
|
| 1338 |
else:
|
| 1339 |
# Check if onboarding is needed
|
|
@@ -1351,11 +1351,11 @@ if __name__ == "__main__":
|
|
| 1351 |
from rotator_library.credential_tool import ensure_env_defaults
|
| 1352 |
|
| 1353 |
ensure_env_defaults()
|
| 1354 |
-
load_dotenv(override=True)
|
| 1355 |
run_credential_tool()
|
| 1356 |
|
| 1357 |
# After credential tool exits, reload and re-check
|
| 1358 |
-
load_dotenv(override=True)
|
| 1359 |
# Re-read PROXY_API_KEY from environment
|
| 1360 |
PROXY_API_KEY = os.getenv("PROXY_API_KEY")
|
| 1361 |
|
|
|
|
| 326 |
logging.debug(f"Modules loaded in {_elapsed:.2f}s")
|
| 327 |
|
| 328 |
# Load environment variables from .env file
|
| 329 |
+
load_dotenv(_root_dir / ".env")
|
| 330 |
|
| 331 |
# --- Configuration ---
|
| 332 |
USE_EMBEDDING_BATCHER = False
|
|
|
|
| 1333 |
|
| 1334 |
ensure_env_defaults()
|
| 1335 |
# Reload environment variables after ensure_env_defaults creates/updates .env
|
| 1336 |
+
load_dotenv(ENV_FILE, override=True)
|
| 1337 |
run_credential_tool()
|
| 1338 |
else:
|
| 1339 |
# Check if onboarding is needed
|
|
|
|
| 1351 |
from rotator_library.credential_tool import ensure_env_defaults
|
| 1352 |
|
| 1353 |
ensure_env_defaults()
|
| 1354 |
+
load_dotenv(ENV_FILE, override=True)
|
| 1355 |
run_credential_tool()
|
| 1356 |
|
| 1357 |
# After credential tool exits, reload and re-check
|
| 1358 |
+
load_dotenv(ENV_FILE, override=True)
|
| 1359 |
# Re-read PROXY_API_KEY from environment
|
| 1360 |
PROXY_API_KEY = os.getenv("PROXY_API_KEY")
|
| 1361 |
|
src/proxy_app/settings_tool.py
CHANGED
|
@@ -64,7 +64,7 @@ class AdvancedSettings:
|
|
| 64 |
"""Load current .env values into env vars"""
|
| 65 |
from dotenv import load_dotenv
|
| 66 |
|
| 67 |
-
load_dotenv(override=True)
|
| 68 |
|
| 69 |
def set(self, key: str, value: str):
|
| 70 |
"""Stage a change"""
|
|
|
|
| 64 |
"""Load current .env values into env vars"""
|
| 65 |
from dotenv import load_dotenv
|
| 66 |
|
| 67 |
+
load_dotenv(self.env_file, override=True)
|
| 68 |
|
| 69 |
def set(self, key: str, value: str):
|
| 70 |
"""Stage a change"""
|