|
|
- from traitlets import Any, Unicode, List, Dict
- from ipywidgets import DOMWidget
- from ipywidgets.widgets.widget import widget_serialization
- from ._version import semver
- from .ForceLoad import force_load_instance
- import inspect
- from importlib import import_module
-
- OBJECT_REF = 'objectRef'
- FUNCTION_REF = 'functionRef'
-
- class Events(object):
- def __init__(self, **kwargs):
- self.on_msg(self._handle_event)
- self.events = [item[4:] for item in dir(self) if item.startswith("vue_")]
-
- def _handle_event(self, _, content, buffers):
- def resolve_ref(value):
- if isinstance(value, dict):
- if OBJECT_REF in value.keys():
- obj = getattr(self, value[OBJECT_REF])
- for path_item in value.get('path', []):
- obj = obj[path_item]
- return obj
- if FUNCTION_REF in value.keys():
- fn = getattr(self, value[FUNCTION_REF])
- args = value.get('args', [])
- kwargs = value.get('kwargs', {})
- return fn(*args, **kwargs)
- return value
-
- if 'create_widget' in content.keys():
- module_name = content['create_widget'][0]
- class_name = content['create_widget'][1]
- props = {k: resolve_ref(v) for k, v in content['props'].items()}
- module = import_module(module_name)
- widget = getattr(module, class_name)(**props, model_id=content['id'])
- self._component_instances = [*self._component_instances, widget]
- elif 'update_ref' in content.keys():
- widget = DOMWidget.widgets[content['id']]
- prop = content['prop']
- obj = resolve_ref(content['update_ref'])
- setattr(widget, prop, obj)
- elif 'destroy_widget' in content.keys():
- self._component_instances = [w for w in self._component_instances
- if w.model_id != content['destroy_widget']]
- elif 'event' in content.keys():
- event = content.get("event", "")
- data = content.get("data", {})
- getattr(self, 'vue_' + event)(data)
-
-
- def _value_to_json(x, obj):
- if inspect.isclass(x):
- return {
- 'class': [x.__module__, x.__name__],
- 'props': x.class_trait_names()
- }
- return widget_serialization['to_json'](x, obj)
-
-
- def _class_to_json(x, obj):
- if not x:
- return widget_serialization['to_json'](x, obj)
- return {k: _value_to_json(v, obj) for k, v in x.items()}
-
-
- def as_refs(name, data):
- def to_ref_structure(obj, path):
- if isinstance(obj, list):
- return [to_ref_structure(item, [*path, index]) for index, item in enumerate(obj)]
- if isinstance(obj, dict):
- return {k: to_ref_structure(v, [*path, k]) for k, v in obj.items()}
-
- # add object id to detect a new object in the same structure
- return {OBJECT_REF: name, 'path': path, 'id': id(obj)}
-
- return to_ref_structure(data, [])
-
-
- class VueTemplate(DOMWidget, Events):
-
- class_component_serialization = {
- 'from_json': widget_serialization['to_json'],
- 'to_json': _class_to_json
- }
-
- # Force the loading of jupyter-vue before dependent extensions when in a static context (embed,
- # voila)
- _jupyter_vue = Any(force_load_instance, read_only=True).tag(sync=True, **widget_serialization)
-
- _model_name = Unicode('VueTemplateModel').tag(sync=True)
-
- _view_name = Unicode('VueView').tag(sync=True)
-
- _view_module = Unicode('jupyter-vue').tag(sync=True)
-
- _model_module = Unicode('jupyter-vue').tag(sync=True)
-
- _view_module_version = Unicode(semver).tag(sync=True)
-
- _model_module_version = Unicode(semver).tag(sync=True)
-
- template = Unicode(None, allow_none=True).tag(sync=True)
-
- css = Unicode(None, allow_none=True).tag(sync=True)
-
- methods = Unicode(None, allow_none=True).tag(sync=True)
-
- data = Unicode(None, allow_none=True).tag(sync=True)
-
- events = List(Unicode(), default_value=None, allow_none=True).tag(sync=True)
-
- components = Dict(default_value=None, allow_none=True).tag(
- sync=True, **class_component_serialization)
-
- _component_instances = List().tag(sync=True, **widget_serialization)
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- sync_ref_traitlets = [v for k, v in self.traits().items()
- if 'sync_ref' in v.metadata.keys()]
-
- def create_ref_and_observe(traitlet):
- data = traitlet.get(self)
- ref_name = traitlet.name + '_ref'
- self.add_traits(**{ref_name: Any(as_refs(traitlet.name, data)).tag(sync=True)})
-
- def on_ref_source_change(change):
- setattr(self, ref_name, as_refs(traitlet.name, change['new']))
-
- self.observe(on_ref_source_change, traitlet.name)
-
- for traitlet in sync_ref_traitlets:
- create_ref_and_observe(traitlet)
-
-
- __all__ = ['VueTemplate']
|