Skip to content

Commit e882f85

Browse files
Merge pull request #2403 from plotly/figure_level_validate
Replace global validate state with Figure level validate flag
2 parents e778c6b + f8ae78d commit e882f85

File tree

846 files changed

+883
-45
lines changed

Some content is hidden

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

846 files changed

+883
-45
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1010
makes it possible to skip hover information for some arguments or to change
1111
the formatting of hover informatiom [#2377](https://github.com/plotly/plotly.py/pull/2377).
1212

13+
### Performance
14+
This version includes several performance improvements ([#2368](https://github.com/plotly/plotly.py/pull/2368), [#2403](https://github.com/plotly/plotly.py/pull/2403)).
15+
16+
- Child graph objects (e.g. `figure.layout.xaxis`) are no longer created eagerly during graph object construction. Instead, they are created lazily the first time the property is accessed.
17+
- Property validation is now disabled for select internal operations.
18+
- When used with Python 3.7 and above, ploty.py now takes advantage of [PEP-562](https://www.python.org/dev/peps/pep-0562/) to perform submodule imports lazily. This dramatically improves import times.
19+
1320
## [4.6] - 2020-03-31
1421

1522
### Updated

packages/python/plotly/_plotly_utils/basevalidators.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -2438,12 +2438,12 @@ def description(self):
24382438

24392439
return desc
24402440

2441-
def validate_coerce(self, v, skip_invalid=False):
2441+
def validate_coerce(self, v, skip_invalid=False, _validate=True):
24422442
if v is None:
24432443
v = self.data_class()
24442444

24452445
elif isinstance(v, dict):
2446-
v = self.data_class(v, skip_invalid=skip_invalid)
2446+
v = self.data_class(v, skip_invalid=skip_invalid, _validate=_validate)
24472447

24482448
elif isinstance(v, self.data_class):
24492449
# Copy object
@@ -2614,7 +2614,7 @@ def get_trace_class(self, trace_name):
26142614

26152615
return self._class_map[trace_name]
26162616

2617-
def validate_coerce(self, v, skip_invalid=False):
2617+
def validate_coerce(self, v, skip_invalid=False, _validate=True):
26182618
from plotly.basedatatypes import BaseTraceType
26192619

26202620
# Import Histogram2dcontour, this is the deprecated name of the
@@ -2649,15 +2649,15 @@ def validate_coerce(self, v, skip_invalid=False):
26492649
if skip_invalid:
26502650
# Treat as scatter trace
26512651
trace = self.get_trace_class("scatter")(
2652-
skip_invalid=skip_invalid, **v_copy
2652+
skip_invalid=skip_invalid, _validate=_validate, **v_copy
26532653
)
26542654
res.append(trace)
26552655
else:
26562656
res.append(None)
26572657
invalid_els.append(v_el)
26582658
else:
26592659
trace = self.get_trace_class(trace_type)(
2660-
skip_invalid=skip_invalid, **v_copy
2660+
skip_invalid=skip_invalid, _validate=_validate, **v_copy
26612661
)
26622662
res.append(trace)
26632663
else:

packages/python/plotly/codegen/__init__.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,6 @@ def perform_codegen():
266266
for dep_clas in DEPRECATED_DATATYPES:
267267
root_datatype_imports.append(f"._deprecations.{dep_clas}")
268268

269-
validate_import = "from .._validate import validate\n"
270269
optional_figure_widget_import = f"""
271270
if sys.version_info < (3, 7):
272271
try:
@@ -307,7 +306,7 @@ def __getattr__(import_name):
307306
rel_classes = datatype_rel_class_imports[path_parts]
308307
rel_modules = datatype_rel_module_imports.get(path_parts, [])
309308
if path_parts == ():
310-
init_extra = validate_import + optional_figure_widget_import
309+
init_extra = optional_figure_widget_import
311310
else:
312311
init_extra = ""
313312
write_init_py(graph_objs_pkg, path_parts, rel_modules, rel_classes, init_extra)
@@ -325,7 +324,7 @@ def __getattr__(import_name):
325324
graph_objects_init_source = build_from_imports_py(
326325
graph_objects_rel_modules,
327326
graph_objects_rel_classes,
328-
init_extra=validate_import + optional_figure_widget_import,
327+
init_extra=optional_figure_widget_import,
329328
)
330329
graph_objects_path = opath.join(outdir, "graph_objects", "__init__.py")
331330
os.makedirs(opath.join(outdir, "graph_objects"), exist_ok=True)

packages/python/plotly/codegen/datatypes.py

+1
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ def __init__(self"""
349349
# Handle skip_invalid
350350
# -------------------
351351
self._skip_invalid = kwargs.pop('skip_invalid', False)
352+
self._validate = kwargs.pop('_validate', True)
352353
"""
353354
)
354355

packages/python/plotly/plotly/_validate.py

-12
This file was deleted.

packages/python/plotly/plotly/basedatatypes.py

+28-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from copy import deepcopy, copy
1111

1212
from _plotly_utils.utils import _natural_sort_strings
13-
from plotly._validate import validate
1413
from .optional_imports import get_module
1514

1615
# Create Undefined sentinel value
@@ -92,6 +91,9 @@ class is a subclass of both BaseFigure and widgets.DOMWidget.
9291

9392
super(BaseFigure, self).__init__()
9493

94+
# Initialize validation
95+
self._validate = kwargs.pop("_validate", True)
96+
9597
# Assign layout_plotly to layout
9698
# ------------------------------
9799
# See docstring note for explanation
@@ -140,7 +142,9 @@ class is a subclass of both BaseFigure and widgets.DOMWidget.
140142
self._data_validator = DataValidator(set_uid=self._set_trace_uid)
141143

142144
# ### Import traces ###
143-
data = self._data_validator.validate_coerce(data, skip_invalid=skip_invalid)
145+
data = self._data_validator.validate_coerce(
146+
data, skip_invalid=skip_invalid, _validate=self._validate
147+
)
144148

145149
# ### Save tuple of trace objects ###
146150
self._data_objs = data
@@ -182,7 +186,7 @@ class is a subclass of both BaseFigure and widgets.DOMWidget.
182186

183187
# ### Import Layout ###
184188
self._layout_obj = self._layout_validator.validate_coerce(
185-
layout, skip_invalid=skip_invalid
189+
layout, skip_invalid=skip_invalid, _validate=self._validate
186190
)
187191

188192
# ### Import clone of layout properties ###
@@ -314,6 +318,8 @@ def __setitem__(self, prop, value):
314318
for p in prop[:-1]:
315319
res = res[p]
316320

321+
res._validate = self._validate
322+
317323
res[prop[-1]] = value
318324

319325
def __setattr__(self, prop, value):
@@ -1940,10 +1946,13 @@ def _initialize_layout_template(self):
19401946

19411947
if self._layout_obj._props.get("template", None) is None:
19421948
if pio.templates.default is not None:
1943-
with validate(False):
1944-
# Assume default template is already validated
1949+
# Assume default template is already validated
1950+
self._layout_obj._validate = False
1951+
try:
19451952
template_dict = pio.templates[pio.templates.default]
19461953
self._layout_obj.template = template_dict
1954+
finally:
1955+
self._layout_obj._validate = self._validate
19471956

19481957
@property
19491958
def layout(self):
@@ -3339,6 +3348,8 @@ def __init__(self, plotly_name, **kwargs):
33393348
# invalid properties will result in an exception
33403349
self._skip_invalid = False
33413350

3351+
self._validate = True
3352+
33423353
# Validate inputs
33433354
# ---------------
33443355
self._process_kwargs(**kwargs)
@@ -3378,6 +3389,14 @@ def __init__(self, plotly_name, **kwargs):
33783389
# ### Backing property for backward compatible _validator property ##
33793390
self.__validators = None
33803391

3392+
# @property
3393+
# def _validate(self):
3394+
# fig = self.figure
3395+
# if fig is None:
3396+
# return True
3397+
# else:
3398+
# return fig._validate
3399+
33813400
def _get_validator(self, prop):
33823401
from .validator_cache import ValidatorCache
33833402

@@ -3425,7 +3444,7 @@ def _process_kwargs(self, **kwargs):
34253444
if k in self:
34263445
# e.g. underscore kwargs like marker_line_color
34273446
self[k] = v
3428-
elif not validate._should_validate:
3447+
elif not self._validate:
34293448
# Set extra property as-is
34303449
self[k] = v
34313450
else:
@@ -3885,7 +3904,7 @@ def __setitem__(self, prop, value):
38853904
# ### Unwrap scalar tuple ###
38863905
prop = prop[0]
38873906

3888-
if validate._should_validate:
3907+
if self._validate:
38893908
if prop not in self._valid_props:
38903909
self._raise_on_invalid_property_error(prop)
38913910

@@ -3937,6 +3956,8 @@ def __setitem__(self, prop, value):
39373956
for p in prop[:-1]:
39383957
res = res[p]
39393958

3959+
res._validate = self._validate
3960+
39403961
res[prop[-1]] = value
39413962

39423963
def __setattr__(self, prop, value):

packages/python/plotly/plotly/graph_objects/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@
258258
],
259259
)
260260

261-
from .._validate import validate
262261

263262
if sys.version_info < (3, 7):
264263
try:

packages/python/plotly/plotly/graph_objs/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@
258258
],
259259
)
260260

261-
from .._validate import validate
262261

263262
if sys.version_info < (3, 7):
264263
try:

packages/python/plotly/plotly/graph_objs/_area.py

+1
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,7 @@ def __init__(
895895
# Handle skip_invalid
896896
# -------------------
897897
self._skip_invalid = kwargs.pop("skip_invalid", False)
898+
self._validate = kwargs.pop("_validate", True)
898899

899900
# Populate data dict with properties
900901
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_bar.py

+1
Original file line numberDiff line numberDiff line change
@@ -2649,6 +2649,7 @@ def __init__(
26492649
# Handle skip_invalid
26502650
# -------------------
26512651
self._skip_invalid = kwargs.pop("skip_invalid", False)
2652+
self._validate = kwargs.pop("_validate", True)
26522653

26532654
# Populate data dict with properties
26542655
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_barpolar.py

+1
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,7 @@ def __init__(
16641664
# Handle skip_invalid
16651665
# -------------------
16661666
self._skip_invalid = kwargs.pop("skip_invalid", False)
1667+
self._validate = kwargs.pop("_validate", True)
16671668

16681669
# Populate data dict with properties
16691670
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_box.py

+1
Original file line numberDiff line numberDiff line change
@@ -2644,6 +2644,7 @@ def __init__(
26442644
# Handle skip_invalid
26452645
# -------------------
26462646
self._skip_invalid = kwargs.pop("skip_invalid", False)
2647+
self._validate = kwargs.pop("_validate", True)
26472648

26482649
# Populate data dict with properties
26492650
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_candlestick.py

+1
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,7 @@ def __init__(
14091409
# Handle skip_invalid
14101410
# -------------------
14111411
self._skip_invalid = kwargs.pop("skip_invalid", False)
1412+
self._validate = kwargs.pop("_validate", True)
14121413

14131414
# Populate data dict with properties
14141415
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_carpet.py

+1
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,7 @@ def __init__(
16121612
# Handle skip_invalid
16131613
# -------------------
16141614
self._skip_invalid = kwargs.pop("skip_invalid", False)
1615+
self._validate = kwargs.pop("_validate", True)
16151616

16161617
# Populate data dict with properties
16171618
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_choropleth.py

+1
Original file line numberDiff line numberDiff line change
@@ -1933,6 +1933,7 @@ def __init__(
19331933
# Handle skip_invalid
19341934
# -------------------
19351935
self._skip_invalid = kwargs.pop("skip_invalid", False)
1936+
self._validate = kwargs.pop("_validate", True)
19361937

19371938
# Populate data dict with properties
19381939
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_choroplethmapbox.py

+1
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,7 @@ def __init__(
19261926
# Handle skip_invalid
19271927
# -------------------
19281928
self._skip_invalid = kwargs.pop("skip_invalid", False)
1929+
self._validate = kwargs.pop("_validate", True)
19291930

19301931
# Populate data dict with properties
19311932
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_cone.py

+1
Original file line numberDiff line numberDiff line change
@@ -2160,6 +2160,7 @@ def __init__(
21602160
# Handle skip_invalid
21612161
# -------------------
21622162
self._skip_invalid = kwargs.pop("skip_invalid", False)
2163+
self._validate = kwargs.pop("_validate", True)
21632164

21642165
# Populate data dict with properties
21652166
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_contour.py

+1
Original file line numberDiff line numberDiff line change
@@ -2444,6 +2444,7 @@ def __init__(
24442444
# Handle skip_invalid
24452445
# -------------------
24462446
self._skip_invalid = kwargs.pop("skip_invalid", False)
2447+
self._validate = kwargs.pop("_validate", True)
24472448

24482449
# Populate data dict with properties
24492450
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_contourcarpet.py

+1
Original file line numberDiff line numberDiff line change
@@ -2056,6 +2056,7 @@ def __init__(
20562056
# Handle skip_invalid
20572057
# -------------------
20582058
self._skip_invalid = kwargs.pop("skip_invalid", False)
2059+
self._validate = kwargs.pop("_validate", True)
20592060

20602061
# Populate data dict with properties
20612062
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_densitymapbox.py

+1
Original file line numberDiff line numberDiff line change
@@ -1874,6 +1874,7 @@ def __init__(
18741874
# Handle skip_invalid
18751875
# -------------------
18761876
self._skip_invalid = kwargs.pop("skip_invalid", False)
1877+
self._validate = kwargs.pop("_validate", True)
18771878

18781879
# Populate data dict with properties
18791880
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_frame.py

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ def __init__(
229229
# Handle skip_invalid
230230
# -------------------
231231
self._skip_invalid = kwargs.pop("skip_invalid", False)
232+
self._validate = kwargs.pop("_validate", True)
232233

233234
# Populate data dict with properties
234235
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_funnel.py

+1
Original file line numberDiff line numberDiff line change
@@ -2192,6 +2192,7 @@ def __init__(
21922192
# Handle skip_invalid
21932193
# -------------------
21942194
self._skip_invalid = kwargs.pop("skip_invalid", False)
2195+
self._validate = kwargs.pop("_validate", True)
21952196

21962197
# Populate data dict with properties
21972198
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_funnelarea.py

+1
Original file line numberDiff line numberDiff line change
@@ -1689,6 +1689,7 @@ def __init__(
16891689
# Handle skip_invalid
16901690
# -------------------
16911691
self._skip_invalid = kwargs.pop("skip_invalid", False)
1692+
self._validate = kwargs.pop("_validate", True)
16921693

16931694
# Populate data dict with properties
16941695
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_heatmap.py

+1
Original file line numberDiff line numberDiff line change
@@ -2242,6 +2242,7 @@ def __init__(
22422242
# Handle skip_invalid
22432243
# -------------------
22442244
self._skip_invalid = kwargs.pop("skip_invalid", False)
2245+
self._validate = kwargs.pop("_validate", True)
22452246

22462247
# Populate data dict with properties
22472248
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_heatmapgl.py

+1
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,7 @@ def __init__(
17501750
# Handle skip_invalid
17511751
# -------------------
17521752
self._skip_invalid = kwargs.pop("skip_invalid", False)
1753+
self._validate = kwargs.pop("_validate", True)
17531754

17541755
# Populate data dict with properties
17551756
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_histogram.py

+1
Original file line numberDiff line numberDiff line change
@@ -2242,6 +2242,7 @@ def __init__(
22422242
# Handle skip_invalid
22432243
# -------------------
22442244
self._skip_invalid = kwargs.pop("skip_invalid", False)
2245+
self._validate = kwargs.pop("_validate", True)
22452246

22462247
# Populate data dict with properties
22472248
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_histogram2d.py

+1
Original file line numberDiff line numberDiff line change
@@ -2393,6 +2393,7 @@ def __init__(
23932393
# Handle skip_invalid
23942394
# -------------------
23952395
self._skip_invalid = kwargs.pop("skip_invalid", False)
2396+
self._validate = kwargs.pop("_validate", True)
23962397

23972398
# Populate data dict with properties
23982399
# ----------------------------------

packages/python/plotly/plotly/graph_objs/_histogram2dcontour.py

+1
Original file line numberDiff line numberDiff line change
@@ -2529,6 +2529,7 @@ def __init__(
25292529
# Handle skip_invalid
25302530
# -------------------
25312531
self._skip_invalid = kwargs.pop("skip_invalid", False)
2532+
self._validate = kwargs.pop("_validate", True)
25322533

25332534
# Populate data dict with properties
25342535
# ----------------------------------

0 commit comments

Comments
 (0)