529 lines
19 KiB
Python
529 lines
19 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
测试带进度条的JSON-RPC Commander
|
||
"""
|
||
|
||
import sys
|
||
import time
|
||
import random
|
||
from pathlib import Path
|
||
|
||
# 添加项目根目录到Python路径
|
||
project_root = Path(__file__).parent.parent
|
||
sys.path.insert(0, str(project_root))
|
||
|
||
def test_progress_commander_import():
|
||
"""测试进度Commander导入"""
|
||
print("🔍 测试进度Commander导入")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
from python_core.utils.progress import (
|
||
ProgressJSONRPCCommander, ProgressiveTask, ProgressInfo,
|
||
TaskResult, with_progress, ProgressGenerator, create_progress_commander
|
||
)
|
||
print("✅ 进度Commander导入成功")
|
||
|
||
# 测试创建简单进度Commander
|
||
commander = create_progress_commander("test_progress_service")
|
||
print("✅ 简单进度Commander创建成功")
|
||
|
||
return True
|
||
|
||
except ImportError as e:
|
||
print(f"❌ 导入失败: {e}")
|
||
return False
|
||
except Exception as e:
|
||
print(f"❌ 测试失败: {e}")
|
||
return False
|
||
|
||
def test_progressive_task():
|
||
"""测试渐进式任务"""
|
||
print("\n⏳ 测试渐进式任务")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
from python_core.utils.progress import ProgressiveTask, ProgressInfo
|
||
|
||
# 收集进度报告
|
||
progress_reports = []
|
||
|
||
def progress_callback(progress: ProgressInfo):
|
||
progress_reports.append(progress)
|
||
print(f"📊 进度: {progress.percentage:.1f}% - {progress.message}")
|
||
|
||
# 创建任务
|
||
task = ProgressiveTask("测试任务", total_steps=10)
|
||
task.set_progress_callback(progress_callback)
|
||
|
||
# 模拟任务执行
|
||
task.start()
|
||
|
||
for i in range(10):
|
||
time.sleep(0.1) # 模拟工作
|
||
task.update(message=f"处理步骤 {i+1}")
|
||
|
||
task.finish("任务完成")
|
||
|
||
# 验证进度报告
|
||
print(f"✅ 收到 {len(progress_reports)} 个进度报告")
|
||
|
||
if len(progress_reports) >= 10:
|
||
first_progress = progress_reports[0]
|
||
last_progress = progress_reports[-1]
|
||
|
||
print(f" 首次进度: {first_progress.percentage:.1f}%")
|
||
print(f" 最终进度: {last_progress.percentage:.1f}%")
|
||
|
||
if last_progress.percentage == 100.0:
|
||
print("✅ 进度计算正确")
|
||
else:
|
||
print("❌ 进度计算错误")
|
||
return False
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ 渐进式任务测试失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def test_progress_commander_basic():
|
||
"""测试基础进度Commander功能"""
|
||
print("\n🎯 测试基础进度Commander功能")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
from python_core.utils.progress import ProgressJSONRPCCommander
|
||
from typing import Dict, Any
|
||
|
||
class TestProgressCommander(ProgressJSONRPCCommander):
|
||
"""测试进度Commander"""
|
||
|
||
def __init__(self):
|
||
super().__init__("test_progress")
|
||
|
||
def _register_commands(self):
|
||
self.register_command(
|
||
name="process_data",
|
||
description="处理数据",
|
||
required_args=["data_size"],
|
||
optional_args={
|
||
"delay": {"type": float, "default": 0.1, "description": "每步延迟"}
|
||
}
|
||
)
|
||
|
||
self.register_command(
|
||
name="quick_task",
|
||
description="快速任务",
|
||
required_args=["message"]
|
||
)
|
||
|
||
def _is_progressive_command(self, command: str) -> bool:
|
||
# 只有process_data需要进度报告
|
||
return command == "process_data"
|
||
|
||
def _execute_with_progress(self, command: str, args: Dict[str, Any]) -> Any:
|
||
if command == "process_data":
|
||
return self._process_data_with_progress(
|
||
int(args["data_size"]),
|
||
args.get("delay", 0.1)
|
||
)
|
||
else:
|
||
raise ValueError(f"Unknown progressive command: {command}")
|
||
|
||
def _execute_simple_command(self, command: str, args: Dict[str, Any]) -> Any:
|
||
if command == "quick_task":
|
||
return {"message": args["message"], "processed": True}
|
||
else:
|
||
raise ValueError(f"Unknown simple command: {command}")
|
||
|
||
def _process_data_with_progress(self, data_size: int, delay: float) -> Dict[str, Any]:
|
||
"""处理数据的示例实现"""
|
||
with self.create_task("处理数据", data_size) as task:
|
||
processed_items = []
|
||
|
||
for i in range(data_size):
|
||
# 模拟处理
|
||
time.sleep(delay)
|
||
|
||
# 模拟一些随机数据
|
||
item = {"id": i, "value": random.randint(1, 100)}
|
||
processed_items.append(item)
|
||
|
||
# 更新进度
|
||
task.update(i + 1, f"已处理 {i + 1}/{data_size} 项")
|
||
|
||
return {
|
||
"processed_count": len(processed_items),
|
||
"items": processed_items[:5], # 只返回前5项作为示例
|
||
"total_items": len(processed_items)
|
||
}
|
||
|
||
# 创建Commander
|
||
commander = TestProgressCommander()
|
||
print("✅ 测试进度Commander创建成功")
|
||
|
||
# 测试进度命令
|
||
print("\n📊 测试进度命令...")
|
||
result = commander.execute_command("process_data", {"data_size": "5", "delay": "0.05"})
|
||
|
||
if isinstance(result, dict) and result.get("processed_count") == 5:
|
||
print(f"✅ 进度命令执行成功: 处理了 {result['processed_count']} 项")
|
||
else:
|
||
print(f"❌ 进度命令执行失败: {result}")
|
||
return False
|
||
|
||
# 测试简单命令
|
||
print("\n⚡ 测试简单命令...")
|
||
result = commander.execute_command("quick_task", {"message": "Hello World"})
|
||
|
||
if isinstance(result, dict) and result.get("processed"):
|
||
print(f"✅ 简单命令执行成功: {result['message']}")
|
||
else:
|
||
print(f"❌ 简单命令执行失败: {result}")
|
||
return False
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ 基础进度Commander测试失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def test_progress_decorator():
|
||
"""测试进度装饰器"""
|
||
print("\n🎨 测试进度装饰器")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
from python_core.utils.progress import (
|
||
ProgressJSONRPCCommander, with_progress, ProgressGenerator
|
||
)
|
||
from typing import Dict, Any
|
||
|
||
class DecoratorTestCommander(ProgressJSONRPCCommander):
|
||
"""装饰器测试Commander"""
|
||
|
||
def __init__(self):
|
||
super().__init__("decorator_test")
|
||
|
||
def _register_commands(self):
|
||
self.register_command(
|
||
name="batch_process",
|
||
description="批量处理",
|
||
required_args=["batch_size"]
|
||
)
|
||
|
||
def _execute_with_progress(self, command: str, args: Dict[str, Any]) -> Any:
|
||
if command == "batch_process":
|
||
return self.batch_process_items(int(args["batch_size"]))
|
||
else:
|
||
raise ValueError(f"Unknown command: {command}")
|
||
|
||
@with_progress(total_steps=100, task_name="批量处理")
|
||
def batch_process_items(self, task, batch_size: int) -> Dict[str, Any]:
|
||
"""使用装饰器的批量处理方法"""
|
||
results = []
|
||
|
||
# 使用进度生成器
|
||
for i in ProgressGenerator.for_range(0, batch_size, task, "处理项目"):
|
||
time.sleep(0.02) # 模拟处理时间
|
||
results.append(f"item_{i}")
|
||
|
||
return {
|
||
"processed_items": len(results),
|
||
"sample_items": results[:3]
|
||
}
|
||
|
||
# 创建Commander
|
||
commander = DecoratorTestCommander()
|
||
print("✅ 装饰器测试Commander创建成功")
|
||
|
||
# 测试装饰器
|
||
print("\n🎯 测试装饰器功能...")
|
||
result = commander.execute_command("batch_process", {"batch_size": "10"})
|
||
|
||
if isinstance(result, dict) and result.get("processed_items") == 10:
|
||
print(f"✅ 装饰器测试成功: 处理了 {result['processed_items']} 项")
|
||
print(f" 示例项目: {result['sample_items']}")
|
||
else:
|
||
print(f"❌ 装饰器测试失败: {result}")
|
||
return False
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ 进度装饰器测试失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def test_simple_progress_commander():
|
||
"""测试简单进度Commander"""
|
||
print("\n🚀 测试简单进度Commander")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
from python_core.utils.progress import create_progress_commander
|
||
import time
|
||
|
||
# 创建简单Commander
|
||
commander = create_progress_commander("simple_test")
|
||
|
||
# 定义带进度的处理函数
|
||
def long_running_task(task_name: str = "默认任务", steps: str = "10"):
|
||
"""长时间运行的任务"""
|
||
steps_count = int(steps)
|
||
|
||
# 这里需要手动获取task对象,在实际使用中会通过上下文传递
|
||
results = []
|
||
for i in range(steps_count):
|
||
time.sleep(0.05) # 模拟工作
|
||
results.append(f"step_{i}")
|
||
|
||
return {
|
||
"task_name": task_name,
|
||
"completed_steps": len(results),
|
||
"results": results[:3] # 只返回前3个结果
|
||
}
|
||
|
||
def quick_task(message: str = "Hello"):
|
||
"""快速任务"""
|
||
return {"message": f"Quick: {message}", "timestamp": time.time()}
|
||
|
||
# 添加命令
|
||
commander.add_command(
|
||
name="long_task",
|
||
handler=long_running_task,
|
||
description="长时间运行的任务",
|
||
optional_args={
|
||
"task_name": {"type": str, "default": "默认任务"},
|
||
"steps": {"type": str, "default": "10"}
|
||
},
|
||
progressive=True
|
||
)
|
||
|
||
commander.add_command(
|
||
name="quick",
|
||
handler=quick_task,
|
||
description="快速任务",
|
||
optional_args={
|
||
"message": {"type": str, "default": "Hello"}
|
||
},
|
||
progressive=False
|
||
)
|
||
|
||
print("✅ 命令注册成功")
|
||
|
||
# 测试快速任务(无进度)
|
||
print("\n⚡ 测试快速任务...")
|
||
result = commander.execute_command("quick", {"message": "World"})
|
||
|
||
if isinstance(result, dict) and "Quick: World" in result.get("message", ""):
|
||
print(f"✅ 快速任务成功: {result['message']}")
|
||
else:
|
||
print(f"❌ 快速任务失败: {result}")
|
||
return False
|
||
|
||
# 测试长时间任务(带进度)
|
||
print("\n📊 测试长时间任务...")
|
||
result = commander.execute_command("long_task", {"task_name": "测试任务", "steps": "5"})
|
||
|
||
if isinstance(result, dict) and result.get("completed_steps") == 5:
|
||
print(f"✅ 长时间任务成功: {result['task_name']} 完成 {result['completed_steps']} 步")
|
||
else:
|
||
print(f"❌ 长时间任务失败: {result}")
|
||
return False
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ 简单进度Commander测试失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def test_video_splitter_with_progress():
|
||
"""测试视频拆分服务的进度集成"""
|
||
print("\n🎬 测试视频拆分服务进度集成")
|
||
print("=" * 50)
|
||
|
||
try:
|
||
# 检查依赖
|
||
try:
|
||
import scenedetect
|
||
print(f"✅ PySceneDetect {scenedetect.__version__} 可用")
|
||
except ImportError:
|
||
print("⚠️ PySceneDetect不可用,跳过视频拆分进度测试")
|
||
return True
|
||
|
||
from python_core.utils.progress import ProgressJSONRPCCommander
|
||
from python_core.services.video_splitter.service import VideoSplitterService
|
||
from python_core.services.video_splitter.types import DetectionConfig, DetectorType
|
||
from typing import Dict, Any
|
||
|
||
class VideoSplitterProgressCommander(ProgressJSONRPCCommander):
|
||
"""带进度的视频拆分Commander"""
|
||
|
||
def __init__(self):
|
||
super().__init__("video_splitter_progress")
|
||
self.service = None
|
||
|
||
def _register_commands(self):
|
||
self.register_command(
|
||
name="analyze_with_progress",
|
||
description="带进度的视频分析",
|
||
required_args=["video_path"],
|
||
optional_args={
|
||
"threshold": {"type": float, "default": 30.0}
|
||
}
|
||
)
|
||
|
||
def _execute_with_progress(self, command: str, args: Dict[str, Any]) -> Any:
|
||
if command == "analyze_with_progress":
|
||
return self._analyze_video_with_progress(
|
||
args["video_path"],
|
||
args.get("threshold", 30.0)
|
||
)
|
||
else:
|
||
raise ValueError(f"Unknown command: {command}")
|
||
|
||
def _analyze_video_with_progress(self, video_path: str, threshold: float) -> Dict[str, Any]:
|
||
"""带进度的视频分析"""
|
||
if self.service is None:
|
||
self.service = VideoSplitterService()
|
||
|
||
config = DetectionConfig(threshold=threshold)
|
||
|
||
with self.create_task("视频分析", 100) as task:
|
||
# 模拟分析步骤
|
||
task.update(10, "初始化视频管理器")
|
||
time.sleep(0.1)
|
||
|
||
task.update(30, "加载视频文件")
|
||
time.sleep(0.1)
|
||
|
||
task.update(50, "检测场景变化")
|
||
# 实际的视频分析
|
||
result = self.service.analyze_video(video_path, config)
|
||
|
||
task.update(80, "处理检测结果")
|
||
time.sleep(0.1)
|
||
|
||
task.update(100, "分析完成")
|
||
|
||
return result.to_dict()
|
||
|
||
# 查找测试视频
|
||
assets_dir = project_root / "assets"
|
||
video_files = list(assets_dir.rglob("*.mp4"))
|
||
|
||
if not video_files:
|
||
print("⚠️ 没有找到测试视频,跳过视频拆分进度测试")
|
||
return True
|
||
|
||
test_video = str(video_files[0])
|
||
print(f"📹 测试视频: {test_video}")
|
||
|
||
# 创建Commander
|
||
commander = VideoSplitterProgressCommander()
|
||
print("✅ 带进度的视频拆分Commander创建成功")
|
||
|
||
# 测试带进度的视频分析
|
||
print("\n📊 测试带进度的视频分析...")
|
||
result = commander.execute_command("analyze_with_progress", {
|
||
"video_path": test_video,
|
||
"threshold": "30.0"
|
||
})
|
||
|
||
if isinstance(result, dict) and result.get("success"):
|
||
print(f"✅ 带进度的视频分析成功:")
|
||
print(f" 总场景数: {result.get('total_scenes', 0)}")
|
||
print(f" 总时长: {result.get('total_duration', 0):.2f}秒")
|
||
else:
|
||
print(f"❌ 带进度的视频分析失败: {result}")
|
||
return False
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"❌ 视频拆分进度集成测试失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("🚀 测试带进度条的JSON-RPC Commander")
|
||
|
||
try:
|
||
# 运行所有测试
|
||
tests = [
|
||
test_progress_commander_import,
|
||
test_progressive_task,
|
||
test_progress_commander_basic,
|
||
test_progress_decorator,
|
||
test_simple_progress_commander,
|
||
test_video_splitter_with_progress
|
||
]
|
||
|
||
results = []
|
||
for test in tests:
|
||
try:
|
||
result = test()
|
||
results.append(result)
|
||
except Exception as e:
|
||
print(f"❌ 测试 {test.__name__} 异常: {e}")
|
||
results.append(False)
|
||
|
||
# 总结
|
||
print("\n" + "=" * 60)
|
||
print("📊 进度Commander测试总结")
|
||
print("=" * 60)
|
||
|
||
passed = sum(results)
|
||
total = len(results)
|
||
|
||
print(f"通过测试: {passed}/{total}")
|
||
|
||
if passed == total:
|
||
print("🎉 所有进度Commander测试通过!")
|
||
print("\n✅ 进度功能验证:")
|
||
print(" 1. 进度任务创建和管理 - ✅")
|
||
print(" 2. 进度回调和报告 - ✅")
|
||
print(" 3. 任务上下文管理 - ✅")
|
||
print(" 4. 装饰器支持 - ✅")
|
||
print(" 5. 简单Commander集成 - ✅")
|
||
print(" 6. 视频拆分服务集成 - ✅")
|
||
|
||
print("\n🔧 进度Commander优势:")
|
||
print(" 1. 实时进度 - 长时间任务的实时进度反馈")
|
||
print(" 2. 时间估算 - 自动计算剩余时间")
|
||
print(" 3. JSON-RPC - 标准化的进度报告协议")
|
||
print(" 4. 易于集成 - 简单的API和装饰器")
|
||
print(" 5. 灵活配置 - 支持不同类型的任务")
|
||
|
||
print("\n📝 使用场景:")
|
||
print(" 1. 视频处理 - 场景检测、格式转换等")
|
||
print(" 2. 数据处理 - 批量导入、ETL等")
|
||
print(" 3. AI任务 - 模型训练、推理等")
|
||
print(" 4. 文件操作 - 大文件上传、下载等")
|
||
|
||
return 0
|
||
else:
|
||
print("⚠️ 部分进度Commander测试失败")
|
||
return 1
|
||
|
||
except Exception as e:
|
||
print(f"❌ 测试过程中出错: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return 1
|
||
|
||
if __name__ == "__main__":
|
||
exit_code = main()
|
||
sys.exit(exit_code)
|