Coverage for backend/django/flowsheetInternals/unitops/config/variant_families.py: 90%
31 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-07-22 05:22 +0000
1from __future__ import annotations
3from dataclasses import dataclass
4from pathlib import Path
6from .json_loader import JsonUnitOpConfig, UnitOpJsonConfigError
9@dataclass(frozen=True, slots=True)
10class UnitOpVariantFamily:
11 """Variant selector data derived from unit-operation JSON configs."""
13 default: str
14 selector_label: str
15 variants: tuple[str, ...]
16 preserve_ports: dict[str, bool]
17 preserve_graphic: dict[str, bool]
20def load_unit_op_variant_families_from_json_dir(
21 path: Path,
22) -> dict[str, UnitOpVariantFamily]:
23 """Build model-type variant families from per-unit JSON config files."""
25 members_by_family: dict[str, list[JsonUnitOpConfig]] = {}
26 for config_path in sorted(path.glob("*.json")):
27 config = JsonUnitOpConfig.model_validate_json(config_path.read_text(encoding="utf-8"))
28 if config.frontend is None or config.frontend.variant is None:
29 continue
30 members_by_family.setdefault(config.frontend.variant.familyKey, []).append(config)
32 families: dict[str, UnitOpVariantFamily] = {}
33 for family_key, members in sorted(members_by_family.items()):
34 selector_labels = {
35 member.frontend.variant.selectorLabel
36 for member in members
37 if member.frontend is not None and member.frontend.variant is not None
38 }
39 if len(selector_labels) != 1: 39 ↛ 40line 39 didn't jump to line 40 because the condition on line 39 was never true
40 raise UnitOpJsonConfigError(
41 f"Variant family {family_key!r} must use exactly one selector label."
42 )
44 defaults = [
45 member
46 for member in members
47 if member.frontend is not None
48 and member.frontend.variant is not None
49 and member.frontend.variant.default
50 ]
51 if len(defaults) != 1: 51 ↛ 52line 51 didn't jump to line 52 because the condition on line 51 was never true
52 raise UnitOpJsonConfigError(
53 f"Variant family {family_key!r} must define exactly one default."
54 )
56 sorted_members = sorted(
57 members,
58 key=lambda member: (
59 member.frontend.variant.order is None,
60 member.frontend.variant.order
61 if member.frontend is not None
62 and member.frontend.variant is not None
63 and member.frontend.variant.order is not None
64 else 0,
65 member.frontend.variant.label
66 if member.frontend is not None and member.frontend.variant is not None
67 else member.displayType,
68 member.objectType,
69 ),
70 )
71 families[family_key] = UnitOpVariantFamily(
72 default=defaults[0].objectType,
73 selector_label=selector_labels.pop(),
74 variants=tuple(member.objectType for member in sorted_members),
75 preserve_ports={
76 member.objectType: member.frontend.variant.preservePorts
77 for member in sorted_members
78 if member.frontend is not None and member.frontend.variant is not None
79 },
80 preserve_graphic={
81 member.objectType: member.frontend.variant.preserveGraphic
82 for member in sorted_members
83 if member.frontend is not None and member.frontend.variant is not None
84 },
85 )
87 return families
90def load_unit_op_variant_families() -> dict[str, UnitOpVariantFamily]:
91 """Load variant families from the conventional unit-operation JSON directory."""
93 return load_unit_op_variant_families_from_json_dir(Path(__file__).parent / "objects")