Coverage for src\genesis\parsers\source_aggregator.py: 100%
44 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-26 14:20 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-26 14:20 +0800
1from __future__ import annotations
3from pathlib import Path
5from genesis.data_models import StructuredSource
6from genesis.impact.code_parser import CodeParser
7from genesis.impact.existing_system_explorer import ExistingSystemExplorer
8from genesis.parsers.excel_parser import ExcelParser
9from genesis.parsers.rule_doc_parser import RuleDocParser
10from genesis.parsers.word_template_parser import WordTemplateParser
12XLSX_EXTS = (".xlsx", ".xls")
13DOCX_EXT = ".docx"
16def _validate_path(path: str | Path, allowed_exts: tuple[str, ...]) -> Path:
17 """校验文件扩展名合法且文件存在(T7 DRY:消除三处重复校验)。
19 Raises:
20 ValueError: 扩展名不在 allowed_exts(含无扩展名)
21 FileNotFoundError: 文件不存在
22 """
23 p = Path(path)
24 if p.suffix.lower() not in allowed_exts:
25 raise ValueError(f"不支持的文件类型: {p.suffix or '(无扩展名)'}")
26 if not p.exists():
27 raise FileNotFoundError(str(path))
28 return p
31class SourceParser:
32 """全量输入门面:Excel 要件定义 + Word 模板 + Word 规则 → StructuredSource。
34 角色由调用方按 api-design file_type 语义显式传入(requirements/template/
35 write_instruction/rules),不做基于文件名的隐式猜测(spec §3.4)。
36 """
38 def __init__(self) -> None:
39 self._excel = ExcelParser()
41 def parse(
42 self,
43 requirement_paths: list[str | Path] | None = None,
44 template_path: str | Path | None = None,
45 write_instruction_paths: list[str | Path] | None = None,
46 rule_paths: list[str | Path] | None = None,
47 existing_system_path: str | Path | None = None,
48 existing_system_language: str | None = None,
49 ) -> StructuredSource:
50 """扩展名校验先于存在性校验(不存在的文件若扩展名未知将抛出 ValueError 而非 FileNotFoundError)。
52 existing_system_path:既有系统源码目录(追加/改修场景)。提供时解析为
53 ExistingSystemInfo(门控通过 → 进入影响调查);未提供/解析失败 → 保持 None。
54 existing_system_language:既有系统源码开发语言(如 "java")。默认 None 表示
55 由 CodeParser 按扩展名自动探测;显式指定时按该语言解析(多语言支持扩展点)。
56 """
58 requirement_paths = requirement_paths or []
59 write_instruction_paths = write_instruction_paths or []
60 rule_paths = rule_paths or []
62 tables = []
63 comments = []
64 for p in requirement_paths:
65 path = _validate_path(p, XLSX_EXTS)
66 result = self._excel.parse(path)
67 tables.extend(result.tables)
68 comments.extend(result.comments)
70 template = None
71 if template_path is not None:
72 tpath = _validate_path(template_path, (DOCX_EXT,))
73 template = WordTemplateParser().parse(tpath)
75 rule_docs = []
76 for p in [*write_instruction_paths, *rule_paths]:
77 path = _validate_path(p, (DOCX_EXT,))
78 # 做成说明书与记入规则均为 Type A 写入规则 → write(api-design §2.2)
79 rule_docs.append(RuleDocParser().parse(path, category="write"))
81 existing_system = None
82 if existing_system_path is not None:
83 code = CodeParser().parse(existing_system_path, language=existing_system_language)
84 existing_system = ExistingSystemExplorer().explore(code)
86 return StructuredSource(
87 tables=tables,
88 template=template,
89 rule_docs=rule_docs,
90 image_analyses=[],
91 existing_system=existing_system,
92 comments=comments,
93 )