blob: 0900d74aa268abcb31731a745c96e014ab2b66d5 [file] [log] [blame]
import uuid
import importlib.util
import logging
from pathlib import Path
from typing import Callable, Any
class SimulateLoader:
"""Dynamically import simulate() from a file path under a random module name."""
def __init__(self):
self._importlib_util = importlib.util
self.logger = logging.getLogger("SimulateLoader")
self.logger.setLevel(logging.INFO)
def import_simulate(self, script_path: Path, iu=None) -> Callable[..., Any]:
"""
Import the simulate function from a script file.
Args:
script_path: Path to the Python script containing simulate function
iu: importlib.util module (for dependency injection/testing)
Returns:
The simulate function from the module
Raises:
ImportError: If module cannot be loaded
AssertionError: If simulate function is missing
"""
self.logger.info(f"[SIMULATE_LOADER] Starting import of simulate function from {script_path}")
import_util = iu if iu is not None else self._importlib_util
name = f"simulate_{uuid.uuid4().hex}"
self.logger.info(f"[SIMULATE_LOADER] Generated module name: {name}")
self.logger.info(f"[SIMULATE_LOADER] Creating spec from file location")
spec = import_util.spec_from_file_location(name, script_path)
if spec is None or spec.loader is None:
self.logger.error(f"[SIMULATE_LOADER] Cannot load {script_path}")
raise ImportError(f"Cannot load {script_path}")
self.logger.info(f"[SIMULATE_LOADER] Creating module from spec")
mod = import_util.module_from_spec(spec)
self.logger.info(f"[SIMULATE_LOADER] Executing module")
spec.loader.exec_module(mod) # type: ignore[attr-defined]
self.logger.info(f"[SIMULATE_LOADER] Checking for simulate function")
if not hasattr(mod, "simulate"):
self.logger.error(f"[SIMULATE_LOADER] simulate() function missing from module")
raise AssertionError("simulate() missing")
self.logger.info(f"[SIMULATE_LOADER] Successfully imported simulate function")
return mod.simulate