Source code for pyiwfm.cli.run

"""
CLI subcommand for generating run scripts and optionally downloading executables.

Usage::

    pyiwfm run --model-dir ./model [--download-executables] [--scripts-only]
               [--format bat] [--format ps1] [--format sh]
"""

from __future__ import annotations

import argparse
import sys
from pathlib import Path


[docs] def add_run_parser(subparsers: argparse._SubParsersAction) -> None: # type: ignore[type-arg] """Register the ``pyiwfm run`` subcommand.""" p = subparsers.add_parser( "run", help="Generate run scripts (and optionally download executables) for an IWFM model", ) p.add_argument( "--model-dir", type=str, required=True, help="Root directory of the IWFM model", ) p.add_argument( "--download-executables", action="store_true", default=False, help="Download IWFM executables from GitHub and place them in the model directory", ) p.add_argument( "--scripts-only", action="store_true", default=False, help="Only generate run scripts without executing the model", ) p.add_argument( "--format", action="append", dest="formats", choices=["bat", "ps1", "sh"], help="Script format(s) to generate (repeatable; default: platform-appropriate)", ) p.set_defaults(func=run_run)
[docs] def run_run(args: argparse.Namespace) -> int: """Execute the run subcommand.""" from pyiwfm.cli._model_finder import find_model_files from pyiwfm.roundtrip.script_generator import generate_run_scripts model_dir = Path(args.model_dir) if not model_dir.is_dir(): print(f"Error: model directory not found: {model_dir}", file=sys.stderr) return 1 # Discover model files found = find_model_files(model_dir) pp_main = found.get("preprocessor_main") sim_main = found.get("simulation_main") if pp_main is None: print("Error: could not find preprocessor main file", file=sys.stderr) return 1 if sim_main is None: print("Error: could not find simulation main file", file=sys.stderr) return 1 pp_main_rel = str(pp_main.relative_to(model_dir)) sim_main_rel = str(sim_main.relative_to(model_dir)) # Default executable names pp_exe = "PreProcessor_x64.exe" sim_exe = "Simulation_x64.exe" budget_exe: str | None = None zbudget_exe: str | None = None # Optionally download and place executables if args.download_executables: from pyiwfm.runner.executables import IWFMExecutableManager mgr = IWFMExecutableManager() exes = mgr.find_or_download() placed = mgr.place_executables(exes, model_dir) if "preprocessor" in placed: pp_exe = placed["preprocessor"].name if "simulation" in placed: sim_exe = placed["simulation"].name if "budget" in placed: budget_exe = placed["budget"].name if "zbudget" in placed: zbudget_exe = placed["zbudget"].name print(f"Placed executables: {list(placed.keys())}") else: # Check for existing executables in model_dir for candidate in model_dir.glob("Budget*"): if candidate.is_file() and candidate.suffix.lower() in {".exe", ""}: budget_exe = candidate.name break for candidate in model_dir.glob("ZBudget*"): if candidate.is_file() and candidate.suffix.lower() in {".exe", ""}: zbudget_exe = candidate.name break # Generate scripts scripts = generate_run_scripts( model_dir, preprocessor_main=pp_main_rel, simulation_main=sim_main_rel, preprocessor_exe=pp_exe, simulation_exe=sim_exe, budget_exe=budget_exe, zbudget_exe=zbudget_exe, formats=args.formats, ) for s in scripts: print(f"Generated: {s}") if not args.scripts_only and not args.download_executables: print( "\nHint: use --download-executables to also fetch IWFM binaries, " "or --scripts-only to skip this message." ) return 0