217 lines
7.2 KiB
Python
217 lines
7.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
带进度的JSON-RPC Commander
|
|
"""
|
|
|
|
import time
|
|
from abc import abstractmethod
|
|
from typing import Dict, Any, Callable
|
|
from contextlib import contextmanager
|
|
|
|
from .types import ProgressInfo, TaskResult
|
|
from .task import ProgressiveTask
|
|
from .reporter import ProgressReporter
|
|
from ..commander import JSONRPCCommander
|
|
from ..logger import logger
|
|
|
|
class ProgressJSONRPCCommander(JSONRPCCommander):
|
|
"""带进度条的JSON-RPC Commander基类"""
|
|
|
|
def __init__(self, service_name: str):
|
|
super().__init__(service_name)
|
|
self.progress_reporter = ProgressReporter(service_name)
|
|
|
|
@contextmanager
|
|
def create_task(self, task_name: str, total_steps: int = 100):
|
|
"""创建带进度的任务上下文"""
|
|
task = ProgressiveTask(task_name, total_steps)
|
|
task.set_progress_callback(self.progress_reporter.report_progress)
|
|
|
|
try:
|
|
task.start()
|
|
yield task
|
|
task.finish()
|
|
except Exception as e:
|
|
task._report_progress(f"任务失败: {str(e)}")
|
|
raise
|
|
|
|
def execute_progressive_command(self, command: str, args: Dict[str, Any]) -> TaskResult:
|
|
"""
|
|
执行带进度的命令
|
|
|
|
Args:
|
|
command: 命令名称
|
|
args: 命令参数
|
|
|
|
Returns:
|
|
任务结果
|
|
"""
|
|
start_time = time.time()
|
|
|
|
try:
|
|
# 调用子类实现的进度命令执行
|
|
result = self._execute_with_progress(command, args)
|
|
|
|
total_time = time.time() - start_time
|
|
|
|
return TaskResult(
|
|
success=True,
|
|
result=result,
|
|
total_time=total_time
|
|
)
|
|
|
|
except Exception as e:
|
|
total_time = time.time() - start_time
|
|
logger.error(f"Progressive command failed: {e}")
|
|
|
|
return TaskResult(
|
|
success=False,
|
|
error=str(e),
|
|
total_time=total_time
|
|
)
|
|
|
|
@abstractmethod
|
|
def _execute_with_progress(self, command: str, args: Dict[str, Any]) -> Any:
|
|
"""
|
|
执行带进度的命令 - 子类必须实现
|
|
|
|
Args:
|
|
command: 命令名称
|
|
args: 命令参数
|
|
|
|
Returns:
|
|
命令执行结果
|
|
"""
|
|
pass
|
|
|
|
def execute_command(self, command: str, args: Dict[str, Any]) -> Any:
|
|
"""
|
|
执行命令(重写基类方法以支持进度)
|
|
|
|
Args:
|
|
command: 命令名称
|
|
args: 命令参数
|
|
|
|
Returns:
|
|
命令执行结果
|
|
"""
|
|
# 先进行参数类型转换
|
|
converted_args = self._convert_args_types(command, args)
|
|
|
|
# 检查是否是需要进度报告的命令
|
|
if self._is_progressive_command(command):
|
|
task_result = self.execute_progressive_command(command, converted_args)
|
|
|
|
if task_result.success:
|
|
return task_result.result
|
|
else:
|
|
raise Exception(task_result.error)
|
|
else:
|
|
# 普通命令,调用子类实现
|
|
return self._execute_simple_command(command, converted_args)
|
|
|
|
def _convert_args_types(self, command: str, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""
|
|
转换参数类型
|
|
|
|
Args:
|
|
command: 命令名称
|
|
args: 原始参数
|
|
|
|
Returns:
|
|
转换后的参数
|
|
"""
|
|
if command not in self.commands:
|
|
return args
|
|
|
|
command_config = self.commands[command]
|
|
converted_args = args.copy()
|
|
|
|
# 转换可选参数的类型
|
|
for arg_name, arg_config in command_config.optional_args.items():
|
|
if arg_name in converted_args:
|
|
arg_type = arg_config.get('type', str)
|
|
try:
|
|
if arg_type == bool:
|
|
# 布尔类型特殊处理
|
|
value = converted_args[arg_name]
|
|
if isinstance(value, str):
|
|
converted_args[arg_name] = value.lower() in ('true', '1', 'yes', 'on')
|
|
elif arg_type != str and isinstance(converted_args[arg_name], str):
|
|
# 其他类型从字符串转换
|
|
converted_args[arg_name] = arg_type(converted_args[arg_name])
|
|
except (ValueError, TypeError) as e:
|
|
logger.warning(f"Failed to convert argument {arg_name}: {e}")
|
|
|
|
return converted_args
|
|
|
|
def _is_progressive_command(self, command: str) -> bool:
|
|
"""
|
|
判断是否是需要进度报告的命令
|
|
子类可以重写此方法来指定哪些命令需要进度报告
|
|
|
|
Args:
|
|
command: 命令名称
|
|
|
|
Returns:
|
|
是否需要进度报告
|
|
"""
|
|
# 默认所有命令都需要进度报告
|
|
return True
|
|
|
|
def _execute_simple_command(self, command: str, args: Dict[str, Any]) -> Any:
|
|
"""
|
|
执行简单命令(不需要进度报告)
|
|
子类可以重写此方法来处理不需要进度的命令
|
|
|
|
Args:
|
|
command: 命令名称
|
|
args: 命令参数
|
|
|
|
Returns:
|
|
命令执行结果
|
|
"""
|
|
# 默认调用带进度的执行方法
|
|
return self._execute_with_progress(command, args)
|
|
|
|
# 便捷函数
|
|
def create_progress_commander(service_name: str):
|
|
"""创建带进度的JSON-RPC Commander"""
|
|
|
|
class SimpleProgressCommander(ProgressJSONRPCCommander):
|
|
def __init__(self):
|
|
super().__init__(service_name)
|
|
self.command_handlers: Dict[str, Callable] = {}
|
|
self._progressive_commands = set()
|
|
|
|
def _register_commands(self):
|
|
pass
|
|
|
|
def add_command(self, name: str, handler: Callable, description: str,
|
|
required_args: list = None, optional_args: dict = None,
|
|
progressive: bool = True):
|
|
"""添加命令"""
|
|
self.register_command(name, description, required_args, optional_args)
|
|
self.command_handlers[name] = handler
|
|
|
|
# 标记是否需要进度报告
|
|
if progressive:
|
|
self._progressive_commands.add(name)
|
|
|
|
def _is_progressive_command(self, command: str) -> bool:
|
|
return command in self._progressive_commands
|
|
|
|
def _execute_with_progress(self, command: str, args: Dict[str, Any]) -> Any:
|
|
if command in self.command_handlers:
|
|
return self.command_handlers[command](**args)
|
|
else:
|
|
raise ValueError(f"No handler for command: {command}")
|
|
|
|
def _execute_simple_command(self, command: str, args: Dict[str, Any]) -> Any:
|
|
if command in self.command_handlers:
|
|
return self.command_handlers[command](**args)
|
|
else:
|
|
raise ValueError(f"No handler for command: {command}")
|
|
|
|
return SimpleProgressCommander()
|