refactor: extract _assemble_pair to lower build_units complexity to B
将 pair 分组的数量/角色校验与组装下沉到 _assemble_pair 私有 helper, build_units 主体只做分组+派发,radon 复杂度从 C(11) 降到 A(4)。 fail-fast 语义、公共函数签名、稳定顺序均不变。
This commit is contained in:
@@ -9,6 +9,35 @@ from collections import defaultdict
|
|||||||
from core.types import GeneratedQuestion, QuestionUnit
|
from core.types import GeneratedQuestion, QuestionUnit
|
||||||
|
|
||||||
|
|
||||||
|
def _assemble_pair(pair_id: str, group: list[GeneratedQuestion]) -> QuestionUnit:
|
||||||
|
"""校验单个 pair 分组的数量/角色并组装为 pair 单元(fail-fast)。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
pair_id: 该分组共享的孪生对标识。
|
||||||
|
group: 归属同一 pair_id 的题目列表。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
kind="pair" 的 QuestionUnit。
|
||||||
|
|
||||||
|
关键实现:
|
||||||
|
- 分组必须恰好 2 条,否则视为孤儿/超员,raise ValueError。
|
||||||
|
- 显式检查 pair_original / pair_mirror 角色齐备且唯一,缺失或重复
|
||||||
|
直接 raise ValueError(防 next(...) 静默 StopIteration)。
|
||||||
|
- 合法孪生对交由 QuestionUnit.from_pair 做 video_id/task_type/flip_axis
|
||||||
|
一致性断言。
|
||||||
|
"""
|
||||||
|
if len(group) != 2:
|
||||||
|
raise ValueError(f"pair {pair_id} 数量={len(group)}≠2(孤儿或超员)")
|
||||||
|
originals = [q for q in group if q.question_role == "pair_original"]
|
||||||
|
mirrors = [q for q in group if q.question_role == "pair_mirror"]
|
||||||
|
if len(originals) != 1 or len(mirrors) != 1:
|
||||||
|
raise ValueError(
|
||||||
|
f"pair {pair_id} 角色非法:original={len(originals)} mirror={len(mirrors)},"
|
||||||
|
"需各恰好 1 条"
|
||||||
|
)
|
||||||
|
return QuestionUnit.from_pair(originals[0], mirrors[0])
|
||||||
|
|
||||||
|
|
||||||
def build_units(questions: list[GeneratedQuestion]) -> list[QuestionUnit]:
|
def build_units(questions: list[GeneratedQuestion]) -> list[QuestionUnit]:
|
||||||
"""将扁平题目列表聚合为单元列表:single 单封、pair 按 pair_id 成对聚合。
|
"""将扁平题目列表聚合为单元列表:single 单封、pair 按 pair_id 成对聚合。
|
||||||
|
|
||||||
@@ -20,11 +49,9 @@ def build_units(questions: list[GeneratedQuestion]) -> list[QuestionUnit]:
|
|||||||
pair 按首次出现的 pair_id 顺序)。
|
pair 按首次出现的 pair_id 顺序)。
|
||||||
|
|
||||||
关键实现:
|
关键实现:
|
||||||
- pair_id 为空 → single 单元;非空 → 归入对应 pair 桶。
|
pair_id 为空 → single 单元;非空 → 归入对应 pair 桶。各 pair 桶的
|
||||||
- 每个 pair 桶必须恰好 2 条,否则视为孤儿/超员,raise ValueError。
|
数量/角色校验与组装下沉到 _assemble_pair(fail-fast),本体只做分组
|
||||||
- 显式检查 pair_original / pair_mirror 角色齐备且唯一,缺失或重复
|
与派发。
|
||||||
直接 raise ValueError(防 next(...) 静默 StopIteration),保持
|
|
||||||
fail-fast。合法孪生对交由 QuestionUnit.from_pair 做一致性断言。
|
|
||||||
"""
|
"""
|
||||||
by_pair: dict[str, list[GeneratedQuestion]] = defaultdict(list)
|
by_pair: dict[str, list[GeneratedQuestion]] = defaultdict(list)
|
||||||
singles: list[QuestionUnit] = []
|
singles: list[QuestionUnit] = []
|
||||||
@@ -34,18 +61,7 @@ def build_units(questions: list[GeneratedQuestion]) -> list[QuestionUnit]:
|
|||||||
else:
|
else:
|
||||||
singles.append(QuestionUnit.from_single(q))
|
singles.append(QuestionUnit.from_single(q))
|
||||||
|
|
||||||
pairs: list[QuestionUnit] = []
|
pairs = [_assemble_pair(pid, qs) for pid, qs in by_pair.items()]
|
||||||
for pid, qs in by_pair.items():
|
|
||||||
if len(qs) != 2:
|
|
||||||
raise ValueError(f"pair {pid} 数量={len(qs)}≠2(孤儿或超员)")
|
|
||||||
originals = [q for q in qs if q.question_role == "pair_original"]
|
|
||||||
mirrors = [q for q in qs if q.question_role == "pair_mirror"]
|
|
||||||
if len(originals) != 1 or len(mirrors) != 1:
|
|
||||||
raise ValueError(
|
|
||||||
f"pair {pid} 角色非法:original={len(originals)} mirror={len(mirrors)},"
|
|
||||||
"需各恰好 1 条"
|
|
||||||
)
|
|
||||||
pairs.append(QuestionUnit.from_pair(originals[0], mirrors[0]))
|
|
||||||
return singles + pairs
|
return singles + pairs
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user