(self, ctx: ConditionContext, node: dict[str, Any], trace: List[EvalTraceEntry])
| 32 | return EvalResult(value=value, trace=trace) |
| 33 | |
| 34 | def _eval_node(self, ctx: ConditionContext, node: dict[str, Any], trace: List[EvalTraceEntry]) -> bool: |
| 35 | if "op" in node: |
| 36 | op = str(node["op"]) |
| 37 | if op == "not": |
| 38 | child = node.get("condition") |
| 39 | if not isinstance(child, dict): |
| 40 | raise ValueError("NOT operator requires dict field 'condition'.") |
| 41 | value = not self._eval_node(ctx, child, trace) |
| 42 | trace.append(EvalTraceEntry(kind="logic", expression=node, value=value)) |
| 43 | return value |
| 44 | |
| 45 | if op == "and": |
| 46 | conditions = node.get("conditions") |
| 47 | if conditions is None: |
| 48 | conditions = [] |
| 49 | if not isinstance(conditions, list): |
| 50 | raise ValueError("AND operator requires list field 'conditions'.") |
| 51 | value = self._eval_and(ctx, conditions, trace) |
| 52 | trace.append(EvalTraceEntry(kind="logic", expression=node, value=value)) |
| 53 | return value |
| 54 | |
| 55 | if op == "or": |
| 56 | conditions = node.get("conditions") |
| 57 | if conditions is None: |
| 58 | conditions = [] |
| 59 | if not isinstance(conditions, list): |
| 60 | raise ValueError("OR operator requires list field 'conditions'.") |
| 61 | value = self._eval_or(ctx, conditions, trace) |
| 62 | trace.append(EvalTraceEntry(kind="logic", expression=node, value=value)) |
| 63 | return value |
| 64 | |
| 65 | raise ValueError(f"Unsupported logical operator '{op}'") |
| 66 | |
| 67 | node_type = node.get("type") |
| 68 | if node_type == "node": |
| 69 | value = evaluate_node_condition(ctx, node) |
| 70 | elif node_type == "edge" or "relation" in node: |
| 71 | value = evaluate_edge_condition(ctx, node) |
| 72 | else: |
| 73 | raise ValueError(f"Unsupported condition node type '{node_type}'") |
| 74 | |
| 75 | trace.append(EvalTraceEntry(kind="atomic", expression=node, value=bool(value))) |
| 76 | return bool(value) |
| 77 | |
| 78 | def _eval_and(self, ctx: ConditionContext, nodes: list[dict[str, Any]], trace: List[EvalTraceEntry]) -> bool: |
| 79 | if len(nodes) == 0: |
no test coverage detected