mxivideo/scripts/test_progress_commander.py

529 lines
19 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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)