LocalScriptsWeb/backend/core/script_manager.py

113 lines
4.1 KiB
Python

# backend/core/script_manager.py
from pathlib import Path
import importlib.util
import inspect
from typing import Dict, List, Any, Optional
import json
class ScriptManager:
"""Manages script discovery and execution"""
def __init__(self, script_groups_dir: Path):
self.script_groups_dir = script_groups_dir
def discover_groups(self) -> List[Dict[str, Any]]:
"""Discover all script groups"""
groups = []
for group_dir in self.script_groups_dir.iterdir():
if group_dir.is_dir() and not group_dir.name.startswith('_'):
group_info = self._analyze_group(group_dir)
if group_info:
groups.append(group_info)
return groups
def _analyze_group(self, group_dir: Path) -> Optional[Dict[str, Any]]:
"""Analyze a script group directory"""
scripts = []
for script_file in group_dir.glob('x[0-9].py'):
try:
script_info = self._analyze_script(script_file)
if script_info:
scripts.append(script_info)
except Exception as e:
print(f"Error analyzing script {script_file}: {e}")
if scripts:
return {
"id": group_dir.name,
"name": group_dir.name.replace('_', ' ').title(),
"scripts": sorted(scripts, key=lambda x: x['id'])
}
return None
def _analyze_script(self, script_file: Path) -> Optional[Dict[str, Any]]:
"""Analyze a single script file"""
try:
# Import script module
spec = importlib.util.spec_from_file_location(
script_file.stem,
script_file
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# Find script class
script_class = None
for name, obj in inspect.getmembers(module):
if (inspect.isclass(obj) and
obj.__module__ == module.__name__ and
hasattr(obj, 'run')):
script_class = obj
break
if script_class:
return {
"id": script_file.stem,
"name": script_class.__doc__.split('\n')[0].strip() if script_class.__doc__ else script_file.stem,
"description": inspect.getdoc(script_class),
"file": str(script_file.relative_to(self.script_groups_dir))
}
except Exception as e:
print(f"Error loading script {script_file}: {e}")
return None
def execute_script(self, group_id: str, script_id: str, work_dir: str,
profile: Dict[str, Any]) -> Dict[str, Any]:
"""Execute a specific script"""
script_file = self.script_groups_dir / group_id / f"{script_id}.py"
if not script_file.exists():
raise ValueError(f"Script {script_id} not found in group {group_id}")
try:
# Import script module
spec = importlib.util.spec_from_file_location(script_id, script_file)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# Find and instantiate script class
script_class = None
for name, obj in inspect.getmembers(module):
if (inspect.isclass(obj) and
obj.__module__ == module.__name__ and
hasattr(obj, 'run')):
script_class = obj
break
if not script_class:
raise ValueError(f"No valid script class found in {script_id}")
script = script_class()
return script.run(work_dir, profile)
except Exception as e:
return {
"status": "error",
"error": str(e)
}