Coverage for tests/diagram_parts.py: 100%
16 statements
« prev ^ index » next coverage.py v7.15.3, created at 2026-08-03 00:00 +0000
« prev ^ index » next coverage.py v7.15.3, created at 2026-08-03 00:00 +0000
1import re as py_re
2import typing
5EDGE_ARROW: typing.Final = " --> "
6_GROUP_BLOCK_PATTERN: typing.Final = py_re.compile(
7 r'subgraph group_\w+\["(?P<group_title>[^"]+)"\]\n(?P<group_body>.*?)\n\s*end',
8 flags=py_re.DOTALL,
9)
10_DEFINED_NODE_PATTERN: typing.Final = py_re.compile(r'(?m)^\s*(?P<node_id>[A-Za-z0-9_]+)\["')
11_EDGE_ENDS_PATTERN: typing.Final = py_re.compile(r"(?m)^\s*(?P<source>\w+) -->.* (?P<target>\w+)$")
14@typing.final
15class EdgeEnds(typing.NamedTuple):
16 source_id: str
17 target_id: str
20def extract_edge_lines(rendered_diagram: str, /) -> list[str]:
21 return [one_line.strip() for one_line in rendered_diagram.split("\n") if EDGE_ARROW in one_line]
24def collect_group_of_every_node(rendered_diagram: str, /) -> dict[str, str]:
25 return {
26 one_node_match.group("node_id"): one_group_match.group("group_title")
27 for one_group_match in _GROUP_BLOCK_PATTERN.finditer(rendered_diagram)
28 for one_node_match in _DEFINED_NODE_PATTERN.finditer(one_group_match.group("group_body"))
29 }
32def collect_defined_node_ids(rendered_diagram: str, /) -> list[str]:
33 return [one_match.group("node_id") for one_match in _DEFINED_NODE_PATTERN.finditer(rendered_diagram)]
36def collect_edge_ends(rendered_diagram: str, /) -> tuple[EdgeEnds, ...]:
37 return tuple(
38 EdgeEnds(source_id=one_match.group("source"), target_id=one_match.group("target"))
39 for one_match in _EDGE_ENDS_PATTERN.finditer(rendered_diagram)
40 )