diff --git a/_plotly_future_/trace_uids.py b/_plotly_future_/trace_uids.py new file mode 100644 index 00000000000..d110359e5dc --- /dev/null +++ b/_plotly_future_/trace_uids.py @@ -0,0 +1,5 @@ +from __future__ import absolute_import +from _plotly_future_ import _future_flags, _assert_plotly_not_imported + +_assert_plotly_not_imported() +_future_flags.add('trace_uids') diff --git a/_plotly_future_/v4.py b/_plotly_future_/v4.py index a4acb8cf132..ae38031e034 100644 --- a/_plotly_future_/v4.py +++ b/_plotly_future_/v4.py @@ -6,5 +6,6 @@ remove_deprecations, v4_subplots, orca_defaults, + trace_uids, ) diff --git a/plotly/basedatatypes.py b/plotly/basedatatypes.py index 3144689218f..ac8a5b51111 100644 --- a/plotly/basedatatypes.py +++ b/plotly/basedatatypes.py @@ -26,6 +26,8 @@ from plotly.utils import ElidedPrettyPrinter from .validators import (DataValidator, LayoutValidator, FramesValidator) +from _plotly_future_ import _future_flags + # Create Undefined sentinel value # - Setting a property to None removes any existing value # - Setting a property to Undefined leaves existing value unmodified @@ -49,6 +51,8 @@ class BaseFigure(object): 'plot_bgcolor': 'plot-bgcolor' } + _set_trace_uid = 'trace_uids' not in _future_flags + # Constructor # ----------- def __init__(self, @@ -145,7 +149,7 @@ class is a subclass of both BaseFigure and widgets.DOMWidget. # ### Construct data validator ### # This is the validator that handles importing sequences of trace # objects - self._data_validator = DataValidator(set_uid=True) + self._data_validator = DataValidator(set_uid=self._set_trace_uid) # ### Import traces ### data = self._data_validator.validate_coerce(data, @@ -513,9 +517,9 @@ def data(self, new_data): # Validate new_data # ----------------- - err_header = ('The data property of a figure may only be assigned ' + err_header = ('The data property of a figure may only be assigned \n' 'a list or tuple that contains a permutation of a ' - 'subset of itself\n') + 'subset of itself.\n') # ### Check valid input type ### if not isinstance(new_data, (list, tuple)): @@ -531,16 +535,14 @@ def data(self, new_data): .format(typ=type(trace))) raise ValueError(err_msg) - # ### Check UIDs ### - # Require that no new uids are introduced - orig_uids = [_trace['uid'] for _trace in self._data] - new_uids = [trace.uid for trace in new_data] + # ### Check trace objects ### + # Require that no new traces are introduced + orig_uids = [id(trace) for trace in self.data] + new_uids = [id(trace) for trace in new_data] invalid_uids = set(new_uids).difference(set(orig_uids)) if invalid_uids: - err_msg = ( - err_header + ' Invalid trace(s) with uid(s): {invalid_uids}' - .format(invalid_uids=invalid_uids)) + err_msg = err_header raise ValueError(err_msg) @@ -551,8 +553,7 @@ def data(self, new_data): ] if duplicate_uids: err_msg = ( - err_header + ' Received duplicated traces with uid(s): ' + - '{duplicate_uids}'.format(duplicate_uids=duplicate_uids)) + err_header + ' Received duplicated traces') raise ValueError(err_msg) @@ -562,8 +563,8 @@ def data(self, new_data): delete_inds = [] # ### Unparent removed traces ### - for i, _trace in enumerate(self._data): - if _trace['uid'] in remove_uids: + for i, trace in enumerate(self.data): + if id(trace) in remove_uids: delete_inds.append(i) # Unparent trace object to be removed @@ -575,7 +576,7 @@ def data(self, new_data): # ### Compute trace props / defaults after removal ### traces_props_post_removal = [t for t in self._data] traces_prop_defaults_post_removal = [t for t in self._data_defaults] - uids_post_removal = [trace_data['uid'] for trace_data in self._data] + uids_post_removal = [id(trace_data) for trace_data in self.data] for i in reversed(delete_inds): del traces_props_post_removal[i] diff --git a/plotly/basewidget.py b/plotly/basewidget.py index 1f6806dbfb9..d022f05646f 100644 --- a/plotly/basewidget.py +++ b/plotly/basewidget.py @@ -113,6 +113,8 @@ class BaseFigureWidget(BaseFigure, widgets.DOMWidget): _last_layout_edit_id = Integer(0).tag(sync=True) _last_trace_edit_id = Integer(0).tag(sync=True) + _set_trace_uid = True + # Constructor # ----------- def __init__(self,