jmri_core.beans.memory

Memory — generic named-value holder.

Memory beans are the universal mutable variable in JMRI: panels, Logix, scripts, and operations all write arbitrary values to memories and listen for changes. The value type is intentionally unconstrained.

 1"""``Memory`` — generic named-value holder.
 2
 3Memory beans are the universal mutable variable in JMRI: panels, Logix,
 4scripts, and operations all write arbitrary values to memories and listen
 5for changes. The value type is intentionally unconstrained.
 6"""
 7from __future__ import annotations
 8
 9from dataclasses import dataclass
10from typing import Any
11
12from jmri_core.bean import AbstractNamedBean
13from jmri_core.manager import Manager
14
15
16@dataclass(frozen=True, slots=True)
17class MemoryChange:
18    previous: Any
19    current: Any
20
21
22class Memory(AbstractNamedBean):
23    """A named slot holding any value. ``None`` means unset."""
24
25    __slots__ = ("_value",)
26
27    type_letter = "M"
28
29    def __init__(self, system_name: str, user_name: str | None = None) -> None:
30        super().__init__(system_name, user_name)
31        self._value: Any = None
32
33    @property
34    def value(self) -> Any:
35        return self._value
36
37    async def set_value(self, value: Any) -> None:
38        prev = self._value
39        if prev == value:
40            return
41        self._value = value
42        await self.state_changed.emit(MemoryChange(prev, value))
43
44
45class MemoryManager(Manager[Memory]):
46    type_letter = "M"
47
48    def _create(self, system_name: str) -> Memory:
49        return Memory(system_name)
@dataclass(frozen=True, slots=True)
class MemoryChange:
17@dataclass(frozen=True, slots=True)
18class MemoryChange:
19    previous: Any
20    current: Any
MemoryChange(previous: Any, current: Any)
previous: Any
current: Any
class Memory(jmri_core.bean.AbstractNamedBean):
23class Memory(AbstractNamedBean):
24    """A named slot holding any value. ``None`` means unset."""
25
26    __slots__ = ("_value",)
27
28    type_letter = "M"
29
30    def __init__(self, system_name: str, user_name: str | None = None) -> None:
31        super().__init__(system_name, user_name)
32        self._value: Any = None
33
34    @property
35    def value(self) -> Any:
36        return self._value
37
38    async def set_value(self, value: Any) -> None:
39        prev = self._value
40        if prev == value:
41            return
42        self._value = value
43        await self.state_changed.emit(MemoryChange(prev, value))

A named slot holding any value. None means unset.

Memory(system_name: str, user_name: str | None = None)
30    def __init__(self, system_name: str, user_name: str | None = None) -> None:
31        super().__init__(system_name, user_name)
32        self._value: Any = None
type_letter = 'M'
value: Any
34    @property
35    def value(self) -> Any:
36        return self._value
async def set_value(self, value: Any) -> None:
38    async def set_value(self, value: Any) -> None:
39        prev = self._value
40        if prev == value:
41            return
42        self._value = value
43        await self.state_changed.emit(MemoryChange(prev, value))
46class MemoryManager(Manager[Memory]):
47    type_letter = "M"
48
49    def _create(self, system_name: str) -> Memory:
50        return Memory(system_name)

Per-type bean registry. Subclass and override _create().

Attributes set on the class describe the bean type:

  • type_letter — single uppercase letter the bean class owns (e.g. "T" for Turnout). Must be set by subclass.
  • system_prefix — connection prefix (e.g. "L"). Set per-instance because one bean class can have many connection-specific managers.
type_letter = 'M'