Closed
Description
plotly.py raises a ValueError
when a blank color property is found in the legend font (and possibly other places), rather than a PlotlyGraphObjectError
. We depend on PlotlyGraphObjectError
being raised in the streambed backend so that we can retry with _raise=False
if the user tries to operate on an invalid figure.
Minimal code to reproduce the issue (Python 2.7.6, plotly.py 3.2.0):
import plotly.graph_objs as go
go.Figure(data=[], layout={'legend': {'font': {'color': u''}}})
Expected results: PlotlyGraphObjectError
is raised.
Actual results:
ValueError Traceback (most recent call last)
<ipython-input-4-ff88e2cee070> in <module>()
----> 1 go.Figure(data=[], layout={'legend': {'font': {'color': u''}}})
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/graph_objs/_figure.pyc in __init__(self, data, layout, frames)
334 respective traces in the data attribute
335 """
--> 336 super(Figure, self).__init__(data, layout, frames)
337
338 def add_area(
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in __init__(self, data, layout_plotly, frames)
155
156 # ### Import Layout ###
--> 157 self._layout_obj = self._layout_validator.validate_coerce(layout)
158
159 # ### Import clone of layout properties ###
/tmp/ppytmp/venv/lib/python2.7/site-packages/_plotly_utils/basevalidators.pyc in validate_coerce(self, v)
1875
1876 elif isinstance(v, dict):
-> 1877 v = self.data_class(**v)
1878
1879 elif isinstance(v, self.data_class):
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/graph_objs/_layout.pyc in __init__(self, arg, angularaxis, annotations, autosize, bargap, bargroupgap, barmode, barnorm, boxgap, boxgroupgap, boxmode, calendar, colorway, datarevision, direction, dragmode, extendpiecolors, font, geo, grid, height, hiddenlabels, hiddenlabelssrc, hidesources, hoverdistance, hoverlabel, hovermode, images, legend, mapbox, margin, orientation, paper_bgcolor, piecolorway, plot_bgcolor, polar, radialaxis, scene, selectdirection, separators, shapes, showlegend, sliders, spikedistance, template, ternary, title, titlefont, updatemenus, violingap, violingroupgap, violinmode, width, xaxis, yaxis, **kwargs)
3832 self.images = images if images is not None else _v
3833 _v = arg.pop('legend', None)
-> 3834 self.legend = legend if legend is not None else _v
3835 _v = arg.pop('mapbox', None)
3836 self.mapbox = mapbox if mapbox is not None else _v
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in __setattr__(self, prop, value)
3601 if match is None:
3602 # Set as ordinary property
-> 3603 super(BaseLayoutHierarchyType, self).__setattr__(prop, value)
3604 else:
3605 # Set as subplotid property
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in __setattr__(self, prop, value)
2702 prop in self._validators):
2703 # Let known properties and private properties through
-> 2704 super(BasePlotlyType, self).__setattr__(prop, value)
2705 else:
2706 # Raise error on unknown public properties
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/graph_objs/_layout.pyc in legend(self, val)
1250 @legend.setter
1251 def legend(self, val):
-> 1252 self['legend'] = val
1253
1254 # mapbox
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in __setitem__(self, prop, value)
3587 if match is None:
3588 # Set as ordinary property
-> 3589 super(BaseLayoutHierarchyType, self).__setitem__(prop, value)
3590 else:
3591 # Set as subplotid property
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in __setitem__(self, prop, value)
2665 # ### Handle compound property ###
2666 if isinstance(validator, CompoundValidator):
-> 2667 self._set_compound_prop(prop, value)
2668
2669 # ### Handle compound array property ###
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in _set_compound_prop(self, prop, val)
2963 validator = self._validators.get(prop)
2964 # type: BasePlotlyType
-> 2965 val = validator.validate_coerce(val)
2966
2967 # Save deep copies of current and new states
/tmp/ppytmp/venv/lib/python2.7/site-packages/_plotly_utils/basevalidators.pyc in validate_coerce(self, v)
1875
1876 elif isinstance(v, dict):
-> 1877 v = self.data_class(**v)
1878
1879 elif isinstance(v, self.data_class):
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/graph_objs/layout/_legend.pyc in __init__(self, arg, bgcolor, bordercolor, borderwidth, font, orientation, tracegroupgap, traceorder, x, xanchor, y, yanchor, **kwargs)
506 self.borderwidth = borderwidth if borderwidth is not None else _v
507 _v = arg.pop('font', None)
--> 508 self.font = font if font is not None else _v
509 _v = arg.pop('orientation', None)
510 self.orientation = orientation if orientation is not None else _v
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in __setattr__(self, prop, value)
2702 prop in self._validators):
2703 # Let known properties and private properties through
-> 2704 super(BasePlotlyType, self).__setattr__(prop, value)
2705 else:
2706 # Raise error on unknown public properties
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/graph_objs/layout/_legend.pyc in font(self, val)
186 @font.setter
187 def font(self, val):
--> 188 self['font'] = val
189
190 # orientation
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in __setitem__(self, prop, value)
2665 # ### Handle compound property ###
2666 if isinstance(validator, CompoundValidator):
-> 2667 self._set_compound_prop(prop, value)
2668
2669 # ### Handle compound array property ###
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in _set_compound_prop(self, prop, val)
2963 validator = self._validators.get(prop)
2964 # type: BasePlotlyType
-> 2965 val = validator.validate_coerce(val)
2966
2967 # Save deep copies of current and new states
/tmp/ppytmp/venv/lib/python2.7/site-packages/_plotly_utils/basevalidators.pyc in validate_coerce(self, v)
1875
1876 elif isinstance(v, dict):
-> 1877 v = self.data_class(**v)
1878
1879 elif isinstance(v, self.data_class):
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/graph_objs/layout/legend/_font.pyc in __init__(self, arg, color, family, size, **kwargs)
207 # ----------------------------------
208 _v = arg.pop('color', None)
--> 209 self.color = color if color is not None else _v
210 _v = arg.pop('family', None)
211 self.family = family if family is not None else _v
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in __setattr__(self, prop, value)
2702 prop in self._validators):
2703 # Let known properties and private properties through
-> 2704 super(BasePlotlyType, self).__setattr__(prop, value)
2705 else:
2706 # Raise error on unknown public properties
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/graph_objs/layout/legend/_font.pyc in color(self, val)
60 @color.setter
61 def color(self, val):
---> 62 self['color'] = val
63
64 # family
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in __setitem__(self, prop, value)
2674 # ### Handle simple property ###
2675 else:
-> 2676 self._set_prop(prop, value)
2677
2678 # Handle non-scalar case
/tmp/ppytmp/venv/lib/python2.7/site-packages/plotly/basedatatypes.pyc in _set_prop(self, prop, val)
2904 # ------------
2905 validator = self._validators.get(prop)
-> 2906 val = validator.validate_coerce(val)
2907
2908 # val is None
/tmp/ppytmp/venv/lib/python2.7/site-packages/_plotly_utils/basevalidators.pyc in validate_coerce(self, v, should_raise)
1077 validated_v = self.vc_scalar(v)
1078 if validated_v is None and should_raise:
-> 1079 self.raise_invalid_val(v)
1080
1081 v = validated_v
/tmp/ppytmp/venv/lib/python2.7/site-packages/_plotly_utils/basevalidators.pyc in raise_invalid_val(self, v)
223 typ=type_str(v),
224 v=repr(v),
--> 225 valid_clr_desc=self.description()))
226
227 def raise_invalid_elements(self, invalid_els):
ValueError:
Invalid value of type '__builtin__.unicode' received for the 'color' property of layout.legend.font
Received value: u''
The 'color' property is a color and may be specified as:
- A hex string (e.g. '#ff0000')
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
- A named CSS color:
aliceblue, antiquewhite, aqua, aquamarine, azure,
beige, bisque, black, blanchedalmond, blue,
blueviolet, brown, burlywood, cadetblue,
chartreuse, chocolate, coral, cornflowerblue,
cornsilk, crimson, cyan, darkblue, darkcyan,
darkgoldenrod, darkgray, darkgrey, darkgreen,
darkkhaki, darkmagenta, darkolivegreen, darkorange,
darkorchid, darkred, darksalmon, darkseagreen,
darkslateblue, darkslategray, darkslategrey,
darkturquoise, darkviolet, deeppink, deepskyblue,
dimgray, dimgrey, dodgerblue, firebrick,
floralwhite, forestgreen, fuchsia, gainsboro,
ghostwhite, gold, goldenrod, gray, grey, green,
greenyellow, honeydew, hotpink, indianred, indigo,
ivory, khaki, lavender, lavenderblush, lawngreen,
lemonchiffon, lightblue, lightcoral, lightcyan,
lightgoldenrodyellow, lightgray, lightgrey,
lightgreen, lightpink, lightsalmon, lightseagreen,
lightskyblue, lightslategray, lightslategrey,
lightsteelblue, lightyellow, lime, limegreen,
linen, magenta, maroon, mediumaquamarine,
mediumblue, mediumorchid, mediumpurple,
mediumseagreen, mediumslateblue, mediumspringgreen,
mediumturquoise, mediumvioletred, midnightblue,
mintcream, mistyrose, moccasin, navajowhite, navy,
oldlace, olive, olivedrab, orange, orangered,
orchid, palegoldenrod, palegreen, paleturquoise,
palevioletred, papayawhip, peachpuff, peru, pink,
plum, powderblue, purple, red, rosybrown,
royalblue, saddlebrown, salmon, sandybrown,
seagreen, seashell, sienna, silver, skyblue,
slateblue, slategray, slategrey, snow, springgreen,
steelblue, tan, teal, thistle, tomato, turquoise,
violet, wheat, white, whitesmoke, yellow,
yellowgreen
@jonmmease FYI