"""Configuration — paths, constants, settings."""
from __future__ import annotations
import json
import os
from pathlib import Path
# ---------------------------------------------------------------------------
# Base directories
# ---------------------------------------------------------------------------
BASE_DIR = Path(os.environ.get("EXCEL_MCP_HOME", Path.home() / "Documents" / "Excel Analytics"))
DATA_DIR = Path(os.environ.get("DATA_DIR", Path.home() / "Documents"))
DB_PATH = BASE_DIR / "data.db"
TOOLS_DIR = BASE_DIR / "tools"
OUTPUT_DIR = BASE_DIR / "output"
CONFIG_PATH = BASE_DIR / "config.json"
# ---------------------------------------------------------------------------
# Defaults
# ---------------------------------------------------------------------------
DEFAULT_PORT = 8765
MAX_ROWS_PREVIEW = 50
MAX_ROWS_QUERY = 10_000
QUERY_TIMEOUT_SECONDS = 10
EXEC_TIMEOUT_SECONDS = 30
HEADER_THRESHOLD = 0.6 # first row with >60% non-null → headers
# ---------------------------------------------------------------------------
# Allowed / blocked imports for sandboxed Python tools
# ---------------------------------------------------------------------------
ALLOWED_IMPORTS = frozenset({
"pandas", "numpy", "datetime", "json", "math",
"statistics", "re", "collections",
})
BLOCKED_IDENTIFIERS = frozenset({
"os", "subprocess", "shutil", "pathlib", "sys",
"importlib", "eval", "exec", "__import__",
"open", # no raw file I/O
"compile", "globals", "locals", "getattr", "setattr", "delattr",
})
# ---------------------------------------------------------------------------
# Load user config (if exists) and override defaults
# ---------------------------------------------------------------------------
def _load_user_config() -> dict:
if CONFIG_PATH.exists():
try:
return json.loads(CONFIG_PATH.read_text())
except (json.JSONDecodeError, OSError):
pass
return {}
def ensure_dirs() -> None:
"""Create required directories if they don't exist."""
for d in (BASE_DIR, TOOLS_DIR, OUTPUT_DIR):
d.mkdir(parents=True, exist_ok=True)
_user = _load_user_config()
PORT: int = int(_user.get("port", os.environ.get("EXCEL_MCP_PORT", DEFAULT_PORT)))
AUTO_SCAN: bool = _user.get("auto_scan", False)