Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

feat: add type annotations to generated code #5008

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: main
Choose a base branch
Loading
from
  •  
  •  
  •  
Prev Previous commit
Next Next commit
feat: merging code generator work with latest changes on master
1.  Modify `commands.py` to run code generation.
1.  Remove comments from generated code.
1.  Replaced named arguments in constructors with positional arguments.
1.  Regenerate all code.

Notes:

The generated code is reformatted once again: this slightly increases
size but makes it more readable.

There is one flaky test:

`tests/test_plotly_utils/validators/test_colorscale_validator.py::test_acceptance_named[Inferno_r]`

It fails when the entire test suite is run but does *not* fail when
only `test_colorscale_validator.py` is run (using Python 3.11.9).

| branch   | format  | bytes    | %age |
| -------- | ------- | -------- | ---- |
| master   | .whl    | 14803768 |      |
| codegen2 | .whl    | 12215667 | -18% |
| master   | .tar.gz |  8100014 |      |
| codegen2 | .tar.gz |  6114458 | -24% |
  • Loading branch information
gvwilson committed Feb 11, 2025
commit 13df0c5ec835b148d05be9e2895a9fcd50b44667
The diff you're trying to view is too large. We only load the first 3000 changed files.
32 changes: 0 additions & 32 deletions 32 bin/get_size.py

This file was deleted.

80 changes: 20 additions & 60 deletions 80 codegen/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,10 @@ def build_datatype_py(node):
"""

# Validate inputs
# ---------------
assert node.is_compound

# Handle template traces
# ----------------------
#
# We want template trace/layout classes like
# plotly.graph_objs.layout.template.data.Scatter to map to the
# corresponding trace/layout class (e.g. plotly.graph_objs.Scatter).
Expand All @@ -85,17 +84,14 @@ def build_datatype_py(node):
return "from plotly.graph_objs import Layout"

# Extract node properties
# -----------------------
undercase = node.name_undercase
datatype_class = node.name_datatype_class
literal_nodes = [n for n in node.child_literals if n.plotly_name in ["type"]]

# Initialze source code buffer
# ----------------------------
buffer = StringIO()

# Imports
# -------
buffer.write(
f"from plotly.basedatatypes "
f"import {node.name_base_datatype} as _{node.name_base_datatype}\n"
Expand All @@ -106,14 +102,13 @@ def build_datatype_py(node):
buffer.write(f"from warnings import warn\n")

# Write class definition
# ----------------------
buffer.write(
f"""

class {datatype_class}(_{node.name_base_datatype}):\n"""
)

# ### Layout subplot properties ###
### Layout subplot properties
if datatype_class == "Layout":
subplot_nodes = [
node
Expand Down Expand Up @@ -168,17 +163,16 @@ def _subplot_re_match(self, prop):
valid_props_list = sorted(
[node.name_property for node in subtype_nodes + literal_nodes]
)
# class properties
buffer.write(
f"""
# class properties
# --------------------
_parent_path_str = '{node.parent_path_str}'
_path_str = '{node.path_str}'
_valid_props = {{"{'", "'.join(valid_props_list)}"}}
"""
)

# ### Property definitions ###
### Property definitions
for subtype_node in subtype_nodes:
if subtype_node.is_array_element:
prop_type = (
Expand All @@ -199,7 +193,7 @@ def _subplot_re_match(self, prop):
else:
prop_type = get_typing_type(subtype_node.datatype, subtype_node.is_array_ok)

# #### Get property description ####
#### Get property description ####
raw_description = subtype_node.description
property_description = "\n".join(
textwrap.wrap(
Expand All @@ -210,12 +204,12 @@ def _subplot_re_match(self, prop):
)
)

# # #### Get validator description ####
# #### Get validator description ####
validator = subtype_node.get_validator_instance()
if validator:
validator_description = reindent_validator_description(validator, 4)

# #### Combine to form property docstring ####
#### Combine to form property docstring ####
if property_description.strip():
property_docstring = f"""{property_description}

Expand All @@ -225,12 +219,10 @@ def _subplot_re_match(self, prop):
else:
property_docstring = property_description

# #### Write get property ####
#### Write get property ####
buffer.write(
f"""\

# {subtype_node.name_property}
# {'-' * len(subtype_node.name_property)}
@property
def {subtype_node.name_property}(self):
\"\"\"
Expand All @@ -243,7 +235,7 @@ def {subtype_node.name_property}(self):
return self['{subtype_node.name_property}']"""
)

# #### Write set property ####
#### Write set property ####
buffer.write(
f"""

Expand All @@ -252,24 +244,20 @@ def {subtype_node.name_property}(self, val):
self['{subtype_node.name_property}'] = val\n"""
)

# ### Literals ###
### Literals
for literal_node in literal_nodes:
buffer.write(
f"""\

# {literal_node.name_property}
# {'-' * len(literal_node.name_property)}
@property
def {literal_node.name_property}(self):
return self._props['{literal_node.name_property}']\n"""
)

# ### Private properties descriptions ###
### Private properties descriptions
valid_props = {node.name_property for node in subtype_nodes}
buffer.write(
f"""
# Self properties description
# ---------------------------
@property
def _prop_descriptions(self):
return \"\"\"\\"""
Expand All @@ -291,15 +279,15 @@ def _prop_descriptions(self):
_mapped_properties = {repr(mapped_properties)}"""
)

# ### Constructor ###
### Constructor
buffer.write(
f"""
def __init__(self"""
)

add_constructor_params(buffer, subtype_nodes, prepend_extras=["arg"])

# ### Constructor Docstring ###
### Constructor Docstring
header = f"Construct a new {datatype_class} object"
class_name = (
f"plotly.graph_objs" f"{node.parent_dotpath_str}." f"{node.name_datatype_class}"
Expand Down Expand Up @@ -331,18 +319,17 @@ def __init__(self"""
)

if datatype_class == "Layout":
buffer.write(
f"""
# Override _valid_props for instance so that instance can mutate set
# to support subplot properties (e.g. xaxis2)
buffer.write(
f"""
self._valid_props = {{"{'", "'.join(valid_props_list)}"}}
"""
)

# Validate arg
buffer.write(
f"""
# Validate arg
# ------------
if arg is None:
arg = {{}}
elif isinstance(arg, self.__class__):
Expand All @@ -355,35 +342,22 @@ def __init__(self"""
constructor must be a dict or
an instance of :class:`{class_name}`\"\"\")

# Handle skip_invalid
# -------------------
self._skip_invalid = kwargs.pop('skip_invalid', False)
self._validate = kwargs.pop('_validate', True)
"""
)

buffer.write(
f"""

# Populate data dict with properties
# ----------------------------------"""
)
buffer.write("\n\n")
for subtype_node in subtype_nodes:
name_prop = subtype_node.name_property
buffer.write(
f"""
self._init_provided('{name_prop}', arg, {name_prop})"""
)

# ### Literals ###
### Literals
if literal_nodes:
buffer.write(
f"""

# Read-only literals
# ------------------
"""
)
buffer.write("\n\n")
for literal_node in literal_nodes:
lit_name = literal_node.name_property
lit_val = repr(literal_node.node_data)
Expand All @@ -395,13 +369,7 @@ def __init__(self"""

buffer.write(
f"""

# Process unknown kwargs
# ----------------------
self._process_kwargs(**dict(arg, **kwargs))

# Reset skip_invalid
# ------------------
self._skip_invalid = False
"""
)
Expand All @@ -420,7 +388,6 @@ def __init__(self"""
)

# Return source string
# --------------------
return buffer.getvalue()


Expand Down Expand Up @@ -527,11 +494,9 @@ def add_docstring(

"""
# Validate inputs
# ---------------
assert node.is_compound

# Build wrapped description
# -------------------------
node_description = node.description
if node_description:
description_lines = textwrap.wrap(
Expand All @@ -544,7 +509,6 @@ def add_docstring(
node_description = "\n".join(description_lines) + "\n\n"

# Write header and description
# ----------------------------
buffer.write(
f"""
\"\"\"
Expand All @@ -555,7 +519,7 @@ def add_docstring(
)

# Write parameter descriptions
# ----------------------------

# Write any prepend extras
for p, v in prepend_extras:
v_wrapped = "\n".join(
Expand Down Expand Up @@ -594,7 +558,6 @@ def add_docstring(
)

# Write return block and close docstring
# --------------------------------------
buffer.write(
f"""

Expand Down Expand Up @@ -623,16 +586,13 @@ def write_datatype_py(outdir, node):
"""

# Build file path
# ---------------
# filepath = opath.join(outdir, "graph_objs", *node.parent_path_parts, "__init__.py")
filepath = opath.join(
outdir, "graph_objs", *node.parent_path_parts, "_" + node.name_undercase + ".py"
)

# Generate source code
# --------------------
datatype_source = build_datatype_py(node)

# Write file
# ----------
write_source_py(datatype_source, filepath, leading_newlines=2)
8 changes: 2 additions & 6 deletions 8 codegen/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ def __init__(self, plotly_name={params['plotly_name']},
# ### Write constructor ###
buffer.write(
f"""
super().__init__(plotly_name=plotly_name,
parent_name=parent_name"""
super().__init__(plotly_name, parent_name"""
)

# Write out remaining constructor parameters
Expand Down Expand Up @@ -198,10 +197,7 @@ def __init__(self, plotly_name={params['plotly_name']},
parent_name={params['parent_name']},
**kwargs):

super().__init__(class_strs_map={params['class_strs_map']},
plotly_name=plotly_name,
parent_name=parent_name,
**kwargs)"""
super().__init__({params['class_strs_map']}, plotly_name, parent_name, **kwargs)"""
)

return buffer.getvalue()
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.