refactor(parsers): 提取 _validate_path helper(T7 架构审查整改,I8 DRY)

- source_aggregator.py 三处重复校验(扩展名白名单 + 存在性)提取为
  _validate_path(path, allowed_exts) -> Path,保留 ValueError/FileNotFoundError
  语义与错误信息,parse 三分支改用 helper
- 外部契约不变:未知扩展名→ValueError、不存在→FileNotFoundError
- 新增 3 用例直接测 helper
- TDD: RED(helper 不存在)→ GREEN(聚焦 13 passed)→ 全量 248 passed / 100.00%(1356 stmts/332 br)
This commit is contained in:
lhl
2026-08-12 23:01:58 +08:00
parent e3c714d5d9
commit 3ae1f5f38f
3 changed files with 48 additions and 15 deletions
+18 -15
View File
@@ -11,6 +11,21 @@ XLSX_EXTS = (".xlsx", ".xls")
DOCX_EXT = ".docx"
def _validate_path(path: str | Path, allowed_exts: tuple[str, ...]) -> Path:
"""校验文件扩展名合法且文件存在(T7 DRY:消除三处重复校验)。
Raises:
ValueError: 扩展名不在 allowed_exts(含无扩展名)
FileNotFoundError: 文件不存在
"""
p = Path(path)
if p.suffix.lower() not in allowed_exts:
raise ValueError(f"不支持的文件类型: {p.suffix or '(无扩展名)'}")
if not p.exists():
raise FileNotFoundError(str(path))
return p
class SourceParser:
"""全量输入门面:Excel 要件定义 + Word 模板 + Word 规则 → StructuredSource。
@@ -37,31 +52,19 @@ class SourceParser:
tables = []
comments = []
for p in requirement_paths:
path = Path(p)
if path.suffix.lower() not in XLSX_EXTS:
raise ValueError(f"不支持的文件类型: {path.suffix or '(无扩展名)'}")
if not path.exists():
raise FileNotFoundError(str(p))
path = _validate_path(p, XLSX_EXTS)
result = self._excel.parse(path)
tables.extend(result.tables)
comments.extend(result.comments)
template = None
if template_path is not None:
tpath = Path(template_path)
if tpath.suffix.lower() != DOCX_EXT:
raise ValueError(f"不支持的文件类型: {tpath.suffix or '(无扩展名)'}")
if not tpath.exists():
raise FileNotFoundError(str(template_path))
tpath = _validate_path(template_path, (DOCX_EXT,))
template = WordTemplateParser().parse(tpath)
rule_docs = []
for p in [*write_instruction_paths, *rule_paths]:
path = Path(p)
if path.suffix.lower() != DOCX_EXT:
raise ValueError(f"不支持的文件类型: {path.suffix or '(无扩展名)'}")
if not path.exists():
raise FileNotFoundError(str(p))
path = _validate_path(p, (DOCX_EXT,))
# 做成说明书与记入规则均为 Type A 写入规则 → writeapi-design §2.2
rule_docs.append(RuleDocParser().parse(path, category="write"))