File: C:/Users/fred/anaconda3/Lib/site-packages/intake/interface/base.py
# -----------------------------------------------------------------------------
# Copyright (c) 2012 - 2019, Anaconda, Inc. and Intake contributors
# All rights reserved.
#
# The full license is in the LICENSE file, distributed with this software.
# -----------------------------------------------------------------------------
import os
from collections import OrderedDict
import panel as pn
MAX_WIDTH = 5000
here = os.path.abspath(os.path.dirname(__file__))
ICONS = {
"logo": os.path.join(here, "icons", "logo.png"),
"error": os.path.join(here, "icons", "baseline-error-24px.svg"),
}
def enable_widget(widget, enable=True):
"""Set disabled on widget"""
widget.disabled = not enable
def coerce_to_list(items, preprocess=None):
"""Given an instance or list, coerce to list.
With optional preprocessing.
"""
if not isinstance(items, list):
items = [items]
if preprocess:
items = list(map(preprocess, items))
return items
class Base(object):
"""
Base class for composable panel objects that make up the GUI.
Parameters
----------
children: list of panel objects
children that will be used to populate the panel when visible
panel: panel layout object
instance of a panel layout (row or column) that contains children
when visible
watchers: list of param watchers
watchers that are set on children - cleaned up when visible
is set to false.
visible: bool
whether or not the instance should be visible. When not visible
``panel`` is empty.
logo : bool, opt
whether to show the intake logo in a panel to the left of the main
panel. Default is False
"""
children = None
panel = None
watchers = None
visible_callback = None
logo_panel = pn.Column(
pn.pane.PNG(ICONS["logo"], align="center"), margin=(25, 0, 0, 0), width=50
)
logo = False
def __init__(self, visible=True, visible_callback=None, logo=False):
self.visible = visible
self.visible_callback = visible_callback
self.logo = logo
@property
def panel(self):
if not self.logo:
return self._panel
return pn.Row(self.logo_panel, self._panel, margin=0)
@panel.setter
def panel(self, panel):
self._panel = panel
def servable(self, *args, **kwargs):
return self.panel.servable(*args, **kwargs)
def show(self, *args, **kwargs):
return self.panel.show(*args, **kwargs)
def __repr__(self):
"""Print output"""
return self.panel.__repr__()
def _repr_mimebundle_(self, *args, **kwargs):
"""Display in a notebook or a server"""
try:
return self.panel._repr_mimebundle_(*args, **kwargs)
except Exception:
raise NotImplementedError("Panel does not seem to be set " "up properly")
def setup(self):
"""Should instantiate widgets, set ``children``, and set watchers"""
raise NotImplementedError
@property
def visible(self):
"""Whether or not the instance should be visible."""
return self._visible
@visible.setter
def visible(self, visible):
"""When visible changed, do setup or unwatch and call visible_callback"""
self._visible = visible
pan = getattr(self._panel, "_layout", self._panel)
if visible and len(pan.objects) == 0:
self.setup()
self._panel.extend(self.children)
elif not visible and len(pan.objects) > 0:
self.unwatch()
pan.clear()
if self.visible_callback:
self.visible_callback(visible)
def unwatch(self):
"""Get rid of any lingering watchers and remove from list"""
if self.watchers is not None:
unwatched = []
for watcher in self.watchers:
watcher.inst.param.unwatch(watcher)
unwatched.append(watcher)
self.watchers = [w for w in self.watchers if w not in unwatched]
def __getstate__(self):
"""Serialize the current state of the object"""
return {"visible": self.visible}
def __setstate__(self, state):
"""Set the current state of the object from the serialized version.
Works inplace. See ``__getstate__`` to get serialized version and
``from_state`` to create a new object."""
self.visible = state.get("visible", True)
return self
@classmethod
def from_state(cls, state):
"""Create a new object from a serialized exising object.
Examples
--------
original = cls()
copy = cls.from_state(original.__getstate__())
"""
return cls().__setstate__(state)
class BaseSelector(Base):
"""Base class for capturing selector logic.
Parameters
----------
preprocess: function
run on every input value when creating options
widget: panel widget
selector widget which this class keeps uptodate with class properties
"""
preprocess = None
widget = None
@property
def labels(self):
"""Labels of items in widget"""
return self.widget.labels
@property
def items(self):
"""Available items to select from"""
return self.widget.values
@items.setter
def items(self, items):
"""When setting items make sure widget options are uptodate"""
if items is not None:
self.options = items
def _create_options(self, items):
"""Helper method to create options from list, or instance.
Applies preprocess method if available to create a uniform
output
"""
return OrderedDict(map(lambda x: (x.name, x), coerce_to_list(items, self.preprocess)))
@property
def options(self):
"""Options available on the widget"""
return self.widget.options
@options.setter
def options(self, new):
"""Set options from list, or instance of named item
Over-writes old options
"""
options = self._create_options(new)
if self.widget.value:
self.widget.set_param(options=options, value=list(options.values())[:1])
else:
self.widget.options = options
self.widget.value = list(options.values())[:1]
def add(self, items):
"""Add items to options"""
options = self._create_options(items)
for k, v in options.items():
if k in self.labels and v not in self.items:
options.pop(k)
count = 0
while f"{k}_{count}" in self.labels:
count += 1
options[f"{k}_{count}"] = v
self.widget.options.update(options)
self.widget.param.trigger("options")
self.widget.value = list(options.values())[:1]
def remove(self, items):
"""Remove items from options"""
items = coerce_to_list(items)
new_options = {k: v for k, v in self.options.items() if v not in items}
self.widget.options = new_options
self.widget.param.trigger("options")
@property
def selected(self):
"""Value selected on the widget"""
ops = self.widget.options
return [
val
for val in self.widget.value
if (val in ops.values() if isinstance(ops, dict) else val in ops)
]
@selected.setter
def selected(self, new):
"""Set selected from list or instance of object or name.
Over-writes existing selection
"""
def preprocess(item):
if isinstance(item, str):
return self.options[item]
return item
items = coerce_to_list(new, preprocess)
self.widget.value = items
class BaseView(Base):
def __getstate__(self, include_source=True):
"""Serialize the current state of the object. Set include_source
to False when using with another panel that will include source."""
if include_source:
return {
"visible": self.visible,
"label": self.source._name,
"source": self.source.__getstate__(),
}
else:
return {"visible": self.visible}
def __setstate__(self, state):
"""Set the current state of the object from the serialized version.
Works inplace. See ``__getstate__`` to get serialized version and
``from_state`` to create a new object."""
if "source" in state:
self.source = state["source"]
self.visible = state.get("visible", True)
@property
def source(self):
return self._source
@source.setter
def source(self, source):
"""When the source gets updated, update the select widget"""
if isinstance(source, list):
# if source is a list, get first item or None
source = source[0] if len(source) > 0 else None
self._source = source