@@ -6278,6 +6278,7 @@ def __init__(self, script_path: str, script_args: Optional[List[str]] = None,
62786278 self .max_output_lines = None
62796279 self .hooks = ExecutionHook ()
62806280 self .monitor_interval = 0.1
6281+ self .config_file = config_file
62816282
62826283 # UPDATED: Phase 2 retry config (replaces old retry_count and retry_delay)
62836284 self .retry_config = RetryConfig () # Default configuration
@@ -6291,8 +6292,10 @@ def __init__(self, script_path: str, script_args: Optional[List[str]] = None,
62916292 # NEW: Phase 2 features
62926293 self .enable_history = enable_history
62936294 self .history_manager = None
6295+ self .history_db_path = None
62946296 if enable_history :
62956297 db_path = history_db or 'script_runner_history.db'
6298+ self .history_db_path = db_path
62966299 self .history_manager = HistoryManager (db_path = db_path )
62976300
62986301 # NEW: Trend Analysis (Phase 2)
@@ -6497,6 +6500,30 @@ def validate_script(self) -> bool:
64976500 self .logger .warning (f"Script does not have .py extension: { self .script_path } " )
64986501 return True
64996502
6503+ def get_execution_plan (self ) -> Dict [str , Any ]:
6504+ """Return a structured view of how the script will be executed.
6505+
6506+ This helper is used by the CLI ``--dry-run`` flag to show what the
6507+ runner would do without actually launching the subprocess. It surfaces
6508+ key configuration such as the script path, arguments, timeouts, logging
6509+ level, configuration file, and history database state.
6510+
6511+ Returns:
6512+ Dict[str, Any]: Execution summary including paths and toggles.
6513+ """
6514+ return {
6515+ 'script_path' : os .path .abspath (self .script_path ),
6516+ 'script_args' : list (self .script_args ),
6517+ 'timeout' : self .timeout ,
6518+ 'log_level' : logging .getLevelName (self .logger .level ),
6519+ 'config_file' : os .path .abspath (self .config_file ) if self .config_file else None ,
6520+ 'history_enabled' : self .enable_history ,
6521+ 'history_db' : os .path .abspath (self .history_db_path ) if self .history_db_path else None ,
6522+ 'monitor_interval' : self .monitor_interval ,
6523+ 'retry_strategy' : self .retry_config .strategy ,
6524+ 'max_attempts' : self .retry_config .max_attempts ,
6525+ }
6526+
65006527 def run_script (self , retry_on_failure : bool = False ) -> Dict :
65016528 """Execute script with advanced retry and monitoring capabilities.
65026529
@@ -7148,8 +7175,10 @@ def main():
71487175 parser .add_argument ('script' , nargs = '?' , help = 'Python script to execute' )
71497176 parser .add_argument ('script_args' , nargs = '*' , help = 'Arguments to pass to the script' )
71507177 parser .add_argument ('--timeout' , type = int , default = None , help = 'Execution timeout in seconds' )
7151- parser .add_argument ('--log-level' , choices = ['DEBUG' , 'INFO' , 'WARNING' , 'ERROR' ],
7178+ parser .add_argument ('--log-level' , choices = ['DEBUG' , 'INFO' , 'WARNING' , 'ERROR' ],
71527179 default = 'INFO' , help = 'Logging level' )
7180+ parser .add_argument ('--dry-run' , action = 'store_true' ,
7181+ help = 'Validate the script and show execution plan without running it' )
71537182 parser .add_argument ('--config' , help = 'Configuration file (YAML)' )
71547183 parser .add_argument ('--monitor-interval' , type = float , default = 0.1 ,
71557184 help = 'Process monitor sampling interval (seconds)' )
@@ -8479,6 +8508,19 @@ def main():
84798508 enable_history = not args .disable_history
84808509 )
84818510
8511+ if args .dry_run :
8512+ try :
8513+ runner .validate_script ()
8514+ except Exception as exc :
8515+ logging .error (f"Dry-run validation failed: { exc } " )
8516+ return 1
8517+
8518+ plan = runner .get_execution_plan ()
8519+ print ("\n DRY-RUN: Execution plan (no script executed)" )
8520+ for key , value in plan .items ():
8521+ print (f" { key } : { value } " )
8522+ return 0
8523+
84828524 runner .monitor_interval = args .monitor_interval
84838525 runner .suppress_warnings = args .suppress_warnings
84848526
0 commit comments