| 75 | |
| 76 | |
| 77 | class Node: |
| 78 | def __init__( |
| 79 | self, |
| 80 | node_class: type["RelationMixin"], |
| 81 | relation_name: Optional[str] = None, |
| 82 | parent_node: Optional["Node"] = None, |
| 83 | ) -> None: |
| 84 | self.relation_name = relation_name |
| 85 | self.node_class = node_class |
| 86 | self.parent_node = parent_node |
| 87 | self.visited_children: list["Node"] = [] |
| 88 | if self.parent_node: |
| 89 | self.parent_node.visited_children.append(self) |
| 90 | |
| 91 | def __repr__(self) -> str: # pragma: no cover |
| 92 | return ( |
| 93 | f"{self.node_class.get_name(lower=False)}, " |
| 94 | f"relation:{self.relation_name}, " |
| 95 | f"parent: {self.parent_node}" |
| 96 | ) |
| 97 | |
| 98 | def visited(self, relation_name: str) -> bool: |
| 99 | """ |
| 100 | Checks if given relation was already visited. |
| 101 | |
| 102 | Relation was visited if it's name is in current node children. |
| 103 | |
| 104 | Relation was visited if one of the parent node had the same Model class |
| 105 | |
| 106 | :param relation_name: name of relation |
| 107 | :type relation_name: str |
| 108 | :return: result of the check |
| 109 | :rtype: bool |
| 110 | """ |
| 111 | target_model = self.node_class.ormar_config.model_fields[relation_name].to |
| 112 | if self.parent_node: |
| 113 | node = self |
| 114 | while node.parent_node: |
| 115 | node = node.parent_node |
| 116 | if node.node_class == target_model: |
| 117 | return True |
| 118 | return False |