jmri_logixng.registry

Type registry — maps type_tag strings to concrete node classes.

Used by the serializer: a serialized tree carries type: <tag> fields, and the deserializer looks up the class by tag, then calls cls.from_dict(payload, registry) (or a default reflection-based constructor) to rebuild the node.

The registry is populated at import time by every action/expression module via register(). Tests use snapshot() / restore() to isolate registrations.

 1"""Type registry — maps ``type_tag`` strings to concrete node classes.
 2
 3Used by the serializer: a serialized tree carries ``type: <tag>`` fields,
 4and the deserializer looks up the class by tag, then calls
 5``cls.from_dict(payload, registry)`` (or a default reflection-based
 6constructor) to rebuild the node.
 7
 8The registry is populated at import time by every action/expression
 9module via :func:`register`. Tests use :func:`snapshot` /
10:func:`restore` to isolate registrations.
11"""
12from __future__ import annotations
13
14from typing import TYPE_CHECKING
15
16if TYPE_CHECKING:
17    from jmri_logixng.tree import Node
18
19
20_REGISTRY: dict[str, type[Node]] = {}
21
22
23def register(cls: type[Node]) -> type[Node]:
24    """Register a node class by its ``type_tag``. Usable as a decorator.
25
26    Raises if the tag is already registered to a different class.
27    """
28    tag = cls.type_tag
29    if not tag:
30        raise ValueError(f"{cls.__name__}.type_tag must be set before registration")
31    existing = _REGISTRY.get(tag)
32    if existing is not None and existing is not cls:
33        raise ValueError(
34            f"type_tag {tag!r} already registered to {existing.__name__}, "
35            f"can't re-register to {cls.__name__}"
36        )
37    _REGISTRY[tag] = cls
38    return cls
39
40
41def lookup(tag: str) -> type[Node]:
42    """Find the class for *tag*. Raises ``KeyError`` if unknown."""
43    if tag not in _REGISTRY:
44        raise KeyError(f"unknown LogixNG type tag: {tag!r}")
45    return _REGISTRY[tag]
46
47
48def known_tags() -> list[str]:
49    return sorted(_REGISTRY)
50
51
52def snapshot() -> dict[str, type[Node]]:
53    return dict(_REGISTRY)
54
55
56def restore(snap: dict[str, type[Node]]) -> None:
57    _REGISTRY.clear()
58    _REGISTRY.update(snap)
def register(cls: type[jmri_logixng.Node]) -> type[jmri_logixng.Node]:
24def register(cls: type[Node]) -> type[Node]:
25    """Register a node class by its ``type_tag``. Usable as a decorator.
26
27    Raises if the tag is already registered to a different class.
28    """
29    tag = cls.type_tag
30    if not tag:
31        raise ValueError(f"{cls.__name__}.type_tag must be set before registration")
32    existing = _REGISTRY.get(tag)
33    if existing is not None and existing is not cls:
34        raise ValueError(
35            f"type_tag {tag!r} already registered to {existing.__name__}, "
36            f"can't re-register to {cls.__name__}"
37        )
38    _REGISTRY[tag] = cls
39    return cls

Register a node class by its type_tag. Usable as a decorator.

Raises if the tag is already registered to a different class.

def lookup(tag: str) -> type[jmri_logixng.Node]:
42def lookup(tag: str) -> type[Node]:
43    """Find the class for *tag*. Raises ``KeyError`` if unknown."""
44    if tag not in _REGISTRY:
45        raise KeyError(f"unknown LogixNG type tag: {tag!r}")
46    return _REGISTRY[tag]

Find the class for tag. Raises KeyError if unknown.

def known_tags() -> list[str]:
49def known_tags() -> list[str]:
50    return sorted(_REGISTRY)
def snapshot() -> dict[str, type[jmri_logixng.Node]]:
53def snapshot() -> dict[str, type[Node]]:
54    return dict(_REGISTRY)
def restore(snap: dict[str, type[jmri_logixng.Node]]) -> None:
57def restore(snap: dict[str, type[Node]]) -> None:
58    _REGISTRY.clear()
59    _REGISTRY.update(snap)