Skip to content

Commit

Permalink
fix: avoid using a global force_load widget
Browse files Browse the repository at this point in the history
  • Loading branch information
maartenbreddels committed Feb 23, 2023
1 parent 2638b7b commit 5289093
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 11 deletions.
3 changes: 0 additions & 3 deletions ipyvue/ForceLoad.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,3 @@ class ForceLoad(DOMWidget):
_model_name = Unicode("ForceLoadModel").tag(sync=True)
_model_module = Unicode("jupyter-vue").tag(sync=True)
_model_module_version = Unicode(semver).tag(sync=True)


force_load_instance = ForceLoad()
14 changes: 9 additions & 5 deletions ipyvue/VueTemplateWidget.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import os
from traitlets import Any, Unicode, List, Dict, Union, Instance
from traitlets import Any, Unicode, List, Dict, Union, Instance, default
from ipywidgets import DOMWidget
from ipywidgets.widgets.widget import widget_serialization

from .Template import Template, get_template
from ._version import semver
from .ForceLoad import force_load_instance
from .ForceLoad import ForceLoad
from .util import singleton
import inspect
from importlib import import_module

Expand Down Expand Up @@ -94,12 +95,15 @@ class VueTemplate(DOMWidget, Events):
"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(
# see VueWidget
_jupyter_vue = Instance(ForceLoad, read_only=True).tag(
sync=True, **widget_serialization
)

@default("_jupyter_vue")
def _default_jupyter_vue(self):
return singleton(ForceLoad)

_model_name = Unicode("VueTemplateModel").tag(sync=True)

_view_name = Unicode("VueView").tag(sync=True)
Expand Down
16 changes: 13 additions & 3 deletions ipyvue/VueWidget.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from traitlets import Unicode, Instance, Union, List, Any, Dict
from traitlets import Unicode, Instance, Union, List, Any, Dict, default
from ipywidgets import DOMWidget
from ipywidgets.widgets.widget import widget_serialization, CallbackDispatcher

from ._version import semver
from .ForceLoad import force_load_instance
from .ForceLoad import ForceLoad
from .util import singleton


class ClassList:
Expand Down Expand Up @@ -113,10 +115,18 @@ class VueWidget(DOMWidget, Events):

# 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(
# this happens when e.g. jupyter-vuedraggable requires jupyter-vue, but it is not
# loaded yet (via a widget creation). This does not trigger the library loading
# via the widget manager, but straight through requirejs

_jupyter_vue = Instance(ForceLoad, read_only=True).tag(
sync=True, **widget_serialization
)

@default("_jupyter_vue")
def _default_jupyter_vue(self):
return singleton(ForceLoad)

_model_name = Unicode("VueModel").tag(sync=True)

_view_name = Unicode("VueView").tag(sync=True)
Expand Down
24 changes: 24 additions & 0 deletions ipyvue/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from ipywidgets import Widget
import threading


lock = threading.Lock()


def singleton(WidgetClass, **kwargs):
# find a 'shared' instance (singleton) to avoid creating
# too many widgets. In contexts where self.widgets is not
# a global dict, this allows different users/context to
# have a singleton without sharing the widget
with lock:
if hasattr(Widget, "widgets"):
# pre 8.0
all_widgets = Widget.widgets
if hasattr(Widget, "widgets"):
all_widgets = Widget._widgets
else:

for widget in all_widgets.values():
if isinstance(widget, WidgetClass):
return widget
return WidgetClass(**kwargs)

0 comments on commit 5289093

Please sign in to comment.