posit-dev / py-shinywidgets

Render ipywidgets inside a PyShiny app
MIT License
46 stars 5 forks source link

Importing ipyreact after shinywidgets causes an error on shiny app initialization #163

Closed machow closed 1 month ago

machow commented 1 month ago

I'm guessing either shinywidgets or ipyreact (or both) sets a hook somewhere on import.

This express app works for me:

from shiny.express import ui, render

from ipyreact import Widget
from shinywidgets import render_widget

ui.h1("yo")

However, switching the ipyreact and shinywidget imports raises an error:

from shiny.express import ui, render

from shinywidgets import render_widget        # <--- shinywidgets first now
from ipyreact import Widget

ui.h1("yo")

Here's the traceback:

``` Process SpawnProcess-2: Traceback (most recent call last): File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/traitlets/traitlets.py", line 632, in get value = obj._trait_values[self.name] KeyError: 'layout' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/shiny/express/_run.py", line 220, in run_express exec( File "/Users/machow/repos/reactable-py/app-ipyreact.py", line 4, in from ipyreact import Widget File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipyreact/__init__.py", line 8, in from .importmap import define_import_map File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipyreact/importmap.py", line 70, in define_import_map( File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipyreact/importmap.py", line 54, in define_import_map _update_import_map() File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipyreact/importmap.py", line 66, in _update_import_map _get_import_map_widget().import_map = _effective_import_map File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipyreact/importmap.py", line 61, in _get_import_map_widget _import_map_widget = ImportMap(import_map=_effective_import_map) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 505, in __init__ Widget._call_widget_constructed(self) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 365, in _call_widget_constructed Widget._widget_construction_callback(widget) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/shinywidgets/_shinywidgets.py", line 65, in init_shiny_widget state, buffer_paths, buffers = _remove_buffers(w.get_state()) # type: ignore File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 615, in get_state value = to_json(getattr(self, k), self) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/traitlets/traitlets.py", line 687, in __get__ return t.cast(G, self.get(obj, cls)) # the G should encode the Optional File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/traitlets/traitlets.py", line 635, in get default = obj.trait_defaults(self.name) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/traitlets/traitlets.py", line 1897, in trait_defaults return t.cast(Sentinel, self._get_trait_default_generator(names[0])(self)) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/traitlets/traitlets.py", line 602, in default return t.cast(G, self.make_dynamic_default()) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipywidgets/widgets/trait_types.py", line 409, in make_dynamic_default return self.klass(*(self.default_args or ()), File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipywidgets/widgets/widget_layout.py", line 86, in __init__ super().__init__(**kwargs) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 505, in __init__ Widget._call_widget_constructed(self) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/ipywidgets/widgets/widget.py", line 365, in _call_widget_constructed Widget._widget_construction_callback(widget) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/shinywidgets/_shinywidgets.py", line 113, in init_shiny_widget session.app._dependency_handler.mount( AttributeError: 'NoneType' object has no attribute '_dependency_handler' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/Users/machow/.pyenv/versions/3.9.5/lib/python3.9/multiprocessing/process.py", line 315, in _bootstrap self.run() File "/Users/machow/.pyenv/versions/3.9.5/lib/python3.9/multiprocessing/process.py", line 108, in run self._target(*self._args, **self._kwargs) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/uvicorn/_subprocess.py", line 80, in subprocess_started target(sockets=sockets) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/uvicorn/server.py", line 65, in run return asyncio.run(self.serve(sockets=sockets)) File "/Users/machow/.pyenv/versions/3.9.5/lib/python3.9/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/Users/machow/.pyenv/versions/3.9.5/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete return future.result() File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/uvicorn/server.py", line 69, in serve await self._serve(sockets) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/uvicorn/server.py", line 76, in _serve config.load() File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/uvicorn/config.py", line 434, in load self.loaded_app = import_from_string(self.app) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/uvicorn/importer.py", line 29, in import_from_string instance = getattr(instance, attr_str) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/shiny/express/app.py", line 13, in __getattr__ return wrap_express_app(Path(name)) File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/shiny/express/_run.py", line 62, in wrap_express_app app_module = importlib.import_module(package_name) File "/Users/machow/.pyenv/versions/3.9.5/lib/python3.9/importlib/__init__.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "", line 1030, in _gcd_import File "", line 1007, in _find_and_load File "", line 986, in _find_and_load_unlocked File "", line 680, in _load_unlocked File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/shiny/express/_run.py", line 102, in exec_module module.app = create_express_app( # pyright: ignore[reportAttributeAccessIssue] File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/shiny/express/_run.py", line 132, in create_express_app app_ui = run_express(file, package_name).tagify() File "/Users/machow/.virtualenvs/reactable-py/lib/python3.9/site-packages/shiny/express/_run.py", line 255, in run_express raise RuntimeError(e) from e RuntimeError: 'NoneType' object has no attribute '_dependency_handler' ```
cpsievert commented 1 month ago

Ah, thanks for the report! Should be fixed by https://github.com/posit-dev/py-shinywidgets/commit/37c71787581c3ef859bd16daaf674228f13689ab