Skip to content

Commit c9958e1

Browse files
authored
Update to plotlyjs 1.43.1 (#1376)
* Update to plotlyjs 1.43.1 * Restore support for setting title properties as strings * Reintroduce support for legacy/deprecated title* properties (e.g. titlefont) * Handle obj.update(title=title_str)
1 parent 2482efd commit c9958e1

File tree

1,035 files changed

+53732
-26700
lines changed

Some content is hidden

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

1,035 files changed

+53732
-26700
lines changed

Diff for: _plotly_utils/basevalidators.py

+17
Original file line numberDiff line numberDiff line change
@@ -2107,6 +2107,23 @@ def validate_coerce(self, v, skip_invalid=False):
21072107
return v
21082108

21092109

2110+
class TitleValidator(CompoundValidator):
2111+
"""
2112+
This is a special validator to allow compound title properties
2113+
(e.g. layout.title, layout.xaxis.title, etc.) to be set as strings
2114+
or numbers. These strings are mapped to the 'text' property of the
2115+
compound validator.
2116+
"""
2117+
def __init__(self, *args, **kwargs):
2118+
super(TitleValidator, self).__init__(*args, **kwargs)
2119+
2120+
def validate_coerce(self, v, skip_invalid=False):
2121+
if isinstance(v, string_types + (int, float)):
2122+
v = {'text': v}
2123+
return super(TitleValidator, self).validate_coerce(
2124+
v, skip_invalid=skip_invalid)
2125+
2126+
21102127
class CompoundArrayValidator(BaseValidator):
21112128

21122129
def __init__(self, plotly_name, parent_name, data_class_str, data_docs,

Diff for: codegen/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ def perform_codegen():
187187
# ### Write __init__.py files for each validator package ###
188188
path_to_validator_import_info = {}
189189
for node in all_datatype_nodes:
190+
if node.is_mapped:
191+
continue
190192
key = node.parent_path_parts
191193
path_to_validator_import_info.setdefault(key, []).append(
192194
(f"._{node.name_property}", node.name_validator_class)

Diff for: codegen/datatypes.py

+18-5
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ class {datatype_class}({node.name_base_datatype}):\n""")
115115
elif subtype_node.is_compound:
116116
prop_type = (f"plotly.graph_objs{node.dotpath_str}." +
117117
f"{subtype_node.name_datatype_class}")
118+
elif subtype_node.is_mapped:
119+
prop_type = ''
118120
else:
119121
prop_type = get_typing_type(
120122
subtype_node.datatype, subtype_node.is_array_ok)
@@ -196,6 +198,13 @@ def _prop_descriptions(self):
196198
buffer.write(f"""
197199
\"\"\"""")
198200

201+
mapped_nodes = [n for n in subtype_nodes if n.is_mapped]
202+
mapped_properties = {n.plotly_name: n.relative_path for n in mapped_nodes}
203+
if mapped_properties:
204+
buffer.write(f"""
205+
206+
_mapped_properties = {repr(mapped_properties)}""")
207+
199208
# ### Constructor ###
200209
buffer.write(f"""
201210
def __init__(self""")
@@ -245,9 +254,10 @@ def __init__(self""")
245254
# Initialize validators
246255
# ---------------------""")
247256
for subtype_node in subtype_nodes:
248-
sub_name = subtype_node.name_property
249-
sub_validator = subtype_node.name_validator_class
250-
buffer.write(f"""
257+
if not subtype_node.is_mapped:
258+
sub_name = subtype_node.name_property
259+
sub_validator = subtype_node.name_validator_class
260+
buffer.write(f"""
251261
self._validators['{sub_name}'] = v_{undercase}.{sub_validator}()""")
252262

253263
buffer.write(f"""
@@ -256,10 +266,13 @@ def __init__(self""")
256266
# ----------------------------------""")
257267
for subtype_node in subtype_nodes:
258268
name_prop = subtype_node.name_property
259-
if name_prop == 'template':
269+
if name_prop == 'template' or subtype_node.is_mapped:
260270
# Special handling for layout.template to avoid infinite
261271
# recursion. Only initialize layout.template object if non-None
262-
# value specified
272+
# value specified.
273+
#
274+
# Same special handling for mapped nodes (e.g. layout.titlefont)
275+
# to keep them for overriding mapped property with None
263276
buffer.write(f"""
264277
_v = arg.pop('{name_prop}', None)
265278
_v = {name_prop} if {name_prop} is not None else _v

Diff for: codegen/utils.py

+110-2
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,8 @@ def name_base_validator(self) -> str:
431431
elif self.plotly_name.endswith('src') and self.datatype == 'string':
432432
validator_base = (f"_plotly_utils.basevalidators."
433433
f"SrcValidator")
434+
elif self.plotly_name == 'title' and self.datatype == 'compound':
435+
validator_base = "_plotly_utils.basevalidators.TitleValidator"
434436
else:
435437
datatype_title_case = self.datatype.title().replace('_', '')
436438
validator_base = (f"_plotly_utils.basevalidators."
@@ -565,7 +567,7 @@ def is_compound(self) -> bool:
565567
bool
566568
"""
567569
return (isinstance(self.node_data, dict_like) and
568-
not self.is_simple and
570+
not self.is_simple and not self.is_mapped and
569571
self.plotly_name not in ('items', 'impliedEdits', 'transforms'))
570572

571573
@property
@@ -629,7 +631,22 @@ def is_datatype(self) -> bool:
629631
-------
630632
bool
631633
"""
632-
return self.is_simple or self.is_compound or self.is_array
634+
return (self.is_simple
635+
or self.is_compound
636+
or self.is_array
637+
or self.is_mapped)
638+
639+
@property
640+
def is_mapped(self) -> bool:
641+
"""
642+
Node represents a mapping from a deprecated property to a
643+
normal property
644+
645+
Returns
646+
-------
647+
bool
648+
"""
649+
return False
633650

634651
# Node path
635652
# ---------
@@ -798,6 +815,29 @@ def child_datatypes(self):
798815
n.parent_path_parts != ('layout', 'template', 'data')):
799816

800817
nodes.append(ElementDefaultsNode(n, self.plotly_schema))
818+
elif n.is_compound and n.plotly_name == 'title':
819+
nodes.append(n)
820+
821+
# Remap deprecated title properties
822+
deprecated_data = n.parent.node_data.get('_deprecated', {})
823+
deprecated_title_prop_names = [
824+
p for p in deprecated_data
825+
if p.startswith('title') and p != 'title']
826+
for prop_name in deprecated_title_prop_names:
827+
828+
mapped_prop_name = prop_name.replace('title', '')
829+
830+
mapped_prop_node = [
831+
title_prop for title_prop in n.child_datatypes
832+
if title_prop.plotly_name == mapped_prop_name][0]
833+
834+
prop_parent = n.parent
835+
836+
legacy_node = MappedPropNode(
837+
mapped_prop_node, prop_parent,
838+
prop_name, self.plotly_schema)
839+
840+
nodes.append(legacy_node)
801841

802842
elif n.is_datatype:
803843
nodes.append(n)
@@ -1177,3 +1217,71 @@ def plotly_name(self):
11771217
@property
11781218
def name_datatype_class(self):
11791219
return self.element_node.name_datatype_class
1220+
1221+
1222+
class MappedPropNode(PlotlyNode):
1223+
1224+
def __init__(self, mapped_prop_node, parent,
1225+
prop_name, plotly_schema):
1226+
"""
1227+
Create node that represents a legacy title property.
1228+
e.g. layout.titlefont. These properties are now subproperties under
1229+
the sibling `title` property. e.g. layout.title.font.
1230+
1231+
Parameters
1232+
----------
1233+
title_node: PlotlyNode
1234+
prop_name: str
1235+
The name of the propery (without the title prefix)
1236+
e.g. 'font' to represent the layout.titlefont property.
1237+
"""
1238+
node_path = parent.node_path + (prop_name,)
1239+
super().__init__(plotly_schema,
1240+
node_path=node_path,
1241+
parent=parent)
1242+
1243+
self.mapped_prop_node = mapped_prop_node
1244+
self.prop_name = prop_name
1245+
1246+
@property
1247+
def node_data(self):
1248+
return {}
1249+
1250+
@property
1251+
def description(self):
1252+
res = f"""\
1253+
Deprecated: Please use {self.mapped_prop_node.path_str} instead.
1254+
""" + self.mapped_prop_node.description
1255+
return res
1256+
1257+
@property
1258+
def name_base_datatype(self):
1259+
return self.mapped_prop_node.description
1260+
1261+
@property
1262+
def root_name(self):
1263+
return self.parent.root_name
1264+
1265+
@property
1266+
def plotly_name(self):
1267+
return self.prop_name
1268+
1269+
@property
1270+
def name_datatype_class(self):
1271+
return self.mapped_prop_node.name_datatype_class
1272+
1273+
@property
1274+
def is_mapped(self):
1275+
return True
1276+
1277+
@property
1278+
def datatype(self):
1279+
return self.mapped_prop_node.datatype
1280+
1281+
def get_validator_instance(self):
1282+
return self.mapped_prop_node.get_validator_instance()
1283+
1284+
@property
1285+
def relative_path(self):
1286+
return (self.mapped_prop_node.parent.plotly_name,
1287+
self.mapped_prop_node.plotly_name)

Diff for: codegen/validators.py

+6
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ def write_validator_py(outdir,
9191
-------
9292
None
9393
"""
94+
if node.is_mapped:
95+
# No validator written for mapped nodes
96+
# e.g. no validator for layout.titlefont since ths is mapped to
97+
# layout.title.font
98+
return
99+
94100
# Generate source code
95101
# --------------------
96102
validator_source = build_validator_py(node)

0 commit comments

Comments
 (0)