93 lines
2.5 KiB
Python
93 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ConnectionSettings:
|
|
host: str
|
|
port: int
|
|
user: str
|
|
password: str
|
|
login_prompt: str
|
|
exit_command: str
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ToolSettings:
|
|
tool_mode: bool
|
|
tool_spec: str
|
|
sideload_specs: list[str]
|
|
autoplay: bool
|
|
|
|
|
|
def load_env_file(path: str = ".env") -> None:
|
|
"""Populate ``os.environ`` with key/value pairs from a dotenv file."""
|
|
env_path = Path(path)
|
|
if not env_path.exists():
|
|
return
|
|
for line in env_path.read_text().splitlines():
|
|
stripped = line.strip()
|
|
if not stripped or stripped.startswith("#"):
|
|
continue
|
|
if "=" not in stripped:
|
|
continue
|
|
key, value = stripped.split("=", 1)
|
|
key = key.strip()
|
|
value = value.strip().strip('"').strip("'")
|
|
if key and key not in os.environ:
|
|
os.environ[key] = value
|
|
|
|
|
|
def require_env(key: str) -> str:
|
|
value = os.environ.get(key)
|
|
if value is None:
|
|
raise RuntimeError(f"Missing required environment variable: {key}")
|
|
return value
|
|
|
|
|
|
def parse_bool(raw: str) -> bool:
|
|
return raw.strip().lower() in {"1", "true", "yes", "on"}
|
|
|
|
|
|
def parse_port(raw: str) -> int:
|
|
try:
|
|
return int(raw)
|
|
except ValueError as exc:
|
|
raise RuntimeError("MISTLE_PORT must be an integer") from exc
|
|
|
|
|
|
def parse_csv(raw: str) -> list[str]:
|
|
return [value.strip() for value in raw.split(",") if value.strip()]
|
|
|
|
|
|
def read_connection_settings() -> ConnectionSettings:
|
|
host = require_env("MISTLE_HOST")
|
|
port = parse_port(require_env("MISTLE_PORT"))
|
|
user = os.environ.get("MISTLE_USER", "")
|
|
password = os.environ.get("MISTLE_PASSWORD", "")
|
|
login_prompt = os.environ.get("MISTLE_LOGIN_PROMPT", "")
|
|
exit_command = os.environ.get("MISTLE_EXIT_COMMAND", "")
|
|
return ConnectionSettings(
|
|
host=host,
|
|
port=port,
|
|
user=user,
|
|
password=password,
|
|
login_prompt=login_prompt,
|
|
exit_command=exit_command,
|
|
)
|
|
|
|
|
|
def read_tool_settings() -> ToolSettings:
|
|
tool_mode = parse_bool(os.environ.get("MISTLE_TOOL_MODE", ""))
|
|
tool_spec = os.environ.get("MISTLE_TOOL", "")
|
|
sideload_specs = parse_csv(os.environ.get("MISTLE_SIDELOAD_TOOL", ""))
|
|
autoplay = parse_bool(os.environ.get("MISTLE_AUTOPLAY", ""))
|
|
return ToolSettings(
|
|
tool_mode=tool_mode,
|
|
tool_spec=tool_spec,
|
|
sideload_specs=sideload_specs,
|
|
autoplay=autoplay,
|
|
)
|