Skip to content

Widget

Widget is the base class of every card. Subclass it to write your own, see Custom Widgets.

from typing import ClassVar

from dachshund.widgets import Widget


class Gauge(Widget):
    type: ClassVar[str] = "gauge"

    def render(self, events):
        return {"value": self.value(events[-1], "value") if events else None}

dachshund.widgets.base.Widget dataclass

Widget(name, *, source='', title=None, actions=list(), action_args=dict())

A card on the dashboard, built from the events of its source.

Every built-in widget subclasses it. A subclass with a type of its own is registered when the class is defined. See the Custom Widgets guide.

Example

class Gauge(Widget):
    type: ClassVar[str] = "gauge"
    script: ClassVar[Path] = Path(__file__).parent / "gauge.js"

    def render(self, events):
        return {"value": self.value(events[-1], "value") if events else None}

Options

  • name (str) - The widget's unique name. Required.
  • source (str) - The events it's built from. Defaults to name.
  • title (str) - The card's title. Defaults to name, underscores as spaces.
  • actions (list[str]) - The actions shown as buttons on the card, see Actions. Defaults to [].
  • action_args (dict[str, dict]) - The arguments each action is called with, by action name. Defaults to {}.

Class attributes

  • type (str) - The renderer drawing the card in the browser.
  • op (str) - How the browser applies an update(): "replace" redraws the card, "append" adds a point. Defaults to "replace".
  • script (Path) - The renderer's JavaScript file, served and loaded with the page. Defaults to None.
  • style (Path) - A stylesheet for the renderer. Defaults to None.
  • renders_own_actions (bool) - The renderer places action buttons itself, like Table does per row. Defaults to False.
  • paginated (bool) - Rows are fetched a page at a time through page(). Defaults to False.
  • rollup_safe (bool) - Old events of the source may be averaged together, see EventStore.compact. Defaults to False.

name instance-attribute

name

source class-attribute instance-attribute

source = ''

title class-attribute instance-attribute

title = None

actions class-attribute instance-attribute

actions = field(default_factory=list)

action_args class-attribute instance-attribute

action_args = field(default_factory=dict)

warned class-attribute instance-attribute

warned = field(default_factory=set, init=False, repr=False, compare=False)

type class-attribute

type = 'widget'

op class-attribute

op = 'replace'

script class-attribute

script = None

style class-attribute

style = None

renders_own_actions class-attribute

renders_own_actions = False

rollup_safe class-attribute

rollup_safe = False

paginated class-attribute

paginated = False

warn

warn(field, value)

Say a field could not be read, once, however often it arrives.

Source code in dachshund/widgets/base.py
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def warn(self, field: str, value: Any) -> None:
    """Say a field could not be read, once, however often it arrives."""
    if field in self.warned:
        return

    self.warned.add(field)

    if value is None:
        logger.warning(
            "%r carries no %r, so it leaves a gap in %r.",
            self.source,
            field,
            self.name,
        )
    else:
        logger.warning(
            "%r is not a number, so %r leaves a gap in %r.",
            value,
            field,
            self.name,
        )

value

value(event, field)

Read a field of an event as a number.

Source code in dachshund/widgets/base.py
131
132
133
134
135
136
137
138
139
140
141
142
143
def value(self, event: Event, field: str) -> float | None:
    """Read a field of an event as a number."""
    if field not in event.payload:
        self.warn(field, None)
        return None

    raw = event.payload[field]
    value = numeric(raw)

    if value is None and raw is not None:
        self.warn(field, raw)

    return value

render

render(events)

Build the whole card from the events kept for its source.

Source code in dachshund/widgets/base.py
145
146
147
def render(self, events: Sequence[Event]) -> dict[str, Any]:
    """Build the whole card from the events kept for its source."""
    raise NotImplementedError

page async

page(events, query, context, host_loop=None)

One page of this widget's rows, as query asks for.

context and host_loop only matter to a widget that calls out to a host-supplied callable to build it. Only called on a paginated widget.

Source code in dachshund/widgets/base.py
149
150
151
152
153
154
155
156
157
158
159
160
161
162
async def page(
    self,
    events: Sequence[Event],
    query: TableQuery,
    context: Context,
    host_loop: asyncio.AbstractEventLoop | None = None,
) -> dict[str, Any]:
    """One page of this widget's rows, as `query` asks for.

    `context` and `host_loop` only matter to a widget that calls out to a
    host-supplied callable to build it. Only called on a `paginated`
    widget.
    """
    raise NotImplementedError

update

update(event)

Build the change a single new event makes, if it makes one.

Source code in dachshund/widgets/base.py
164
165
166
def update(self, event: Event) -> dict[str, Any] | None:
    """Build the change a single new event makes, if it makes one."""
    raise NotImplementedError

window

window()

The stored window this widget aggregates, None to render its kept events.

Source code in dachshund/widgets/base.py
168
169
170
def window(self) -> Window | None:
    """The stored window this widget aggregates, `None` to render its kept events."""
    return None

render_buckets

render_buckets(buckets)

Build the whole card from window()'s buckets, by field.

Source code in dachshund/widgets/base.py
172
173
174
def render_buckets(self, buckets: Mapping[str, Sequence[Bucket]]) -> dict[str, Any]:
    """Build the whole card from `window()`'s buckets, by field."""
    raise NotImplementedError

raw_events

raw_events()

How many of its source's newest events stay raw, None for the default.

Source code in dachshund/widgets/base.py
176
177
178
def raw_events(self) -> int | None:
    """How many of its source's newest events stay raw, `None` for the default."""
    return None

bind

bind(dashboard)

Called when the widget goes on dashboard, and when it starts again.

Source code in dachshund/widgets/base.py
180
181
def bind(self, dashboard: Any) -> None:
    """Called when the widget goes on `dashboard`, and when it starts again."""

unbind

unbind()

Called when the widget leaves its dashboard, and when it stops.

Source code in dachshund/widgets/base.py
183
184
def unbind(self) -> None:
    """Called when the widget leaves its dashboard, and when it stops."""