Skip to content

Commit 3cb9303

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. Remove mention of Chart Studio and explicit enumeration of system font names from plotly.js / plot-schema.json so that this text isn't copied dozens of times into the plotly.py bundle. 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: 42283582 bytes Current size of plotly/**/*.py: 31931739 bytes Change: -25%
1 parent 5813a8a commit 3cb9303

File tree

14,853 files changed

+253000
-493024
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,853 files changed

+253000
-493024
lines changed

_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

bin/get_size.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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 2 <= len(sys.argv) <= 3, "Usage: get_size.py src_dir [build_dir]"
10+
11+
src_files, src_bytes = get_size(sys.argv[1])
12+
print(f"src,files,{src_files}")
13+
print(f"src,bytes,{src_bytes}")
14+
15+
if len(sys.argv) == 3:
16+
build_files, build_bytes = get_size(sys.argv[2])
17+
print(f"build,files,{build_files}")
18+
print(f"build,bytes,{build_bytes}")
19+
20+
21+
def get_size(root_dir):
22+
"""Count files and size in bytes."""
23+
num_files, num_bytes = 0, 0
24+
for f in Path(root_dir).glob("**/*.*"):
25+
if "__pycache__" not in str(f):
26+
num_files += 1
27+
num_bytes += f.stat().st_size
28+
return num_files, num_bytes
29+
30+
31+
if __name__ == "__main__":
32+
main()

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__":

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

codegen/datatypes.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class {datatype_class}(_{node.name_base_datatype}):\n"""
127127
128128
import re
129129
_subplotid_prop_re = re.compile(
130-
'^(' + '|'.join(_subplotid_prop_names) + r')(\d+)$')
130+
'^(' + '|'.join(_subplotid_prop_names) + r')(\\d+)$')
131131
"""
132132
)
133133

@@ -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 ###

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

0 commit comments

Comments
 (0)