1
0
Files
PPTX/validators/validator.py
lanyuanxiaoyao ef3fa6a06a feat: 添加模板变量验证功能
- 在 ResourceValidator 中添加 validate_template_vars 方法
- 在验证阶段检查用户是否提供了模板所需的必需变量
- 缺少必需变量时返回 ERROR 级别错误
- 添加 9 个单元测试用例验证功能
- 同步更新 OpenSpec 规格文档
2026-03-03 01:00:21 +08:00

166 lines
5.7 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.
"""
主验证器
协调各子验证器,执行完整的 YAML 文件验证。
"""
from pathlib import Path
from loaders.yaml_loader import load_yaml_file, validate_presentation_yaml, YAMLError
from validators.result import ValidationResult, ValidationIssue
from validators.geometry import GeometryValidator
from validators.resource import ResourceValidator
from core.elements import create_element
class Validator:
"""主验证器"""
# 幻灯片尺寸映射(英寸)
SLIDE_SIZES = {
"16:9": (10, 5.625),
"4:3": (10, 7.5),
}
def __init__(self):
"""初始化验证器"""
pass
def validate(self, yaml_path: Path, template_dir: Path = None) -> ValidationResult:
"""
验证 YAML 文件
Args:
yaml_path: YAML 文件路径
template_dir: 模板文件目录(可选)
Returns:
验证结果
"""
errors = []
warnings = []
infos = []
# 1. 加载 YAML
try:
data = load_yaml_file(yaml_path)
validate_presentation_yaml(data, str(yaml_path))
except YAMLError as e:
errors.append(
ValidationIssue(
level="ERROR", message=str(e), location="", code="YAML_ERROR"
)
)
return ValidationResult(
valid=False, errors=errors, warnings=warnings, infos=infos
)
except Exception as e:
errors.append(
ValidationIssue(
level="ERROR",
message=f"加载 YAML 文件失败: {str(e)}",
location="",
code="YAML_LOAD_ERROR",
)
)
return ValidationResult(
valid=False, errors=errors, warnings=warnings, infos=infos
)
# 获取幻灯片尺寸
size_str = data.get("metadata", {}).get("size", "16:9")
slide_width, slide_height = self.SLIDE_SIZES.get(size_str, (10, 5.625))
# 初始化子验证器
geometry_validator = GeometryValidator(slide_width, slide_height)
resource_validator = ResourceValidator(
yaml_dir=yaml_path.parent, template_dir=template_dir
)
# 2. 验证每个幻灯片
slides = data.get("slides", [])
for slide_index, slide_data in enumerate(slides, start=1):
# 验证模板
template_issues = resource_validator.validate_template(
slide_data, slide_index
)
self._categorize_issues(template_issues, errors, warnings, infos)
# 验证模板变量
template_var_issues = resource_validator.validate_template_vars(
slide_data, slide_index
)
self._categorize_issues(template_var_issues, errors, warnings, infos)
# 验证元素
elements = slide_data.get("elements", [])
for elem_index, elem_dict in enumerate(elements, start=1):
# 3. 元素级验证
try:
element = create_element(elem_dict)
# 调用元素的 validate() 方法
if hasattr(element, "validate"):
elem_issues = element.validate()
# 填充位置信息
for issue in elem_issues:
issue.location = f"幻灯片 {slide_index}, 元素 {elem_index}"
self._categorize_issues(elem_issues, errors, warnings, infos)
# 4. 几何验证
geom_issues = geometry_validator.validate_element(
element, slide_index, elem_index
)
self._categorize_issues(geom_issues, errors, warnings, infos)
# 5. 资源验证(图片)
if elem_dict.get("type") == "image":
img_issues = resource_validator.validate_image(
element, slide_index, elem_index
)
self._categorize_issues(img_issues, errors, warnings, infos)
except ValueError as e:
# 元素创建失败__post_init__ 中的验证)
errors.append(
ValidationIssue(
level="ERROR",
message=str(e),
location=f"幻灯片 {slide_index}, 元素 {elem_index}",
code="ELEMENT_VALIDATION_ERROR",
)
)
except Exception as e:
errors.append(
ValidationIssue(
level="ERROR",
message=f"验证元素时出错: {str(e)}",
location=f"幻灯片 {slide_index}, 元素 {elem_index}",
code="ELEMENT_VALIDATION_ERROR",
)
)
# 返回验证结果
return ValidationResult(
valid=len(errors) == 0, errors=errors, warnings=warnings, infos=infos
)
def _categorize_issues(
self, issues: list, errors: list, warnings: list, infos: list
):
"""
将问题按级别分类
Args:
issues: 问题列表
errors: 错误列表
warnings: 警告列表
infos: 提示列表
"""
for issue in issues:
if issue.level == "ERROR":
errors.append(issue)
elif issue.level == "WARNING":
warnings.append(issue)
elif issue.level == "INFO":
infos.append(issue)