feat: add unique IDs to our nodes for easier debugging

This commit is contained in:
Juro Oravec 2024-04-16 14:26:53 +02:00
parent f3a2bcbc4f
commit f86eeb25a9
2 changed files with 29 additions and 7 deletions

View file

@ -87,18 +87,20 @@ class ComponentIdMixin:
self._component_id = value self._component_id = value
class SlotNode(Node, ComponentIdMixin): class SlotNode(Node):
def __init__( def __init__(
self, self,
name: str, name: str,
nodelist: NodeList, nodelist: NodeList,
is_required: bool = False, is_required: bool = False,
is_default: bool = False, is_default: bool = False,
node_id: Optional[str] = None,
): ):
self.name = name self.name = name
self.nodelist = nodelist self.nodelist = nodelist
self.is_required = is_required self.is_required = is_required
self.is_default = is_default self.is_default = is_default
self.node_id = node_id or gen_id()
@property @property
def active_flags(self) -> List[str]: def active_flags(self) -> List[str]:
@ -167,7 +169,9 @@ class FillNode(Node, ComponentIdMixin):
name_fexp: FilterExpression, name_fexp: FilterExpression,
alias_fexp: Optional[FilterExpression] = None, alias_fexp: Optional[FilterExpression] = None,
is_implicit: bool = False, is_implicit: bool = False,
node_id: Optional[str] = None,
): ):
self.node_id = node_id or gen_id()
self.nodelist = nodelist self.nodelist = nodelist
self.name_fexp = name_fexp self.name_fexp = name_fexp
self.alias_fexp = alias_fexp self.alias_fexp = alias_fexp
@ -214,9 +218,11 @@ class IfSlotFilledConditionBranchNode(_IfSlotFilledBranchNode, ComponentIdMixin)
slot_name: str, slot_name: str,
nodelist: NodeList, nodelist: NodeList,
is_positive: Union[bool, None] = True, is_positive: Union[bool, None] = True,
node_id: Optional[str] = None,
) -> None: ) -> None:
self.slot_name = slot_name self.slot_name = slot_name
self.is_positive: Optional[bool] = is_positive self.is_positive: Optional[bool] = is_positive
self.node_id = node_id or gen_id()
super().__init__(nodelist) super().__init__(nodelist)
def evaluate(self, context: Context) -> bool: def evaluate(self, context: Context) -> bool:

View file

@ -146,15 +146,22 @@ def do_slot(parser: Parser, token: Token) -> SlotNode:
"Order of options is free." "Order of options is free."
) )
# Use a unique ID to be able to tie the fill nodes with components and slots
# NOTE: MUST be called BEFORE `parser.parse()` to ensure predictable numbering
slot_id = gen_id()
nodelist = parser.parse(parse_until=["endslot"]) nodelist = parser.parse(parse_until=["endslot"])
parser.delete_first_token() parser.delete_first_token()
return SlotNode( slot_node = SlotNode(
slot_name, slot_name,
nodelist, nodelist,
is_required=is_required, is_required=is_required,
is_default=is_default, is_default=is_default,
node_id=slot_id,
) )
return slot_node
@register.tag("fill") @register.tag("fill")
def do_fill(parser: Parser, token: Token) -> FillNode: def do_fill(parser: Parser, token: Token) -> FillNode:
@ -180,15 +187,23 @@ def do_fill(parser: Parser, token: Token) -> FillNode:
alias_fexp = FilterExpression(alias, parser) alias_fexp = FilterExpression(alias, parser)
else: else:
raise TemplateSyntaxError(f"'{tag}' tag takes either 1 or 3 arguments: Received {len(args)}.") raise TemplateSyntaxError(f"'{tag}' tag takes either 1 or 3 arguments: Received {len(args)}.")
# Use a unique ID to be able to tie the fill nodes with components and slots
# NOTE: MUST be called BEFORE `parser.parse()` to ensure predictable numbering
fill_id = gen_id()
nodelist = parser.parse(parse_until=["endfill"]) nodelist = parser.parse(parse_until=["endfill"])
parser.delete_first_token() parser.delete_first_token()
return FillNode( fill_node = FillNode(
nodelist, nodelist,
name_fexp=FilterExpression(tgt_slot_name, tag), name_fexp=FilterExpression(tgt_slot_name, tag),
alias_fexp=alias_fexp, alias_fexp=alias_fexp,
node_id=fill_id,
) )
return fill_node
@register.tag(name="component") @register.tag(name="component")
def do_component(parser: Parser, token: Token) -> ComponentNode: def do_component(parser: Parser, token: Token) -> ComponentNode:
@ -208,14 +223,15 @@ def do_component(parser: Parser, token: Token) -> ComponentNode:
bits = token.split_contents() bits = token.split_contents()
bits, isolated_context = check_for_isolated_context_keyword(bits) bits, isolated_context = check_for_isolated_context_keyword(bits)
component_name, context_args, context_kwargs = parse_component_with_args(parser, bits, "component") component_name, context_args, context_kwargs = parse_component_with_args(parser, bits, "component")
# Use a unique ID to be able to tie the fill nodes with components and slots
# NOTE: MUST be called BEFORE `parser.parse()` to ensure predictable numbering
component_id = gen_id()
body: NodeList = parser.parse(parse_until=["endcomponent"]) body: NodeList = parser.parse(parse_until=["endcomponent"])
parser.delete_first_token() parser.delete_first_token()
fill_nodes = parse_slot_fill_nodes_from_component_nodelist(body, ComponentNode) fill_nodes = parse_slot_fill_nodes_from_component_nodelist(body, ComponentNode)
# Use a unique ID to be able to tie the fill nodes with this specific component
# and its slots
component_id = gen_id()
# Tag all fill nodes as children of this particular component instance # Tag all fill nodes as children of this particular component instance
for node in fill_nodes: for node in fill_nodes:
node.component_id = component_id node.component_id = component_id