Coverage for graphqler / chains / chain.py: 71%
17 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-20 10:09 -0400
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-20 10:09 -0400
1"""Chain dataclass representing an ordered sequence of nodes to execute."""
3from dataclasses import dataclass, field
4from graphqler.graph.node import Node
7@dataclass
8class Chain:
9 """An ordered list of nodes representing a root-to-leaf path (or a prefix thereof).
11 Example: for a dependency path A -> B -> C, the following chains would be generated:
12 Chain([A]), Chain([A, B]), Chain([A, B, C])
14 Each chain is intended to be executed from start to finish with a fresh ObjectsBucket,
15 ensuring all prerequisite nodes run before dependent ones within the same chain.
16 """
18 nodes: list[Node] = field(default_factory=list)
19 name: str = ""
21 def __len__(self) -> int:
22 return len(self.nodes)
24 def __repr__(self) -> str:
25 path = " -> ".join(n.name for n in self.nodes)
26 return f"Chain([{path}])"
28 def last_node(self) -> Node | None:
29 """Returns the terminal (last) node in the chain, or None if the chain is empty."""
30 if not self.nodes:
31 return None
32 return self.nodes[-1]
34 def has_mutation_type(self, mutation_types: list[str]) -> bool:
35 """Returns True if any node in the chain has a mutation_type in the given list.
37 Args:
38 mutation_types (list[str]): Mutation types to check for (e.g. ["UPDATE", "DELETE"])
40 Returns:
41 bool: True if any node matches
42 """
43 return any(n.mutation_type in mutation_types for n in self.nodes)