Closed keller-mark closed 1 year ago
Thanks for the issue. I ran into something similar in Google Colab (#48), and tried to implemented a specific fix for that environment #52 to allow for backwards compatibility with ipywidgets
v7/8. I will try to reproduce this issue in Jupyter, and then perhaps we can just extend the fix in #52 for all environments.
Ok, I went down a bit of a rabbit hole today with this. However, I have not been able to reproduce the issue in Jupyter/JupyterLab – only Google Colab. Therefore, I'm not sure if this exploration directly addresses this issue, but I have have a deeper understanding of how Colab/Jupyter differ in terms of displaying custom widgets.
TL;DR - the message sent from Python to display the front end requires additional metadata for colab. This metadata is injected by Colab when custom widgets are enabled, but only in the case of display_data
messages and not execute_cell
messages. We can potentially fix this by injecting the metadata ourselves within _repr_mimebundle_
.
At a high level, when you execute a cell, the object at the end of the block is passed to sys.displayhook
. So you can reproduce bug with ipywidgets==8.0.4
in Colab with:
import sys
counter = Counter()
sys.displayhook(counter) # 'Widget anywidget AnyModel is not supported' in browser console
in Colab, this triggers a prompt telling the user to enable custom widgets,
which does not resolve the issue does not resolve the issue. However, if you manually call IPython.display.display
, the widget displays
from IPython.display import display
display(counter) # works if custom widgets are enabled
What gives?
The main difference is that kernel messages sent from sys.displayhook
and display
are just slightly different. Both functions create a msg
dictionary and then call jupyter_client.session.Session.send(<stream>, msg)
to send the payload to the front end. You can inspect these messages by enabling logging on the session
:
sys.displayhook.session.debug = True
sys.displayhook(counter)
display(counter)
sys.displayhook.session.debug = False
sys.displayhook
creates a message of type execute_result
whereas display
creates a message of type display_data
. This alone is not the issue, but moreover that display
internally has a "hook" to allow plugins to modify the message contents (which Colab makes use of to enable custom widgets) and sys.displayhook
does not. Therefore, messages created with display
have the appropriate metadata and execute_results
do not (regardless of whether custom widgets are enabled). This can be seen by diffing msg
contents:
execute_result
, created with sys.displayhook
{'content': {'data': {'application/vnd.jupyter.widget-view+json': {'model_id': 'e475d038722645829dc019e6ce546591',
'version_major': 2,
'version_minor': 0},
'text/plain': 'Counter()'},
'execution_count': 77,
-- 'metadata': {}},
}
display_data
, created with display
(with widgets disabled){'content': {'data': {'application/vnd.jupyter.widget-view+json': {'model_id': 'e475d038722645829dc019e6ce546591',
'version_major': 2,
'version_minor': 0},
'text/plain': 'Counter()'},
-- 'metadata': {},
'transient': {}},
display_data
, created with display
(with widgets enabled){'content': {'data': {'application/vnd.jupyter.widget-view+json': {'model_id': 'e475d038722645829dc019e6ce546591',
'version_major': 2,
'version_minor': 0},
'text/plain': 'Counter()'},
++ 'metadata': {'application/vnd.jupyter.widget-view+json': {'colab': {'custom_widget_manager': {'url': 'https://ssl.gstatic.com/colaboratory-static/widgets/colab-cdn-widget-manager/b3e629b1971e1542/manager.min.js'}}}},
'transient': {}},
Only the last message displays the widget correctly because it's the only case where the colab metadata is sent to the front end. This metadata is injected by a hook included in
So what to do? In anywidget
we could could just inject this metadata ourselves and both execute_result
and display_data
would render correctly:
def _repr_mimebundle_(self, **kwargs):
try:
import google.colab.output._widgets
url = google.colab.output._widgets._installed_url
except ImportError:
url = None
meta = {}
if url:
meta["application/vnd.jupyter.widget-view+json"] = { 'colab': {'custom_widget_manager': {'url': url} } }
data = super()._repr_mimebundle_(**kwargs)
return data, meta
The latest release of anywidget should have more robust rendering for both ipywidget v7 and v8. I'm going to close this for now, but feel free to open again if issues arise.
Working with a collaborator who is having issues using the vitessce widget. They see the error
I believe it is related to https://stackoverflow.com/questions/73715821/jupyter-lab-issue-displaying-widgets-javascript-error and https://github.com/jupyterlab/jupyterlab/issues/12977#issuecomment-1221309124
Based on the environment info they shared with me, I am guessing they must have had
ipywidgets==8.0.4
installed before trying to install vitessce (of course I can add a dependency on a specificipywidgets
version in thevitessce
package, but probably best to fix at the anywidget level)Minimal reproducer: https://colab.research.google.com/drive/1QkDXWsvyXISdGbR5ETb8HvOqR719lG9s?usp=sharing