jmri_logixng.logix

LogixNG and ConditionalNG containers.

  • ConditionalNG runs a sequence of actions when invoked.
  • LogixNG is a named collection of conditionals — JMRI's user-facing organizational unit. Triggering one conditional is independent of the others; the LogixNG container is mainly for serialization grouping and enable/disable in bulk.
 1"""``LogixNG`` and ``ConditionalNG`` containers.
 2
 3* :class:`ConditionalNG` runs a sequence of actions when invoked.
 4* :class:`LogixNG` is a named collection of conditionals — JMRI's
 5  user-facing organizational unit. Triggering one conditional is
 6  independent of the others; the LogixNG container is mainly for
 7  serialization grouping and enable/disable in bulk.
 8"""
 9from __future__ import annotations
10
11from typing import Any, ClassVar
12
13from jmri_logixng.context import ExecutionContext
14from jmri_logixng.registry import register
15from jmri_logixng.tree import Action, Node
16
17
18@register
19class ConditionalNG(Action):
20    """A sequence of root actions executed in order."""
21
22    type_tag: ClassVar[str] = "logixng:conditional"
23
24    def __init__(
25        self,
26        actions: list[Action] | None = None,
27        *,
28        user_name: str = "",
29        node_id: str | None = None,
30        enabled: bool = True,
31    ) -> None:
32        super().__init__(user_name=user_name, node_id=node_id)
33        self.actions: list[Action] = list(actions or [])
34        self.enabled = enabled
35
36    async def execute(self, ctx: ExecutionContext) -> None:
37        if not self.enabled:
38            ctx.emit_trace(f"conditional {self.id!r} skipped (disabled)")
39            return
40        ctx.emit_trace(f"conditional {self.id!r} executing {len(self.actions)} actions")
41        for action in self.actions:
42            await action.execute(ctx)
43
44    def extra_fields(self) -> dict[str, Any]:
45        return {
46            "enabled": self.enabled,
47            "actions": [a.to_dict() for a in self.actions],
48        }
49
50
51@register
52class LogixNG(Node):
53    """A named collection of :class:`ConditionalNG` instances."""
54
55    type_tag: ClassVar[str] = "logixng:root"
56
57    def __init__(
58        self,
59        conditionals: list[ConditionalNG] | None = None,
60        *,
61        user_name: str = "",
62        node_id: str | None = None,
63        enabled: bool = True,
64    ) -> None:
65        super().__init__(user_name=user_name, node_id=node_id)
66        self.conditionals: list[ConditionalNG] = list(conditionals or [])
67        self.enabled = enabled
68
69    def add(self, conditional: ConditionalNG) -> None:
70        self.conditionals.append(conditional)
71
72    async def execute_all(self, ctx: ExecutionContext) -> None:
73        """Execute every conditional in order (for fire-and-forget runs)."""
74        if not self.enabled:
75            return
76        for c in self.conditionals:
77            await c.execute(ctx)
78
79    def extra_fields(self) -> dict[str, Any]:
80        return {
81            "enabled": self.enabled,
82            "conditionals": [c.to_dict() for c in self.conditionals],
83        }
@register
class ConditionalNG(jmri_logixng.tree.Action):
19@register
20class ConditionalNG(Action):
21    """A sequence of root actions executed in order."""
22
23    type_tag: ClassVar[str] = "logixng:conditional"
24
25    def __init__(
26        self,
27        actions: list[Action] | None = None,
28        *,
29        user_name: str = "",
30        node_id: str | None = None,
31        enabled: bool = True,
32    ) -> None:
33        super().__init__(user_name=user_name, node_id=node_id)
34        self.actions: list[Action] = list(actions or [])
35        self.enabled = enabled
36
37    async def execute(self, ctx: ExecutionContext) -> None:
38        if not self.enabled:
39            ctx.emit_trace(f"conditional {self.id!r} skipped (disabled)")
40            return
41        ctx.emit_trace(f"conditional {self.id!r} executing {len(self.actions)} actions")
42        for action in self.actions:
43            await action.execute(ctx)
44
45    def extra_fields(self) -> dict[str, Any]:
46        return {
47            "enabled": self.enabled,
48            "actions": [a.to_dict() for a in self.actions],
49        }

A sequence of root actions executed in order.

ConditionalNG( actions: list[jmri_logixng.Action] | None = None, *, user_name: str = '', node_id: str | None = None, enabled: bool = True)
25    def __init__(
26        self,
27        actions: list[Action] | None = None,
28        *,
29        user_name: str = "",
30        node_id: str | None = None,
31        enabled: bool = True,
32    ) -> None:
33        super().__init__(user_name=user_name, node_id=node_id)
34        self.actions: list[Action] = list(actions or [])
35        self.enabled = enabled
type_tag: ClassVar[str] = 'logixng:conditional'
actions: list[jmri_logixng.Action]
enabled
async def execute(self, ctx: jmri_logixng.ExecutionContext) -> None:
37    async def execute(self, ctx: ExecutionContext) -> None:
38        if not self.enabled:
39            ctx.emit_trace(f"conditional {self.id!r} skipped (disabled)")
40            return
41        ctx.emit_trace(f"conditional {self.id!r} executing {len(self.actions)} actions")
42        for action in self.actions:
43            await action.execute(ctx)
def extra_fields(self) -> dict[str, typing.Any]:
45    def extra_fields(self) -> dict[str, Any]:
46        return {
47            "enabled": self.enabled,
48            "actions": [a.to_dict() for a in self.actions],
49        }

Hook for subclasses to add their own fields to to_dict.

@register
class LogixNG(jmri_logixng.tree.Node):
52@register
53class LogixNG(Node):
54    """A named collection of :class:`ConditionalNG` instances."""
55
56    type_tag: ClassVar[str] = "logixng:root"
57
58    def __init__(
59        self,
60        conditionals: list[ConditionalNG] | None = None,
61        *,
62        user_name: str = "",
63        node_id: str | None = None,
64        enabled: bool = True,
65    ) -> None:
66        super().__init__(user_name=user_name, node_id=node_id)
67        self.conditionals: list[ConditionalNG] = list(conditionals or [])
68        self.enabled = enabled
69
70    def add(self, conditional: ConditionalNG) -> None:
71        self.conditionals.append(conditional)
72
73    async def execute_all(self, ctx: ExecutionContext) -> None:
74        """Execute every conditional in order (for fire-and-forget runs)."""
75        if not self.enabled:
76            return
77        for c in self.conditionals:
78            await c.execute(ctx)
79
80    def extra_fields(self) -> dict[str, Any]:
81        return {
82            "enabled": self.enabled,
83            "conditionals": [c.to_dict() for c in self.conditionals],
84        }

A named collection of ConditionalNG instances.

LogixNG( conditionals: list[ConditionalNG] | None = None, *, user_name: str = '', node_id: str | None = None, enabled: bool = True)
58    def __init__(
59        self,
60        conditionals: list[ConditionalNG] | None = None,
61        *,
62        user_name: str = "",
63        node_id: str | None = None,
64        enabled: bool = True,
65    ) -> None:
66        super().__init__(user_name=user_name, node_id=node_id)
67        self.conditionals: list[ConditionalNG] = list(conditionals or [])
68        self.enabled = enabled
type_tag: ClassVar[str] = 'logixng:root'
conditionals: list[ConditionalNG]
enabled
def add(self, conditional: ConditionalNG) -> None:
70    def add(self, conditional: ConditionalNG) -> None:
71        self.conditionals.append(conditional)
async def execute_all(self, ctx: jmri_logixng.ExecutionContext) -> None:
73    async def execute_all(self, ctx: ExecutionContext) -> None:
74        """Execute every conditional in order (for fire-and-forget runs)."""
75        if not self.enabled:
76            return
77        for c in self.conditionals:
78            await c.execute(ctx)

Execute every conditional in order (for fire-and-forget runs).

def extra_fields(self) -> dict[str, typing.Any]:
80    def extra_fields(self) -> dict[str, Any]:
81        return {
82            "enabled": self.enabled,
83            "conditionals": [c.to_dict() for c in self.conditionals],
84        }

Hook for subclasses to add their own fields to to_dict.