Files
deepdata/runtime/deepdata-python/tests/test_module_cleaning.py
沃巴蒂 ff22ed3a8b feat(deepdata): 引入修改密码、文件预览组件与清洗算子增强,deepflow 改名为 deep-flow
本次同步 09-12 至 09-28 的代码变更,主要内容:

新增功能
- 修改密码:后端新增 ChangePasswordRequest DTO 与UserController/UserService
  对应接口,前端新增 ChangePasswordDialog 并在 Header 接入入口
- 文件预览组件重构:file-preview 目录拆分出 VideoPreview(支持 blobUrl 直传)、
  ImagePreview、AudioPreview,index.tsx 统一调度各类型预览器
- 新增 my_ops 算子模块:markitdown_parser、mineru_pdf_parser、text_quality_evaluator
- 新增 tools/minio-file-server MinIO 文件服务

功能增强
- 数据清洗:cleaning_task_service/scheduler/routes 重构,
  data_juicer_executor 与 wrapper 增强,OperatorTable/LogsTable/TaskDetail 同步调整
- 数据标注:annotation sync.py、project.py 接口与schema 更新
- 数据采集、算子市场、首页与菜单路由相关页面调整
- DataJuicer 算子接入(useOperatorOperations、dj_ops_schema)

结构调整
- deepflow/ 更名为 deep-flow/(419 个文件重命名)
- 新增 helm 部署编排、GitHub Actions 之外的自建镜像构建脚本

未纳入本次提交
- scripts-backup/、runtime/python-executor-backup/、components_backup/(备份目录)
- *.backup*、__pycache__ 产物
- zh_core_web_sm-3.8.0-py3-none-any.whl(46MB 构建产物)
- DataX/(内嵌独立仓库,远程亦未收录其源码)
2026-10-03 22:44:56 +08:00

100 lines
3.2 KiB
Python

import pytest
from app.core.exception import BusinessError
from app.module.cleaning.schema.cleaning import OperatorInstanceDto
from app.module.cleaning.service.cleaning_task_validator import CleaningTaskValidator
from app.module.operator.constants import CATEGORY_DEEPDATA_ID, CATEGORY_DATA_JUICER_ID
def _op(op_id: str, inputs: str | None, outputs: str | None, categories: list[str] | None = None) -> OperatorInstanceDto:
return OperatorInstanceDto(id=op_id, inputs=inputs, outputs=outputs, categories=categories)
def test_check_input_and_output_passes_with_multimodal() -> None:
instances = [
_op("a", "text", "multimodal"),
_op("b", "image", "text"),
]
CleaningTaskValidator.check_input_and_output(instances)
def test_check_input_and_output_raises_on_type_mismatch() -> None:
instances = [
_op("a", "text", "image"),
_op("b", "text", "text"),
]
with pytest.raises(BusinessError):
CleaningTaskValidator.check_input_and_output(instances)
def test_check_and_get_executor_type_raises_when_mixed_categories() -> None:
instances = [
_op("a", None, None, [CATEGORY_DEEPDATA_ID]),
_op("b", None, None, [CATEGORY_DATA_JUICER_ID]),
]
with pytest.raises(BusinessError):
CleaningTaskValidator.check_and_get_executor_type(instances)
def test_check_and_get_executor_type_defaults_to_DeepData() -> None:
instances = [_op("a", None, None, None)]
executor = CleaningTaskValidator.check_and_get_executor_type(instances)
assert executor == "deepdata"
def test_check_task_id_raises_when_empty() -> None:
with pytest.raises(BusinessError):
CleaningTaskValidator.check_task_id("")
def test_check_task_id_accepts_normal_value() -> None:
CleaningTaskValidator.check_task_id("task-1")
def test_check_input_and_output_returns_for_empty_instances() -> None:
CleaningTaskValidator.check_input_and_output([])
def test_check_input_and_output_raises_when_current_has_no_outputs() -> None:
instances = [
_op("a", "text", None),
_op("b", "text", "text"),
]
with pytest.raises(BusinessError):
CleaningTaskValidator.check_input_and_output(instances)
def test_check_input_and_output_raises_when_next_has_no_inputs() -> None:
instances = [
_op("a", "text", "text"),
_op("b", None, "text"),
]
with pytest.raises(BusinessError):
CleaningTaskValidator.check_input_and_output(instances)
@pytest.mark.parametrize(
"out_type,in_type",
[
("text", "text"),
(" image ", "image"),
("AUDIO", "audio"),
],
)
def test_check_input_and_output_allows_exact_match_with_normalization(out_type: str, in_type: str) -> None:
instances = [
_op("a", "x", out_type),
_op("b", in_type, "y"),
]
CleaningTaskValidator.check_input_and_output(instances)
def test_check_and_get_executor_type_prefers_datajuicer_when_only_datajuicer() -> None:
instances = [_op("a", None, None, [CATEGORY_DATA_JUICER_ID])]
assert CleaningTaskValidator.check_and_get_executor_type(instances) == "default"