diff --git a/giant/analysis/condor.py b/giant/analysis/condor.py index 2593165..0312ca4 100644 --- a/giant/analysis/condor.py +++ b/giant/analysis/condor.py @@ -43,6 +43,7 @@ from __future__ import annotations import json import shutil +import sys from dataclasses import dataclass, field from pathlib import Path @@ -356,7 +357,7 @@ class SubmitConfig: _WRAPPER = """#!/bin/bash set -euo pipefail cd {repo_dir} -exec {repo_dir}/.venv/bin/giant analyze compute-one --id "$1" --chunk "$2" --run-dir {run_dir} +exec {giant_exe} analyze compute-one --id "$1" --chunk "$2" --run-dir {run_dir} """ @@ -405,6 +406,29 @@ def _job_walltimes( return jobs +def _resolve_giant_executable(repo_dir: Path) -> Path: + """Path to the ``giant`` entry point to bake into the condor wrapper script. + + Prefers the venv currently running this process (``sys.executable``'s + sibling ``giant``) so a submit from a non-default venv (e.g. ``--extra + cuda`` on a dev box) doesn't silently pick up a different one; falls back + to ``repo_dir/.venv/bin/giant`` for the case this is invoked from outside + any venv (e.g. a system Python). + """ + active = Path(sys.executable).parent / "giant" + if active.exists(): + return active + venv_giant = repo_dir / ".venv" / "bin" / "giant" + if not venv_giant.exists(): + raise FileNotFoundError( + f"no `giant` executable found next to {sys.executable} or at " + f"{venv_giant} — condor jobs run it directly (no `uv` on the " + f"worker image), so run `uv sync --extra cpu` in {repo_dir} " + "before submitting." + ) + return venv_giant + + def write_submit(cfg: SubmitConfig, ids: list[str] | None = None) -> Path: """Write the wrapper script, (plot, chunk) job list, and HTCondor submit description. @@ -422,13 +446,7 @@ def write_submit(cfg: SubmitConfig, ids: list[str] | None = None) -> Path: independent values — checked equal up front so a mismatch is a clear error here rather than an ``IndexError`` out of ``_job_walltimes``. """ - venv_giant = cfg.repo_dir / ".venv" / "bin" / "giant" - if not venv_giant.exists(): - raise FileNotFoundError( - f"{venv_giant} not found — condor jobs run it directly (no `uv` on " - f"the worker image), so run `uv sync --extra cpu` in {cfg.repo_dir} " - "before submitting." - ) + giant_exe = _resolve_giant_executable(cfg.repo_dir) ids = ids or catalog_ids() run_dir = cfg.run_dir @@ -446,7 +464,9 @@ def write_submit(cfg: SubmitConfig, ids: list[str] | None = None) -> Path: (run_dir / "reduced_partial").mkdir(parents=True, exist_ok=True) wrapper = run_dir / "run_compute.sh" - wrapper.write_text(_WRAPPER.format(repo_dir=cfg.repo_dir, run_dir=run_dir)) + wrapper.write_text( + _WRAPPER.format(repo_dir=cfg.repo_dir, giant_exe=giant_exe, run_dir=run_dir) + ) wrapper.chmod(0o755) jobs = _job_walltimes(run_dir, ids, cfg.n_chunks)