flow: structured dtypes, and the widgets that read them
A series, record or list message declares its shape instead of riding DType.JSON, so a widget binds a shape rather than some JSON and a wrong binding is refused before anything runs. A list declares its item type, which is what keeps list[float] expressible for a pipeline. On top of that: an agenda over a list, a notification over a record, and a dashboard alert channel that publishes engine faults as one — so a panel can show what went wrong without a flow wiring it by hand. Also: only None means a node published nothing, a falsy value of the wrong shape is now the named error it always should have been; and the gauge's readout says its size is viewBox geometry rather than type scale. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -197,3 +197,36 @@ def test_alerting_can_be_switched_off():
|
||||
def test_every_alerting_event_reads_as_a_sentence(event, expected):
|
||||
alert = describe(event)
|
||||
assert (alert.title if alert else None) == expected
|
||||
|
||||
|
||||
def test_a_dashboard_channel_publishes_the_alert_as_a_record():
|
||||
published: list[tuple[str, dict]] = []
|
||||
config = AlertsConfig(
|
||||
channels=[
|
||||
Channel(name="panel", kind="dashboard", config={"message": "house.notice"})
|
||||
],
|
||||
rules=[Rule(events=[], channels=["panel"])],
|
||||
)
|
||||
alerts = AlertManager(EventBus(), config=config, now=Clock())
|
||||
alerts.publish = lambda name, value: published.append((name, value))
|
||||
|
||||
asyncio.run(alerts.handle(error_event()))
|
||||
|
||||
assert len(published) == 1
|
||||
name, record = published[0]
|
||||
assert name == "house.notice"
|
||||
# Flat named scalars, which is what a notification widget binds.
|
||||
assert record["title"] == "heating.pump failed"
|
||||
assert record["severity"] == "error"
|
||||
assert all(isinstance(v, str) for v in record.values())
|
||||
|
||||
|
||||
def test_a_dashboard_channel_without_a_message_says_so():
|
||||
alerts = AlertManager(EventBus(), now=Clock())
|
||||
alerts.publish = lambda name, value: None
|
||||
channel = Channel(name="panel", kind="dashboard")
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
asyncio.run(
|
||||
alerts.send(channel, Alert(title="t", body="b"), raise_on_error=True)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user