"""Internal OpenFOAM environment resolution for Python scripts. This keeps user-facing commands rooted in the project .venv while still giving OpenFOAM subprocesses the environment normally produced by etc/bashrc. """ from __future__ import annotations import os import shlex import subprocess from functools import lru_cache from pathlib import Path ROOT = Path(__file__).resolve().parents[1] @lru_cache(maxsize=1) def openfoam_env() -> dict[str, str]: """Return a sanitized environment with OpenFOAM v14 sourced. The returned environment intentionally removes ambient PYTHONPATH. The project package is installed into .venv by `uv sync --dev`, so PYTHONPATH is unnecessary and can accidentally shadow the venv's binary wheels. """ bashrc = ROOT / "OpenFOAM-14/etc/bashrc" if not bashrc.exists(): raise RuntimeError(f"OpenFOAM bashrc not found: {bashrc}") command = " ".join( [ "set +u;", "source", shlex.quote(str(bashrc)), "WM_MPLIB=Dummy", "ParaView_TYPE=none", "SCOTCH_TYPE=none", "ZOLTAN_TYPE=none", ">/dev/null;", "set -u;", "unset FOAM_SIGFPE;", "unset PYTHONPATH;", "env -0", ] ) completed = subprocess.run( ["bash", "-lc", command], cwd=ROOT, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env={key: value for key, value in os.environ.items() if key not in {"PYTHONPATH", "FOAM_SIGFPE"}}, ) env: dict[str, str] = {} for item in completed.stdout.decode().split("\0"): if not item: continue key, _, value = item.partition("=") env[key] = value env.pop("PYTHONPATH", None) env.pop("FOAM_SIGFPE", None) return env def apply_openfoam_env() -> dict[str, str]: """Apply and return the sanitized OpenFOAM environment to this process.""" env = openfoam_env() os.environ.update(env) os.environ.pop("PYTHONPATH", None) os.environ.pop("FOAM_SIGFPE", None) return env