from __future__ import annotations from datetime import datetime from typing import Any from .exceptions import ProjectNotOpenError from .utils import safe_count, safe_text class ProjectService: def __init__(self, pcpy: Any): self._pcpy = pcpy @property def is_open(self) -> bool: try: _ = self._pcpy.SWMM return True except Exception: return False def require_open(self): if not self.is_open: raise ProjectNotOpenError( "No active PCSWMM/SWMM5 project is open." ) @property def swmm(self): self.require_open() return self._pcpy.SWMM def summary(self) -> dict[str, Any]: self.require_open() swmm = self.swmm collection_names = { "scenario_count": "Scenarios", "node_count": "Nodes", "link_count": "Links", "junction_count": "Junctions", "conduit_count": "Conduits", "subcatchment_count": "Subcatchments", "storage_count": "Storages", "outfall_count": "Outfalls", } result = { "captured_at": datetime.now().isoformat(timespec="seconds"), "project_open": True, "project_name": safe_text(swmm.ProjectName), "project_folder": safe_text(swmm.ProjectFolder), "model_file": safe_text(swmm.FilePath), "swmm_version": safe_text(swmm.Version), "run_status": safe_text(swmm.RunStatus), } for output_name, attribute_name in collection_names.items(): try: result[output_name] = safe_count(getattr(swmm, attribute_name)) except Exception: result[output_name] = None try: result["graph_file_count"] = safe_count(self._pcpy.Graph.Files) except Exception: result["graph_file_count"] = 0 return result def open_project(self, path: str): self._pcpy.open_project(path) return self.summary()