From 873c89c7786f4b23c856a2dcb2340828c7b9b056 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Wed, 24 Sep 2025 11:28:42 +0800 Subject: [PATCH] u --- config/settings.py | 18 ++++---- index.py | 2 +- mypy.ini | 38 ++++++++++++++++ template/__init__.py | 2 +- tests/conftest.py | 11 ++--- .../test_ffmpeg_command_builder.py | 10 ++--- tests/utils/test_helpers.py | 44 ++++++++++++++----- util/exceptions.py | 12 ++--- util/json_utils.py | 2 +- 9 files changed, 100 insertions(+), 39 deletions(-) create mode 100644 mypy.ini diff --git a/config/settings.py b/config/settings.py index ab762a0..5f7c797 100644 --- a/config/settings.py +++ b/config/settings.py @@ -21,11 +21,11 @@ class FFmpegConfig: # 新增配置选项,消除硬编码 max_download_workers: int = 8 - progress_args: List[str] = None - loglevel_args: List[str] = None - null_audio_args: List[str] = None + progress_args: Optional[List[str]] = None + loglevel_args: Optional[List[str]] = None + null_audio_args: Optional[List[str]] = None overlay_scale_mode: str = "scale2ref" # 新版本使用scale2ref,旧版本使用scale - amix_args: List[str] = None + amix_args: Optional[List[str]] = None @classmethod def from_env(cls) -> "FFmpegConfig": @@ -35,12 +35,14 @@ class FFmpegConfig: default_args = ["-shortest"] re_encode_video_args = None - if os.getenv("RE_ENCODE_VIDEO_ARGS"): - re_encode_video_args = os.getenv("RE_ENCODE_VIDEO_ARGS").split(" ") + re_encode_video_env = os.getenv("RE_ENCODE_VIDEO_ARGS") + if re_encode_video_env: + re_encode_video_args = re_encode_video_env.split(" ") re_encode_encoder_args = None - if os.getenv("RE_ENCODE_ENCODER_ARGS"): - re_encode_encoder_args = os.getenv("RE_ENCODE_ENCODER_ARGS").split(" ") + re_encode_encoder_env = os.getenv("RE_ENCODE_ENCODER_ARGS") + if re_encode_encoder_env: + re_encode_encoder_args = re_encode_encoder_env.split(" ") # 新增配置项的默认值 progress_args = ["-progress", "-"] diff --git a/index.py b/index.py index 5466f40..e47b460 100644 --- a/index.py +++ b/index.py @@ -21,7 +21,7 @@ template_service = get_template_service() if "redownload" in sys.argv: print("Redownloading all templates...") try: - for template_name in template_service.templates.keys(): + for template_name in template_service.get_all_templates().keys(): print(f"Redownloading template: {template_name}") if not template_service.download_template(template_name): print(f"Failed to download template: {template_name}") diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..316b504 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,38 @@ +[mypy] +python_version = 3.9 +warn_return_any = True +warn_unused_configs = True +disallow_untyped_defs = False +disallow_incomplete_defs = False +check_untyped_defs = False +disallow_untyped_decorators = False +no_implicit_optional = False +warn_redundant_casts = False +warn_unused_ignores = False +warn_no_return = False +warn_unreachable = False +strict_equality = False +namespace_packages = True +explicit_package_bases = True + +# Exclude duplicate modules and legacy code +exclude = biz/ffmpeg\.py + +# Ignore missing type annotations for third-party libraries +[mypy-requests.*] +ignore_missing_imports = True + +[mypy-flask.*] +ignore_missing_imports = True + +[mypy-pytest.*] +ignore_missing_imports = True + +[mypy-PIL.*] +ignore_missing_imports = True + +[mypy-psutil.*] +ignore_missing_imports = True + +[mypy-opentelemetry.*] +ignore_missing_imports = True \ No newline at end of file diff --git a/template/__init__.py b/template/__init__.py index f16905b..6f4e904 100644 --- a/template/__init__.py +++ b/template/__init__.py @@ -19,7 +19,7 @@ def _get_template_service(): return _template_service # 向后兼容的全局变量和函数 -TEMPLATES = {} +TEMPLATES: dict = {} def _update_templates_dict(): """更新全局TEMPLATES字典以保持向后兼容""" diff --git a/tests/conftest.py b/tests/conftest.py index 8353567..d03bdee 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -23,8 +23,10 @@ def temp_dir(): def test_ffmpeg_config(): """测试用FFmpeg配置""" return FFmpegConfig( - encoder_args="-c:v h264", - video_args="", + encoder_args=["-c:v", "h264"], + video_args=["-profile:v", "high"], + audio_args=["-c:a", "aac"], + default_args=["-shortest"], ) @@ -49,9 +51,8 @@ def test_storage_config(): def sample_render_task(): """示例渲染任务""" return RenderTask( - task_id="test_task_001", - template_id="test_template", - output_path="test_output.mp4", + input_files=["test_input.mp4"], + output_file="test_output.mp4", frame_rate=25, effects=["zoom:0,2.0,3.0", "ospeed:1.5"], ext_data={ diff --git a/tests/test_ffmpeg_builder/test_ffmpeg_command_builder.py b/tests/test_ffmpeg_builder/test_ffmpeg_command_builder.py index bf874a1..0f40c87 100644 --- a/tests/test_ffmpeg_builder/test_ffmpeg_command_builder.py +++ b/tests/test_ffmpeg_builder/test_ffmpeg_command_builder.py @@ -96,7 +96,7 @@ class TestFFmpegCommandBuilder: task.ext_data = {"posJson": "{}"} builder = FFmpegCommandBuilder(task) - filter_args = [] + filter_args: list[str] = [] result_input, result_index = builder._add_effects(filter_args, "[0:v]", 1) @@ -112,7 +112,7 @@ class TestFFmpegCommandBuilder: task.ext_data = {"posJson": "{}"} builder = FFmpegCommandBuilder(task) - filter_args = [] + filter_args: list[str] = [] result_input, result_index = builder._add_effects(filter_args, "[0:v]", 1) @@ -127,7 +127,7 @@ class TestFFmpegCommandBuilder: task.effects = ["invalid_effect:params"] builder = FFmpegCommandBuilder(task) - filter_args = [] + filter_args: list[str] = [] result_input, result_index = builder._add_effects(filter_args, "[0:v]", 1) @@ -141,7 +141,7 @@ class TestFFmpegCommandBuilder: task.effects = [] builder = FFmpegCommandBuilder(task) - filter_args = [] + filter_args: list[str] = [] result_input, result_index = builder._add_effects(filter_args, "[0:v]", 1) @@ -210,7 +210,7 @@ class TestFFmpegCommandBuilder: task.frame_rate = 30 builder = FFmpegCommandBuilder(task) - filter_args = [] + filter_args: list[str] = [] builder._add_effects(filter_args, "[0:v]", 1) diff --git a/tests/utils/test_helpers.py b/tests/utils/test_helpers.py index b6d6119..f4476d5 100644 --- a/tests/utils/test_helpers.py +++ b/tests/utils/test_helpers.py @@ -16,21 +16,41 @@ class MockRenderTask: def __init__( self, - task_id: str = "test_task", - template_id: str = "test_template", - effects: List[str] = None, - ext_data: Dict[str, Any] = None, + input_files: Optional[List[str]] = None, + output_file: str = "test_output.mp4", + effects: Optional[List[str]] = None, + ext_data: Optional[Dict[str, Any]] = None, frame_rate: int = 25, - output_path: str = "test_output.mp4", ): - self.task_id = task_id - self.template_id = template_id - self.effects = effects or [] - self.ext_data = ext_data or {} + # RenderTask required fields + self.input_files = input_files or [] + self.output_file = output_file + self.task_type = "copy" # TaskType.COPY equivalent + + # Optional fields that match RenderTask + self.resolution = None self.frame_rate = frame_rate - self.output_path = output_path - self.input_files = [] - self.overlays = [] + self.speed = 1.0 + self.mute = True + self.annexb = False + + # Cut parameters + self.zoom_cut = None + self.center_cut = None + + # Resource lists + self.subtitles: List[str] = [] + self.luts: List[str] = [] + self.audios: List[str] = [] + self.overlays: List[str] = [] + self.effects = effects or [] + + # Extension data + self.ext_data = ext_data or {} + + # Legacy compatibility + self.task_id = "test_task" + self.template_id = "test_template" self.use_center_cut = False self.use_zoom_cut = False self.audio_file = None diff --git a/util/exceptions.py b/util/exceptions.py index 64a9156..8ea677a 100644 --- a/util/exceptions.py +++ b/util/exceptions.py @@ -1,7 +1,7 @@ class RenderWorkerError(Exception): """RenderWorker基础异常类""" - def __init__(self, message: str, error_code: str = None): + def __init__(self, message: str, error_code: Optional[str] = None): super().__init__(message) self.message = message self.error_code = error_code or self.__class__.__name__ @@ -55,9 +55,9 @@ class FFmpegError(RenderError): def __init__( self, message: str, - command: list = None, - return_code: int = None, - stderr: str = None, + command: Optional[list] = None, + return_code: Optional[int] = None, + stderr: Optional[str] = None, ): super().__init__(message) self.command = command @@ -69,7 +69,7 @@ class EffectError(RenderError): """效果处理错误""" def __init__( - self, message: str, effect_name: str = None, effect_params: str = None + self, message: str, effect_name: Optional[str] = None, effect_params: Optional[str] = None ): super().__init__(message) self.effect_name = effect_name @@ -86,7 +86,7 @@ class APIError(RenderWorkerError): """API调用错误""" def __init__( - self, message: str, status_code: int = None, response_body: str = None + self, message: str, status_code: Optional[int] = None, response_body: Optional[str] = None ): super().__init__(message) self.status_code = status_code diff --git a/util/json_utils.py b/util/json_utils.py index 603e531..46c6bda 100644 --- a/util/json_utils.py +++ b/util/json_utils.py @@ -26,7 +26,7 @@ def safe_json_loads(json_str: Union[str, bytes], default: Any = None) -> Any: try: return json.loads(json_str) except (json.JSONDecodeError, TypeError) as e: - logger.warning(f"Failed to parse JSON: {e}, input: {json_str}") + logger.warning(f"Failed to parse JSON: {e}, input: {json_str!r}") return default or {}