Skip to content

Converting go.Figure into go.FigureWidget causes error for date axis #3075

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
stephprobst opened this issue Feb 16, 2021 · 4 comments · Fixed by ipython/ipykernel#1057
Closed

Comments

@stephprobst
Copy link

Converting a go.Figure object into a go.FigureWidget object causes a serialization error.

Environment:

Plotly version: 4.14.1
Jupyter Lab version: 3.0.0
Windows 10

Sample code:

import plotly.graph_objects as go
from datetime import date
fig = go.Figure(data=go.Bar(
    x=[date(2017,1,1), date(2017,1,2), date(2017,1,3)],
    y=[2, 3, 1]))
go.FigureWidget(fig)

Error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-21-73510c9ecfe4> in <module>
      1 fig = my_chart.plotly_figure
----> 2 go.FigureWidget(fig)
C:\ProgramData\Anaconda3\lib\site-packages\plotly\graph_objs\_figurewidget.py in __init__(self, data, layout, frames, skip_invalid, **kwargs)
    594             is invalid AND skip_invalid is False
    595         """
--> 596         super(FigureWidget, self).__init__(data, layout, frames, skip_invalid, **kwargs)
    597 
    598     def add_area(
C:\ProgramData\Anaconda3\lib\site-packages\plotly\basewidget.py in __init__(self, data, layout, frames, skip_invalid, **kwargs)
    115         # with the `layout` constructor parameter of the `widgets.DOMWidget`
    116         # ipywidgets class
--> 117         super(BaseFigureWidget, self).__init__(
    118             data=data,
    119             layout_plotly=layout,
C:\ProgramData\Anaconda3\lib\site-packages\plotly\basedatatypes.py in __init__(self, data, layout_plotly, frames, skip_invalid, **kwargs)
    524         # The _data property is a list of dicts containing the properties
    525         # explicitly set by the user for each trace.
--> 526         self._data = [deepcopy(trace._props) for trace in data]
    527 
    528         # ### Create data defaults ###
C:\ProgramData\Anaconda3\lib\site-packages\plotly\basedatatypes.py in __setattr__(self, prop, value)
    719         if prop.startswith("_") or hasattr(self, prop):
    720             # Let known properties and private properties through
--> 721             super(BaseFigure, self).__setattr__(prop, value)
    722         else:
    723             # Raise error on unknown public properties
C:\ProgramData\Anaconda3\lib\site-packages\traitlets\traitlets.py in __set__(self, obj, value)
    583             raise TraitError('The "%s" trait is read-only.' % self.name)
    584         else:
--> 585             self.set(obj, value)
    586 
    587     def _validate(self, obj, value):
C:\ProgramData\Anaconda3\lib\site-packages\traitlets\traitlets.py in set(self, obj, value)
    572             # we explicitly compare silent to True just in case the equality
    573             # comparison above returns something other than True/False
--> 574             obj._notify_trait(self.name, old_value, new_value)
    575 
    576     def __set__(self, obj, value):
C:\ProgramData\Anaconda3\lib\site-packages\traitlets\traitlets.py in _notify_trait(self, name, old_value, new_value)
   1132 
   1133     def _notify_trait(self, name, old_value, new_value):
-> 1134         self.notify_change(Bunch(
   1135             name=name,
   1136             old=old_value,
C:\ProgramData\Anaconda3\lib\site-packages\ipywidgets\widgets\widget.py in notify_change(self, change)
    603             if name in self.keys and self._should_send_property(name, getattr(self, name)):
    604                 # Send new state to front-end
--> 605                 self.send_state(key=name)
    606         super(Widget, self).notify_change(change)
    607 
C:\ProgramData\Anaconda3\lib\site-packages\ipywidgets\widgets\widget.py in send_state(self, key)
    487             state, buffer_paths, buffers = _remove_buffers(state)
    488             msg = {'method': 'update', 'state': state, 'buffer_paths': buffer_paths}
--> 489             self._send(msg, buffers=buffers)
    490 
    491 
C:\ProgramData\Anaconda3\lib\site-packages\ipywidgets\widgets\widget.py in _send(self, msg, buffers)
    735         """Sends a message to the model in the front-end."""
    736         if self.comm is not None and self.comm.kernel is not None:
--> 737             self.comm.send(data=msg, buffers=buffers)
    738 
    739     def _repr_keys(self):
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\comm\comm.py in send(self, data, metadata, buffers)
    120     def send(self, data=None, metadata=None, buffers=None):
    121         """Send a message to the frontend-side version of this comm"""
--> 122         self._publish_msg('comm_msg',
    123             data=data, metadata=metadata, buffers=buffers,
    124         )
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\comm\comm.py in _publish_msg(self, msg_type, data, metadata, buffers, **keys)
     63         data = {} if data is None else data
     64         metadata = {} if metadata is None else metadata
---> 65         content = json_clean(dict(data=data, comm_id=self.comm_id, **keys))
     66         self.kernel.session.send(self.kernel.iopub_socket, msg_type,
     67             content,
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\jsonutil.py in json_clean(obj)
    189         out = {}
    190         for k,v in iteritems(obj):
--> 191             out[unicode_type(k)] = json_clean(v)
    192         return out
    193     if isinstance(obj, datetime):
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\jsonutil.py in json_clean(obj)
    189         out = {}
    190         for k,v in iteritems(obj):
--> 191             out[unicode_type(k)] = json_clean(v)
    192         return out
    193     if isinstance(obj, datetime):
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\jsonutil.py in json_clean(obj)
    189         out = {}
    190         for k,v in iteritems(obj):
--> 191             out[unicode_type(k)] = json_clean(v)
    192         return out
    193     if isinstance(obj, datetime):
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\jsonutil.py in json_clean(obj)
    175 
    176     if isinstance(obj, list):
--> 177         return [json_clean(x) for x in obj]
    178 
    179     if isinstance(obj, dict):
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\jsonutil.py in <listcomp>(.0)
    175 
    176     if isinstance(obj, list):
--> 177         return [json_clean(x) for x in obj]
    178 
    179     if isinstance(obj, dict):
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\jsonutil.py in json_clean(obj)
    189         out = {}
    190         for k,v in iteritems(obj):
--> 191             out[unicode_type(k)] = json_clean(v)
    192         return out
    193     if isinstance(obj, datetime):
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\jsonutil.py in json_clean(obj)
    175 
    176     if isinstance(obj, list):
--> 177         return [json_clean(x) for x in obj]
    178 
    179     if isinstance(obj, dict):
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\jsonutil.py in <listcomp>(.0)
    175 
    176     if isinstance(obj, list):
--> 177         return [json_clean(x) for x in obj]
    178 
    179     if isinstance(obj, dict):
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\jsonutil.py in json_clean(obj)
    195 
    196     # we don't understand it, it's probably an unserializable object
--> 197     raise ValueError("Can't clean for JSON: %r" % obj)
ValueError: Can't clean for JSON: datetime.date(2017, 1, 1)
@nicolaskruchten
Copy link
Contributor

@jonmmease is there a straightforward fix we can think of here, or is this a structural issue?

@jonmmease
Copy link
Contributor

FigureWidget has it's own serialization logic. So there's probably some datetime logic missing there.

@gvwilson
Copy link
Contributor

Hi - we are trying to tidy up the stale issues and PRs in Plotly's public repositories so that we can focus on things that are still important to our community. Since this one has been sitting for several years, I'm going to close it; if it is still a concern, please add a comment letting us know what recent version of our software you've checked it with so that I can reopen it and add it to our backlog. Thanks for your help - @gvwilson

@sebwills
Copy link

@gvwilson This has regressed (or is still broken) in both plotly 5.24.1 and plotly 6.0.1

This PR resolves it for plotly 6: jupyter/jupyter_client#1060

Don't know if someone here is able to nudge jupyter people into reviewing it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants