Skip to content

Commit 1c75712

Browse files
authored
Fix update method on empty and uninitialized array property (plotly#1092)
* Fix for GH1072. Empty array properties are replaced during update * Don't error when a literal property is set to it's correct value. This avoids errors when performing updates like figure.update(data=[go.Scatter(...), ...]) * Fix two failing validator tests
1 parent 7ab0c90 commit 1c75712

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+253
-108
lines changed

_plotly_utils/basevalidators.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -1658,16 +1658,21 @@ class LiteralValidator(BaseValidator):
16581658
"""
16591659
Validator for readonly literal values
16601660
"""
1661-
def __init__(self, plotly_name, parent_name, **kwargs):
1662-
super(LiteralValidator, self).__init__(plotly_name=plotly_name,
1663-
parent_name=parent_name,
1664-
**kwargs)
1661+
def __init__(self, plotly_name, parent_name, val, **kwargs):
1662+
super(LiteralValidator, self).__init__(
1663+
plotly_name=plotly_name,
1664+
parent_name=parent_name,
1665+
**kwargs)
1666+
self.val = val
16651667

16661668
def validate_coerce(self, v):
1667-
raise ValueError("""\
1668-
The '{plotly_name}' property of {parent_name} is read-only""".format(
1669-
plotly_name=self.plotly_name, parent_name=self.parent_name
1670-
))
1669+
if v != self.val:
1670+
raise ValueError("""\
1671+
The '{plotly_name}' property of {parent_name} is read-only""".format(
1672+
plotly_name=self.plotly_name, parent_name=self.parent_name
1673+
))
1674+
else:
1675+
return v
16711676

16721677

16731678
class ImageUriValidator(BaseValidator):

_plotly_utils/tests/validators/test_basetraces_validator.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ def validator():
1010
'bar': 'Bar',
1111
'box': 'Box'},
1212
plotly_name='prop',
13-
parent_name='parent')
13+
parent_name='parent',
14+
set_uid=True)
1415

1516

1617
# Tests

_plotly_utils/tests/validators/test_infoarray_validator.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def validator_number3_free():
3030
# ----------
3131
# ### Acceptance ###
3232
@pytest.mark.parametrize('val', [
33-
[1, 'A'], ('hello', 'world!'), [1, ()], [-1, 1]
33+
[1, 'A'], ('hello', 'world!'), [1, set()], [-1, 1]
3434
])
3535
def test_validator_acceptance_any2(val, validator_any2: InfoArrayValidator):
3636
coerce_val = validator_any2.validate_coerce(val)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import pytest
2+
from _plotly_utils.basevalidators import LiteralValidator
3+
import numpy as np
4+
5+
6+
# Fixtures
7+
# --------
8+
@pytest.fixture()
9+
def validator():
10+
return LiteralValidator('prop', 'parent', 'scatter')
11+
12+
13+
# Tests
14+
# -----
15+
# ### Acceptance ###
16+
@pytest.mark.parametrize('val', ['scatter'])
17+
def test_acceptance(val, validator):
18+
assert validator.validate_coerce(val) is val
19+
20+
21+
# ### Test rejection ###
22+
@pytest.mark.parametrize('val',
23+
['hello', (), [], [1, 2, 3], set(), '34'])
24+
def test_rejection(val, validator):
25+
with pytest.raises(ValueError) as validation_failure:
26+
validator.validate_coerce(val)
27+
28+
assert 'read-only' in str(validation_failure.value)

codegen/datatypes.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,12 @@ def __init__(self""")
254254
for literal_node in literal_nodes:
255255
lit_name = literal_node.name_property
256256
lit_parent = literal_node.parent_path_str
257-
lit_val = literal_node.node_data
257+
lit_val = repr(literal_node.node_data)
258258
buffer.write(f"""
259-
self._props['{lit_name}'] = '{lit_val}'
259+
self._props['{lit_name}'] = {lit_val}
260260
self._validators['{lit_name}'] =\
261-
LiteralValidator(plotly_name='{lit_name}', parent_name='{lit_parent}')""")
261+
LiteralValidator(plotly_name='{lit_name}',\
262+
parent_name='{lit_parent}', val={lit_val})""")
262263

263264
buffer.write(f"""
264265

codegen/utils.py

+2
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ def get_validator_params(self):
423423
if colorscale_node_list:
424424
colorscale_path = colorscale_node_list[0].path_str
425425
params['colorscale_path'] = repr(colorscale_path)
426+
elif self.datatype == 'literal':
427+
params['val'] = self.node_data
426428

427429
return params
428430

plotly/basedatatypes.py

+19-8
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,16 @@ def update(self, dict1=None, **kwargs):
378378
for d in [dict1, kwargs]:
379379
if d:
380380
for k, v in d.items():
381-
BaseFigure._perform_update(self[k], v)
381+
if self[k] == ():
382+
# existing data or frames property is empty
383+
# In this case we accept the v as is.
384+
if k == 'data':
385+
self.add_traces(v)
386+
else:
387+
# Accept v
388+
self[k] = v
389+
else:
390+
BaseFigure._perform_update(self[k], v)
382391

383392
return self
384393

@@ -1059,11 +1068,6 @@ def add_traces(self, data, rows=None, cols=None):
10591068
... rows=[1, 2], cols=[1, 1])
10601069
"""
10611070

1062-
if self._in_batch_mode:
1063-
self._batch_layout_edits.clear()
1064-
self._batch_trace_edits.clear()
1065-
raise ValueError('Traces may not be added in a batch context')
1066-
10671071
# Validate traces
10681072
data = self._data_validator.validate_coerce(data)
10691073

@@ -2133,8 +2137,15 @@ def _perform_update(plotly_obj, update_obj):
21332137
BaseFigure._perform_update(
21342138
plotly_obj[key], val)
21352139
elif isinstance(validator, CompoundArrayValidator):
2136-
BaseFigure._perform_update(
2137-
plotly_obj[key], val)
2140+
if plotly_obj[key]:
2141+
# plotly_obj has an existing non-empty array for key
2142+
# In this case we merge val into the existing elements
2143+
BaseFigure._perform_update(
2144+
plotly_obj[key], val)
2145+
else:
2146+
# plotly_obj is an empty or uninitialized list for key
2147+
# In this case we accept val as is
2148+
plotly_obj[key] = val
21382149
else:
21392150
# Assign non-compound value
21402151
plotly_obj[key] = val

plotly/graph_objs/_area.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ def __init__(
785785
from _plotly_utils.basevalidators import LiteralValidator
786786
self._props['type'] = 'area'
787787
self._validators['type'] = LiteralValidator(
788-
plotly_name='type', parent_name='area'
788+
plotly_name='type', parent_name='area', val='area'
789789
)
790790

791791
# Process unknown kwargs

plotly/graph_objs/_bar.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2172,7 +2172,7 @@ def __init__(
21722172
from _plotly_utils.basevalidators import LiteralValidator
21732173
self._props['type'] = 'bar'
21742174
self._validators['type'] = LiteralValidator(
2175-
plotly_name='type', parent_name='bar'
2175+
plotly_name='type', parent_name='bar', val='bar'
21762176
)
21772177

21782178
# Process unknown kwargs

plotly/graph_objs/_box.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1574,7 +1574,7 @@ def __init__(
15741574
from _plotly_utils.basevalidators import LiteralValidator
15751575
self._props['type'] = 'box'
15761576
self._validators['type'] = LiteralValidator(
1577-
plotly_name='type', parent_name='box'
1577+
plotly_name='type', parent_name='box', val='box'
15781578
)
15791579

15801580
# Process unknown kwargs

plotly/graph_objs/_candlestick.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1234,7 +1234,7 @@ def __init__(
12341234
from _plotly_utils.basevalidators import LiteralValidator
12351235
self._props['type'] = 'candlestick'
12361236
self._validators['type'] = LiteralValidator(
1237-
plotly_name='type', parent_name='candlestick'
1237+
plotly_name='type', parent_name='candlestick', val='candlestick'
12381238
)
12391239

12401240
# Process unknown kwargs

plotly/graph_objs/_carpet.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1712,7 +1712,7 @@ def __init__(
17121712
from _plotly_utils.basevalidators import LiteralValidator
17131713
self._props['type'] = 'carpet'
17141714
self._validators['type'] = LiteralValidator(
1715-
plotly_name='type', parent_name='carpet'
1715+
plotly_name='type', parent_name='carpet', val='carpet'
17161716
)
17171717

17181718
# Process unknown kwargs

plotly/graph_objs/_choropleth.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,7 @@ def __init__(
14781478
from _plotly_utils.basevalidators import LiteralValidator
14791479
self._props['type'] = 'choropleth'
14801480
self._validators['type'] = LiteralValidator(
1481-
plotly_name='type', parent_name='choropleth'
1481+
plotly_name='type', parent_name='choropleth', val='choropleth'
14821482
)
14831483

14841484
# Process unknown kwargs

plotly/graph_objs/_cone.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1798,7 +1798,7 @@ def __init__(
17981798
from _plotly_utils.basevalidators import LiteralValidator
17991799
self._props['type'] = 'cone'
18001800
self._validators['type'] = LiteralValidator(
1801-
plotly_name='type', parent_name='cone'
1801+
plotly_name='type', parent_name='cone', val='cone'
18021802
)
18031803

18041804
# Process unknown kwargs

plotly/graph_objs/_contour.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2080,7 +2080,7 @@ def __init__(
20802080
from _plotly_utils.basevalidators import LiteralValidator
20812081
self._props['type'] = 'contour'
20822082
self._validators['type'] = LiteralValidator(
2083-
plotly_name='type', parent_name='contour'
2083+
plotly_name='type', parent_name='contour', val='contour'
20842084
)
20852085

20862086
# Process unknown kwargs

plotly/graph_objs/_contourcarpet.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1979,7 +1979,9 @@ def __init__(
19791979
from _plotly_utils.basevalidators import LiteralValidator
19801980
self._props['type'] = 'contourcarpet'
19811981
self._validators['type'] = LiteralValidator(
1982-
plotly_name='type', parent_name='contourcarpet'
1982+
plotly_name='type',
1983+
parent_name='contourcarpet',
1984+
val='contourcarpet'
19831985
)
19841986

19851987
# Process unknown kwargs

plotly/graph_objs/_heatmap.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1877,7 +1877,7 @@ def __init__(
18771877
from _plotly_utils.basevalidators import LiteralValidator
18781878
self._props['type'] = 'heatmap'
18791879
self._validators['type'] = LiteralValidator(
1880-
plotly_name='type', parent_name='heatmap'
1880+
plotly_name='type', parent_name='heatmap', val='heatmap'
18811881
)
18821882

18831883
# Process unknown kwargs

plotly/graph_objs/_heatmapgl.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1646,7 +1646,7 @@ def __init__(
16461646
from _plotly_utils.basevalidators import LiteralValidator
16471647
self._props['type'] = 'heatmapgl'
16481648
self._validators['type'] = LiteralValidator(
1649-
plotly_name='type', parent_name='heatmapgl'
1649+
plotly_name='type', parent_name='heatmapgl', val='heatmapgl'
16501650
)
16511651

16521652
# Process unknown kwargs

plotly/graph_objs/_histogram.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1754,7 +1754,7 @@ def __init__(
17541754
from _plotly_utils.basevalidators import LiteralValidator
17551755
self._props['type'] = 'histogram'
17561756
self._validators['type'] = LiteralValidator(
1757-
plotly_name='type', parent_name='histogram'
1757+
plotly_name='type', parent_name='histogram', val='histogram'
17581758
)
17591759

17601760
# Process unknown kwargs

plotly/graph_objs/_histogram2d.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1941,7 +1941,7 @@ def __init__(
19411941
from _plotly_utils.basevalidators import LiteralValidator
19421942
self._props['type'] = 'histogram2d'
19431943
self._validators['type'] = LiteralValidator(
1944-
plotly_name='type', parent_name='histogram2d'
1944+
plotly_name='type', parent_name='histogram2d', val='histogram2d'
19451945
)
19461946

19471947
# Process unknown kwargs

plotly/graph_objs/_histogram2dcontour.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -2090,7 +2090,9 @@ def __init__(
20902090
from _plotly_utils.basevalidators import LiteralValidator
20912091
self._props['type'] = 'histogram2dcontour'
20922092
self._validators['type'] = LiteralValidator(
2093-
plotly_name='type', parent_name='histogram2dcontour'
2093+
plotly_name='type',
2094+
parent_name='histogram2dcontour',
2095+
val='histogram2dcontour'
20942096
)
20952097

20962098
# Process unknown kwargs

plotly/graph_objs/_mesh3d.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2268,7 +2268,7 @@ def __init__(
22682268
from _plotly_utils.basevalidators import LiteralValidator
22692269
self._props['type'] = 'mesh3d'
22702270
self._validators['type'] = LiteralValidator(
2271-
plotly_name='type', parent_name='mesh3d'
2271+
plotly_name='type', parent_name='mesh3d', val='mesh3d'
22722272
)
22732273

22742274
# Process unknown kwargs

plotly/graph_objs/_ohlc.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,7 @@ def __init__(
12251225
from _plotly_utils.basevalidators import LiteralValidator
12261226
self._props['type'] = 'ohlc'
12271227
self._validators['type'] = LiteralValidator(
1228-
plotly_name='type', parent_name='ohlc'
1228+
plotly_name='type', parent_name='ohlc', val='ohlc'
12291229
)
12301230

12311231
# Process unknown kwargs

plotly/graph_objs/_parcoords.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,7 @@ def __init__(
10261026
from _plotly_utils.basevalidators import LiteralValidator
10271027
self._props['type'] = 'parcoords'
10281028
self._validators['type'] = LiteralValidator(
1029-
plotly_name='type', parent_name='parcoords'
1029+
plotly_name='type', parent_name='parcoords', val='parcoords'
10301030
)
10311031

10321032
# Process unknown kwargs

plotly/graph_objs/_pie.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,7 @@ def __init__(
15051505
from _plotly_utils.basevalidators import LiteralValidator
15061506
self._props['type'] = 'pie'
15071507
self._validators['type'] = LiteralValidator(
1508-
plotly_name='type', parent_name='pie'
1508+
plotly_name='type', parent_name='pie', val='pie'
15091509
)
15101510

15111511
# Process unknown kwargs

plotly/graph_objs/_pointcloud.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,7 @@ def __init__(
12071207
from _plotly_utils.basevalidators import LiteralValidator
12081208
self._props['type'] = 'pointcloud'
12091209
self._validators['type'] = LiteralValidator(
1210-
plotly_name='type', parent_name='pointcloud'
1210+
plotly_name='type', parent_name='pointcloud', val='pointcloud'
12111211
)
12121212

12131213
# Process unknown kwargs

plotly/graph_objs/_sankey.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ def __init__(
981981
from _plotly_utils.basevalidators import LiteralValidator
982982
self._props['type'] = 'sankey'
983983
self._validators['type'] = LiteralValidator(
984-
plotly_name='type', parent_name='sankey'
984+
plotly_name='type', parent_name='sankey', val='sankey'
985985
)
986986

987987
# Process unknown kwargs

plotly/graph_objs/_scatter.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2145,7 +2145,7 @@ def __init__(
21452145
from _plotly_utils.basevalidators import LiteralValidator
21462146
self._props['type'] = 'scatter'
21472147
self._validators['type'] = LiteralValidator(
2148-
plotly_name='type', parent_name='scatter'
2148+
plotly_name='type', parent_name='scatter', val='scatter'
21492149
)
21502150

21512151
# Process unknown kwargs

plotly/graph_objs/_scatter3d.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1925,7 +1925,7 @@ def __init__(
19251925
from _plotly_utils.basevalidators import LiteralValidator
19261926
self._props['type'] = 'scatter3d'
19271927
self._validators['type'] = LiteralValidator(
1928-
plotly_name='type', parent_name='scatter3d'
1928+
plotly_name='type', parent_name='scatter3d', val='scatter3d'
19291929
)
19301930

19311931
# Process unknown kwargs

plotly/graph_objs/_scattercarpet.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1580,7 +1580,9 @@ def __init__(
15801580
from _plotly_utils.basevalidators import LiteralValidator
15811581
self._props['type'] = 'scattercarpet'
15821582
self._validators['type'] = LiteralValidator(
1583-
plotly_name='type', parent_name='scattercarpet'
1583+
plotly_name='type',
1584+
parent_name='scattercarpet',
1585+
val='scattercarpet'
15841586
)
15851587

15861588
# Process unknown kwargs

plotly/graph_objs/_scattergeo.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ def __init__(
15891589
from _plotly_utils.basevalidators import LiteralValidator
15901590
self._props['type'] = 'scattergeo'
15911591
self._validators['type'] = LiteralValidator(
1592-
plotly_name='type', parent_name='scattergeo'
1592+
plotly_name='type', parent_name='scattergeo', val='scattergeo'
15931593
)
15941594

15951595
# Process unknown kwargs

plotly/graph_objs/_scattergl.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1942,7 +1942,7 @@ def __init__(
19421942
from _plotly_utils.basevalidators import LiteralValidator
19431943
self._props['type'] = 'scattergl'
19441944
self._validators['type'] = LiteralValidator(
1945-
plotly_name='type', parent_name='scattergl'
1945+
plotly_name='type', parent_name='scattergl', val='scattergl'
19461946
)
19471947

19481948
# Process unknown kwargs

plotly/graph_objs/_scattermapbox.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,9 @@ def __init__(
14301430
from _plotly_utils.basevalidators import LiteralValidator
14311431
self._props['type'] = 'scattermapbox'
14321432
self._validators['type'] = LiteralValidator(
1433-
plotly_name='type', parent_name='scattermapbox'
1433+
plotly_name='type',
1434+
parent_name='scattermapbox',
1435+
val='scattermapbox'
14341436
)
14351437

14361438
# Process unknown kwargs

0 commit comments

Comments
 (0)