Source code for pySimBlocks.project.generate_run_script

# ******************************************************************************
#                                  pySimBlocks
#                     Copyright (c) 2026 Université de Lille & INRIA
# ******************************************************************************
#  This program is free software: you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or (at your
#  option) any later version.
#
#  This program is distributed in the hope that it will be useful, but WITHOUT
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
#  for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
# ******************************************************************************
#  Authors: see Authors.txt
# ******************************************************************************

from __future__ import annotations

from pathlib import Path


RUN_TEMPLATE = """\
from pathlib import Path
from pySimBlocks.project import load_simulator_from_project
from pySimBlocks.project.plot_from_config import plot_from_config

try:
    BASE_DIR = Path(__file__).parent.resolve()
except Exception:
    BASE_DIR = Path("")

sim, plot_cfg = load_simulator_from_project(BASE_DIR / {project_path!r})

logs = sim.run()
if {enable_plots} and plot_cfg is not None:
    plot_from_config(logs, plot_cfg)
"""


[docs] def generate_python_content( project_yaml_path: str, enable_plots: bool = True, ) -> str: """Render the run script template for a given project YAML path. Args: project_yaml_path: Path string to the project YAML file, embedded verbatim into the generated script. enable_plots: Whether to include the plotting call in the script. Returns: The rendered run script as a string. """ return RUN_TEMPLATE.format( project_path=project_yaml_path, enable_plots=enable_plots, )
[docs] def generate_run_script( *, project_dir: Path | None = None, project_yaml: Path | None = None, output: Path | None = None, ) -> None: """Generate a canonical ``run.py`` script for a pySimBlocks project. Exactly one of ``project_dir`` or ``project_yaml`` must be provided. Args: project_dir: Path to a project folder containing ``project.yaml``. The output script defaults to ``<project_dir>/run.py``. project_yaml: Explicit path to a ``project.yaml`` file. output: Output path for the generated script. Defaults to ``<project_dir>/run.py`` in ``project_dir`` mode or ``run.py`` in the current directory in ``project_yaml`` mode. Raises: ValueError: If both ``project_dir`` and ``project_yaml`` are given, or if neither is given. FileNotFoundError: If the resolved project YAML file does not exist. """ has_project_yaml_mode = project_yaml is not None if project_dir and has_project_yaml_mode: raise ValueError( "Cannot use project_dir with project_yaml." ) if not project_dir and not has_project_yaml_mode: raise ValueError( "You must specify one mode: project_dir or project_yaml." ) if project_dir: project_dir = Path(project_dir) project_yaml = project_dir / "project.yaml" output = output or (project_dir / "run.py") if not project_yaml.exists(): raise FileNotFoundError(f"project.yaml not found: {project_yaml}") content = generate_python_content(project_yaml_path=project_yaml.name) elif has_project_yaml_mode: project_yaml = Path(project_yaml) output = Path(output or "run.py") if not project_yaml.exists(): raise FileNotFoundError(f"project.yaml not found: {project_yaml}") content = generate_python_content(project_yaml_path=str(project_yaml)) output.write_text(content) print(f"[pySimBlocks] run script generated: {output}")