1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
from __future__ import annotations
import weakref
from bokeh.core.properties import without_property_validation
class DashboardComponent:
"""Base class for Dask.distributed UI dashboard components.
This class must have two attributes, ``root`` and ``source``, and one
method ``update``:
* source: a Bokeh ColumnDataSource
* root: a Bokeh Model
* update: a method that consumes the messages dictionary found in
distributed.bokeh.messages
"""
def __init__(self):
self.source = None
self.root = None
def update(self, messages):
"""Reads from bokeh.distributed.messages and updates self.source"""
def add_periodic_callback(doc, component, interval):
"""Add periodic callback to doc in a way that avoids reference cycles
If we instead use ``doc.add_periodic_callback(component.update, 100)`` then
the component stays in memory as a reference cycle because its method is
still around. This way we avoid that and let things clean up a bit more
nicely.
TODO: we still have reference cycles. Docs seem to be referred to by their
add_periodic_callback methods.
"""
ref = weakref.ref(component)
doc.add_periodic_callback(lambda: update(ref), interval)
_attach(doc, component)
@without_property_validation
def update(ref):
comp = ref()
if comp is not None:
comp.update()
def _attach(doc, component):
if not hasattr(doc, "components"):
doc.components = set()
doc.components.add(component)
|