Skip to content

Commit cafba6e

Browse files
committed
removed _DESC_ATTR_KEYS; the loop now iterates over message.attrs.items() and stamps every entry into the desc XML
1 parent d441a38 commit cafba6e

2 files changed

Lines changed: 12 additions & 31 deletions

File tree

src/ezmsg/lsl/outlet.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,31 +43,17 @@ def generate_source_id(
4343
return hashlib.sha256(combined.encode()).hexdigest()[:16]
4444

4545

46-
# Stream-level attrs we promote to top-level desc XML elements when present
47-
# on the incoming AxisArray. Sources upstream (e.g. ``Digitize``) stamp
48-
# these so consumers — pulling from the stream's desc XML — can recover an
49-
# approximation of the original float values via ``data * conversion +
50-
# offset`` (and label units accordingly). Anything else stays on
51-
# ``message.attrs`` but doesn't ride the LSL XML.
52-
#
53-
# ``min_val`` / ``max_val`` aren't included: a consumer that has the data
54-
# dtype can derive them from ``conversion`` and ``offset``, so emitting
55-
# them would be redundant.
56-
_DESC_ATTR_KEYS = ("conversion", "offset", "unit")
57-
58-
5946
def populate_desc_from_axisarray(info: pylsl.StreamInfo, message: AxisArray, *, out_size: int) -> None:
6047
"""Populate the ``desc`` of *info* from *message*'s metadata.
6148
62-
Stamps two kinds of metadata onto the StreamInfo description:
63-
well-known stream-level attrs (see :data:`_DESC_ATTR_KEYS`) and
49+
Stamps two kinds of metadata onto the StreamInfo description: all
50+
stream-level ``message.attrs`` as top-level desc XML elements, and
6451
per-channel labels / structured-array fields from a ``"ch"``
6552
CoordinateAxis.
6653
"""
6754
desc = info.desc()
68-
for key in _DESC_ATTR_KEYS:
69-
if key in message.attrs:
70-
desc.append_child_value(key, str(message.attrs[key]))
55+
for key, value in message.attrs.items():
56+
desc.append_child_value(str(key), str(value))
7157

7258
# Add channel metadata to the info desc.
7359
if "ch" in message.axes and isinstance(message.axes["ch"], AxisArray.CoordinateAxis):

tests/test_outlet_desc.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
would touch the LSL network. The function takes a fresh ``StreamInfo``
66
and an :class:`AxisArray`, and writes both:
77
8-
* well-known stream-level ``attrs`` (``conversion``, ``offset``,
9-
``unit``) as top-level desc XML elements; and
8+
* every stream-level entry in ``message.attrs`` as a top-level desc XML
9+
element; and
1010
* a per-channel ``<channel>`` block when the message's ``"ch"`` axis is
1111
a :class:`CoordinateAxis`.
1212
"""
@@ -54,7 +54,7 @@ def _make_info(
5454

5555

5656
class TestStreamLevelAttrs:
57-
def test_known_attrs_emitted_as_desc_children(self):
57+
def test_attrs_emitted_as_desc_children(self):
5858
msg = _make_int16_msg(
5959
attrs={
6060
"conversion": 0.000244,
@@ -65,7 +65,7 @@ def test_known_attrs_emitted_as_desc_children(self):
6565
info = _make_info()
6666
populate_desc_from_axisarray(info, msg, out_size=3)
6767
xml = info.as_xml()
68-
# Each promoted attr appears as a top-level <key>value</key> in desc.
68+
# Each attr appears as a top-level <key>value</key> in desc.
6969
assert "<conversion>0.000244</conversion>" in xml
7070
assert "<offset>0.0</offset>" in xml
7171
assert "<unit>a.u.</unit>" in xml
@@ -85,21 +85,16 @@ def test_missing_attrs_do_not_appear(self):
8585
assert "<offset>" not in xml
8686
assert "<unit>" not in xml
8787

88-
def test_non_known_attrs_are_dropped(self):
89-
"""Only the well-known attr keys ride the LSL XML.
90-
91-
Other AxisArray.attrs entries stay on the message but don't
92-
appear in the stream descriptor, so the on-the-wire XML stays
93-
bounded regardless of how the upstream graph populates attrs.
94-
"""
88+
def test_arbitrary_attrs_ride_xml(self):
89+
"""All AxisArray.attrs entries land in the stream descriptor."""
9590
msg = _make_int16_msg(
96-
attrs={"conversion": 0.5, "ignore_me": "private"},
91+
attrs={"conversion": 0.5, "custom_key": "custom_value"},
9792
)
9893
info = _make_info()
9994
populate_desc_from_axisarray(info, msg, out_size=3)
10095
xml = info.as_xml()
10196
assert "<conversion>0.5</conversion>" in xml
102-
assert "ignore_me" not in xml
97+
assert "<custom_key>custom_value</custom_key>" in xml
10398

10499

105100
class TestPerChannelLabels:

0 commit comments

Comments
 (0)