From f8deca071f5da5039c2c674055a1e4ea6ef4d06a Mon Sep 17 00:00:00 2001 From: Dmitry Nikulin <1315874+dniku@users.noreply.github.com> Date: Sat, 15 Jun 2024 10:23:35 +0100 Subject: [PATCH] Treat range() as a simple array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://github.com/plotly/plotly.py/issues/1798 (incorrectly closed during a recent cleanup). Allows range() to be passed where simple arrays are expected. Previously the following code ```python import plotly.graph_objects as go go.Figure(go.Scatter(x=range(3), y=[3, 2, 1])) ``` failed with ``` --------------------------------------------------------------------------- ValueError Traceback (most recent call last) in () 1 import plotly.graph_objects as go ----> 2 go.Figure(go.Scatter(x=range(3), y=[3, 2, 1])) 5 frames /usr/local/lib/python3.10/dist-packages/plotly/graph_objs/_scatter.py in __init__(self, arg, alignmentgroup, cliponaxis, connectgaps, customdata, customdatasrc, dx, dy, error_x, error_y, fill, fillcolor, fillpattern, groupnorm, hoverinfo, hoverinfosrc, hoverlabel, hoveron, hovertemplate, hovertemplatesrc, hovertext, hovertextsrc, ids, idssrc, legend, legendgroup, legendgrouptitle, legendrank, legendwidth, line, marker, meta, metasrc, mode, name, offsetgroup, opacity, orientation, selected, selectedpoints, showlegend, stackgaps, stackgroup, stream, text, textfont, textposition, textpositionsrc, textsrc, texttemplate, texttemplatesrc, uid, uirevision, unselected, visible, x, x0, xaxis, xcalendar, xhoverformat, xperiod, xperiod0, xperiodalignment, xsrc, y, y0, yaxis, ycalendar, yhoverformat, yperiod, yperiod0, yperiodalignment, ysrc, **kwargs) 3476 _v = x if x is not None else _v 3477 if _v is not None: -> 3478 self["x"] = _v 3479 _v = arg.pop("x0", None) 3480 _v = x0 if x0 is not None else _v /usr/local/lib/python3.10/dist-packages/plotly/basedatatypes.py in __setitem__(self, prop, value) 4871 # ### Handle simple property ### 4872 else: -> 4873 self._set_prop(prop, value) 4874 else: 4875 # Make sure properties dict is initialized /usr/local/lib/python3.10/dist-packages/plotly/basedatatypes.py in _set_prop(self, prop, val) 5215 return 5216 else: -> 5217 raise err 5218 5219 # val is None /usr/local/lib/python3.10/dist-packages/plotly/basedatatypes.py in _set_prop(self, prop, val) 5210 5211 try: -> 5212 val = validator.validate_coerce(val) 5213 except ValueError as err: 5214 if self._skip_invalid: /usr/local/lib/python3.10/dist-packages/_plotly_utils/basevalidators.py in validate_coerce(self, v) 401 v = to_scalar_or_list(v) 402 else: --> 403 self.raise_invalid_val(v) 404 return v 405 /usr/local/lib/python3.10/dist-packages/_plotly_utils/basevalidators.py in raise_invalid_val(self, v, inds) 285 name += "[" + str(i) + "]" 286 --> 287 raise ValueError( 288 """ 289 Invalid value of type {typ} received for the '{name}' property of {pname} ValueError: Invalid value of type 'builtins.range' received for the 'x' property of scatter Received value: range(0, 3) The 'x' property is an array that may be specified as a tuple, list, numpy array, or pandas Series ``` (tested via [Google Colab](https://colab.research.google.com/notebooks/empty.ipynb)) After this change, it is possible to use `range()` in this context. A potential concern is Python 2 support — there, `range()` is a plain list. I have not tested this with Python 2. --- packages/python/plotly/_plotly_utils/basevalidators.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/python/plotly/_plotly_utils/basevalidators.py b/packages/python/plotly/_plotly_utils/basevalidators.py index 71c01b41168..42bc5073bb6 100644 --- a/packages/python/plotly/_plotly_utils/basevalidators.py +++ b/packages/python/plotly/_plotly_utils/basevalidators.py @@ -36,7 +36,7 @@ def to_scalar_or_list(v): pd = get_module("pandas", should_load=False) if np and np.isscalar(v) and hasattr(v, "item"): return v.item() - if isinstance(v, (list, tuple)): + if is_simple_array(v): return [to_scalar_or_list(e) for e in v] elif np and isinstance(v, np.ndarray): if v.ndim == 0: @@ -211,7 +211,7 @@ def is_simple_array(v): """ Return whether a value is considered to be an simple array """ - return isinstance(v, (list, tuple)) + return isinstance(v, (list, tuple, range)) def is_array(v):