Skip to content

Commit 000a5e9

Browse files
committed
feat: modify code generation to reduce bundle size
1. Add `bin/get_size.py` so that `python bin/get_size.py plotly build` reports the number of files and total size in bytes of the `plotly` directory (where generated code is put) and the `build` directory that is populated by `python setup.py build`. 1. Modify `codegen/__init__.py` and `./setup.py` so that `python setup.py --reformat=false` disables reformatting. 1. Assign an empty string to the `data_docs` field of generated validators. (This has a major impact because those docs are duplicated many times.) 1. Alias name of base validator during import in `codegen/validators.py`. 1. Remove the long list of CSS colors from help strings for color properties. 1. Replace `super(Parent, self)` with `super()` in generated code. 1. Drop use of sys.version_info and TYPE_CHECKING. Removed the check for Python < 3.7 using `sys.version_info` and as a backup checking `typing.TYPE_CHECKING`; this saves a little space and also cleans up the code. 1. Introduce `_init_provided()` for `BaseFigure` and `BasePlotlyType` that calls a helper function `_initialize_provided()` to replace repetitions of: ``` _v = arg.pop("something", None) _v = something if something is not None else _v if _v is not None: self["something"] = _v ``` Original size of plotly/**/*.py: 50365842 bytes Current size of plotly/**/*.py: 38256842 bytes Change: -26%
1 parent 3d36f14 commit 000a5e9

File tree

14,851 files changed

+248693
-482819
lines changed

Some content is hidden

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

14,851 files changed

+248693
-482819
lines changed

packages/python/plotly/_plotly_utils/basevalidators.py

+4-23
Original file line numberDiff line numberDiff line change
@@ -1328,25 +1328,14 @@ def numbers_allowed(self):
13281328
return self.colorscale_path is not None
13291329

13301330
def description(self):
1331-
1332-
named_clrs_str = "\n".join(
1333-
textwrap.wrap(
1334-
", ".join(self.named_colors),
1335-
width=79 - 16,
1336-
initial_indent=" " * 12,
1337-
subsequent_indent=" " * 12,
1338-
)
1339-
)
1340-
13411331
valid_color_description = """\
13421332
The '{plotly_name}' property is a color and may be specified as:
13431333
- A hex string (e.g. '#ff0000')
13441334
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
13451335
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
13461336
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
1347-
- A named CSS color:
1348-
{clrs}""".format(
1349-
plotly_name=self.plotly_name, clrs=named_clrs_str
1337+
- A named CSS color""".format(
1338+
plotly_name=self.plotly_name
13501339
)
13511340

13521341
if self.colorscale_path:
@@ -2483,15 +2472,11 @@ def description(self):
24832472
that may be specified as:
24842473
- An instance of :class:`{module_str}.{class_str}`
24852474
- A dict of string/value properties that will be passed
2486-
to the {class_str} constructor
2487-
2488-
Supported dict properties:
2489-
{constructor_params_str}"""
2475+
to the {class_str} constructor"""
24902476
).format(
24912477
plotly_name=self.plotly_name,
24922478
class_str=self.data_class_str,
24932479
module_str=self.module_str,
2494-
constructor_params_str=self.data_docs,
24952480
)
24962481

24972482
return desc
@@ -2560,15 +2545,11 @@ def description(self):
25602545
{class_str} that may be specified as:
25612546
- A list or tuple of instances of {module_str}.{class_str}
25622547
- A list or tuple of dicts of string/value properties that
2563-
will be passed to the {class_str} constructor
2564-
2565-
Supported dict properties:
2566-
{constructor_params_str}"""
2548+
will be passed to the {class_str} constructor"""
25672549
).format(
25682550
plotly_name=self.plotly_name,
25692551
class_str=self.data_class_str,
25702552
module_str=self.module_str,
2571-
constructor_params_str=self.data_docs,
25722553
)
25732554

25742555
return desc
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Calculate total size and total number of files of package."""
2+
3+
from pathlib import Path
4+
import sys
5+
6+
7+
def main():
8+
"""Main driver."""
9+
assert len(sys.argv) == 3, "Usage: get_size.py src_dir build_dir"
10+
src_files, src_bytes = get_size(sys.argv[1])
11+
build_files, build_bytes = get_size(sys.argv[2])
12+
print(f"src,files,{src_files}")
13+
print(f"src,bytes,{src_bytes}")
14+
print(f"build,files,{build_files}")
15+
print(f"build,bytes,{build_bytes}")
16+
17+
18+
def get_size(root_dir):
19+
"""Count files and size in bytes."""
20+
num_files, num_bytes = 0, 0
21+
for f in Path(root_dir).glob("**/*.*"):
22+
if "__pycache__" not in str(f):
23+
num_files += 1
24+
num_bytes += f.stat().st_size
25+
return num_files, num_bytes
26+
27+
28+
if __name__ == "__main__":
29+
main()

packages/python/plotly/codegen/__init__.py

+23-32
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def preprocess_schema(plotly_schema):
8585
items["colorscale"] = items.pop("concentrationscales")
8686

8787

88-
def perform_codegen():
88+
def perform_codegen(reformat=True):
8989
# Set root codegen output directory
9090
# ---------------------------------
9191
# (relative to project root)
@@ -267,36 +267,24 @@ def perform_codegen():
267267
root_datatype_imports.append(f"._deprecations.{dep_clas}")
268268

269269
optional_figure_widget_import = f"""
270-
if sys.version_info < (3, 7) or TYPE_CHECKING:
271-
try:
272-
import ipywidgets as _ipywidgets
273-
from packaging.version import Version as _Version
274-
if _Version(_ipywidgets.__version__) >= _Version("7.0.0"):
275-
from ..graph_objs._figurewidget import FigureWidget
276-
else:
277-
raise ImportError()
278-
except Exception:
279-
from ..missing_anywidget import FigureWidget
280-
else:
281-
__all__.append("FigureWidget")
282-
orig_getattr = __getattr__
283-
def __getattr__(import_name):
284-
if import_name == "FigureWidget":
285-
try:
286-
import ipywidgets
287-
from packaging.version import Version
288-
289-
if Version(ipywidgets.__version__) >= Version("7.0.0"):
290-
from ..graph_objs._figurewidget import FigureWidget
291-
292-
return FigureWidget
293-
else:
294-
raise ImportError()
295-
except Exception:
296-
from ..missing_anywidget import FigureWidget
270+
__all__.append("FigureWidget")
271+
orig_getattr = __getattr__
272+
def __getattr__(import_name):
273+
if import_name == "FigureWidget":
274+
try:
275+
import ipywidgets
276+
from packaging.version import Version
277+
278+
if Version(ipywidgets.__version__) >= Version("7.0.0"):
279+
from ..graph_objs._figurewidget import FigureWidget
297280
return FigureWidget
281+
else:
282+
raise ImportError()
283+
except Exception:
284+
from ..missing_anywidget import FigureWidget
285+
return FigureWidget
298286
299-
return orig_getattr(import_name)
287+
return orig_getattr(import_name)
300288
"""
301289
# ### __all__ ###
302290
for path_parts, class_names in alls.items():
@@ -337,9 +325,12 @@ def __getattr__(import_name):
337325
f.write(graph_objects_init_source)
338326

339327
# ### Run black code formatter on output directories ###
340-
subprocess.call(["black", "--target-version=py36", validators_pkgdir])
341-
subprocess.call(["black", "--target-version=py36", graph_objs_pkgdir])
342-
subprocess.call(["black", "--target-version=py36", graph_objects_path])
328+
if reformat:
329+
subprocess.call(["black", "--target-version=py36", validators_pkgdir])
330+
subprocess.call(["black", "--target-version=py36", graph_objs_pkgdir])
331+
subprocess.call(["black", "--target-version=py36", graph_objects_path])
332+
else:
333+
print("skipping reformatting")
343334

344335

345336
if __name__ == "__main__":

packages/python/plotly/codegen/compatibility.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def __init__(self, *args, **kwargs):
8989
{depr_msg}
9090
\"\"\"
9191
warnings.warn(\"\"\"{depr_msg}\"\"\", DeprecationWarning)
92-
super({class_name}, self).__init__(*args, **kwargs)\n\n\n"""
92+
super().__init__(*args, **kwargs)\n\n\n"""
9393
)
9494

9595
# Return source string

packages/python/plotly/codegen/datatypes.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,7 @@ def __init__(self"""
323323

324324
buffer.write(
325325
f"""
326-
super({datatype_class}, self).__init__('{node.name_property}')
327-
326+
super().__init__('{node.name_property}')
328327
if '_parent' in kwargs:
329328
self._parent = kwargs['_parent']
330329
return
@@ -373,10 +372,7 @@ def __init__(self"""
373372
name_prop = subtype_node.name_property
374373
buffer.write(
375374
f"""
376-
_v = arg.pop('{name_prop}', None)
377-
_v = {name_prop} if {name_prop} is not None else _v
378-
if _v is not None:
379-
self['{name_prop}'] = _v"""
375+
self._init_provided('{name_prop}', arg, {name_prop})"""
380376
)
381377

382378
# ### Literals ###

packages/python/plotly/codegen/figure.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,7 @@ def __init__(self, data=None, layout=None,
108108
if a property in the specification of data, layout, or frames
109109
is invalid AND skip_invalid is False
110110
\"\"\"
111-
super({fig_classname} ,self).__init__(data, layout,
112-
frames, skip_invalid,
113-
**kwargs)
111+
super().__init__(data, layout, frames, skip_invalid, **kwargs)
114112
"""
115113
)
116114

@@ -121,7 +119,7 @@ def {wrapped_name}(self, {full_params}) -> "{fig_classname}":
121119
'''
122120
{getattr(BaseFigure, wrapped_name).__doc__}
123121
'''
124-
return super({fig_classname}, self).{wrapped_name}({param_list})
122+
return super().{wrapped_name}({param_list})
125123
"""
126124
)
127125

packages/python/plotly/codegen/utils.py

+7-13
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,12 @@ def build_from_imports_py(rel_modules=(), rel_classes=(), init_extra=""):
7575

7676
result = f"""\
7777
import sys
78-
from typing import TYPE_CHECKING
79-
if sys.version_info < (3, 7) or TYPE_CHECKING:
80-
{imports_str}
81-
else:
82-
from _plotly_utils.importers import relative_import
83-
__all__, __getattr__, __dir__ = relative_import(
84-
__name__,
85-
{repr(rel_modules)},
86-
{repr(rel_classes)}
87-
)
78+
from _plotly_utils.importers import relative_import
79+
__all__, __getattr__, __dir__ = relative_import(
80+
__name__,
81+
{repr(rel_modules)},
82+
{repr(rel_classes)}
83+
)
8884
8985
{init_extra}
9086
"""
@@ -456,9 +452,7 @@ def get_validator_params(self):
456452

457453
if self.is_compound:
458454
params["data_class_str"] = repr(self.name_datatype_class)
459-
params["data_docs"] = (
460-
'"""' + self.get_constructor_params_docstring() + '\n"""'
461-
)
455+
params["data_docs"] = '"""\n"""'
462456
else:
463457
assert self.is_simple
464458

packages/python/plotly/codegen/validators.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ def build_validator_py(node: PlotlyNode):
2424
# ---------------
2525
assert node.is_datatype
2626

27-
# Initialize source code buffer
28-
# -----------------------------
27+
# Initialize
2928
buffer = StringIO()
29+
import_alias = "_bv"
3030

3131
# Imports
3232
# -------
3333
# ### Import package of the validator's superclass ###
3434
import_str = ".".join(node.name_base_validator.split(".")[:-1])
35-
buffer.write(f"import {import_str }\n")
35+
buffer.write(f"import {import_str} as {import_alias}\n")
3636

3737
# Build Validator
3838
# ---------------
@@ -41,11 +41,11 @@ def build_validator_py(node: PlotlyNode):
4141

4242
# ### Write class definition ###
4343
class_name = node.name_validator_class
44-
superclass_name = node.name_base_validator
44+
superclass_name = node.name_base_validator.split(".")[-1]
4545
buffer.write(
4646
f"""
4747
48-
class {class_name}({superclass_name}):
48+
class {class_name}({import_alias}.{superclass_name}):
4949
def __init__(self, plotly_name={params['plotly_name']},
5050
parent_name={params['parent_name']},
5151
**kwargs):"""
@@ -54,7 +54,7 @@ def __init__(self, plotly_name={params['plotly_name']},
5454
# ### Write constructor ###
5555
buffer.write(
5656
f"""
57-
super({class_name}, self).__init__(plotly_name=plotly_name,
57+
super().__init__(plotly_name=plotly_name,
5858
parent_name=parent_name"""
5959
)
6060

@@ -198,7 +198,7 @@ def __init__(self, plotly_name={params['plotly_name']},
198198
parent_name={params['parent_name']},
199199
**kwargs):
200200
201-
super(DataValidator, self).__init__(class_strs_map={params['class_strs_map']},
201+
super().__init__(class_strs_map={params['class_strs_map']},
202202
plotly_name=plotly_name,
203203
parent_name=parent_name,
204204
**kwargs)"""

packages/python/plotly/plotly/basedatatypes.py

+28
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,18 @@ def _generator(i):
385385
yield x
386386

387387

388+
def _initialize_provided(obj, name, arg, provided):
389+
"""
390+
Initialize a property of this object using the provided value
391+
or a value popped from the arguments dictionary. If neither
392+
is available, do not set the property.
393+
"""
394+
val = arg.pop(name, None)
395+
val = provided if provided is not None else val
396+
if val is not None:
397+
obj[name] = val
398+
399+
388400
class BaseFigure(object):
389401
"""
390402
Base class for all figure types (both widget and non-widget)
@@ -834,6 +846,14 @@ def _ipython_display_(self):
834846
else:
835847
print(repr(self))
836848

849+
def _init_provided(self, name, arg, provided):
850+
"""
851+
Initialize a property of this object using the provided value
852+
or a value popped from the arguments dictionary. If neither
853+
is available, do not set the property.
854+
"""
855+
_initialize_provided(self, name, arg, provided)
856+
837857
def update(self, dict1=None, overwrite=False, **kwargs):
838858
"""
839859
Update the properties of the figure with a dict and/or with
@@ -4329,6 +4349,14 @@ def _get_validator(self, prop):
43294349

43304350
return ValidatorCache.get_validator(self._path_str, prop)
43314351

4352+
def _init_provided(self, name, arg, provided):
4353+
"""
4354+
Initialize a property of this object using the provided value
4355+
or a value popped from the arguments dictionary. If neither
4356+
is available, do not set the property.
4357+
"""
4358+
_initialize_provided(self, name, arg, provided)
4359+
43324360
@property
43334361
def _validators(self):
43344362
"""

0 commit comments

Comments
 (0)