11import os .path as opath
22from io import StringIO
3+ import json
34
45import _plotly_utils .basevalidators
56from codegen .utils import CAVEAT , PlotlyNode , TraceNode , write_source_py
67
78
8- def build_validator_py (node : PlotlyNode ):
9+ def get_validator_params (node : PlotlyNode , store : dict ):
910 """
10- Build validator class source code string for a datatype PlotlyNode
11+ Get params for the validator instance for the supplied node
12+ and add them to the store.
1113
1214 Parameters
1315 ----------
1416 node : PlotlyNode
1517 The datatype node (node.is_datatype must evaluate to true) for which
16- to build the validator class
18+ to build a validator class
19+ store : dict
20+ Dictionary to store the JSON data for the validator
1721 Returns
1822 -------
19- str
20- String containing source code for the validator class definition
23+ None
2124 """
22-
23- # Validate inputs
24- # ---------------
25+ assert isinstance (store , dict )
2526 assert node .is_datatype
2627
27- # Initialize
28- import_alias = "_bv"
29- buffer = StringIO ()
30- buffer .write (CAVEAT )
31-
32- # Imports
33- # -------
34- # ### Import package of the validator's superclass ###
35- import_str = "." .join (node .name_base_validator .split ("." )[:- 1 ])
36- buffer .write (f"import { import_str } as { import_alias } \n " )
37-
38- # Build Validator
39- # ---------------
40- # ### Get dict of validator's constructor params ###
41- params = node .get_validator_params ()
42-
43- # ### Write class definition ###
44- class_name = node .name_validator_class
28+ raw_params = node .get_validator_params ()
29+ params = dict ([(k , eval (v )) for k , v in raw_params .items ()])
4530 superclass_name = node .name_base_validator .split ("." )[- 1 ]
46- buffer .write (
47- f"""
4831
49- class { class_name } ({ import_alias } .{ superclass_name } ):
50- def __init__(self, plotly_name={ params ['plotly_name' ]} ,
51- parent_name={ params ['parent_name' ]} ,
52- **kwargs):"""
53- )
32+ key = "." .join (node .parent_path_parts + (node .name_property ,))
33+ store [key ] = {"params" : params , "superclass" : superclass_name }
5434
55- # ### Write constructor ###
56- buffer .write (
57- f"""
58- super().__init__(plotly_name, parent_name"""
59- )
60-
61- # Write out remaining constructor parameters
62- for attr_name , attr_val in params .items ():
63- if attr_name in ["plotly_name" , "parent_name" ]:
64- # plotly_name and parent_name are already handled
65- continue
66-
67- buffer .write (
68- f""",
69- { attr_name } =kwargs.pop('{ attr_name } ', { attr_val } )"""
70- )
7135
72- buffer .write (
73- f""",
74- **kwargs"""
75- )
36+ def get_data_validator_params (base_trace_node : TraceNode , store : dict ):
37+ """
38+ Add a dict of constructor params for the DataValidator to the store.
7639
77- buffer .write (")" )
40+ Parameters
41+ ----------
42+ base_trace_node : TraceNode
43+ PlotlyNode that is the parent of all of the individual trace nodes
44+ store : dict
45+ Dictionary to store the JSON data for the validator
46+ Returns
47+ -------
48+ None"""
49+ assert isinstance (store , dict )
7850
79- # ### Return buffer's string ###
80- return buffer .getvalue ()
51+ params = build_data_validator_params (base_trace_node )
52+ store ["data" ] = {
53+ "params" : params ,
54+ "superclass" : "BaseDataValidator" ,
55+ }
8156
8257
83- def write_validator_py (outdir , node : PlotlyNode ):
58+ def write_validator_json (outdir , params : dict ):
8459 """
85- Build validator source code and write to a file
60+ Write out a JSON serialization of the validator arguments
61+ for all validators (keyed by f"{parent_name}.{plotly_name})
62+
63+ Each validator has a "params": {kwargs} entry and
64+ a "superclass": str to indicate the class to be instantiated
8665
8766 Parameters
8867 ----------
8968 outdir : str
9069 Root outdir in which the validators package should reside
91- node : PlotlyNode
92- The datatype node (node.is_datatype must evaluate to true) for which
93- to build a validator class
70+ params : dict
71+ Dictionary to store the JSON data for the validator
9472 Returns
9573 -------
9674 None
9775 """
98- if node .is_mapped :
99- # No validator written for mapped nodes
100- # e.g. no validator for layout.title_font since ths is mapped to
101- # layout.title.font
102- return
76+ import json
10377
104- # Generate source code
105- # --------------------
106- validator_source = build_validator_py (node )
78+ # Validate inputs
79+ # ---------------
80+ if not isinstance (params , dict ):
81+ raise ValueError ("Expected params to be a dictionary" )
10782
10883 # Write file
10984 # ----------
110- # filepath = opath.join(outdir, "validators", *node.parent_path_parts, "__init__.py")
111- filepath = opath .join (
112- outdir , "validators" , * node .parent_path_parts , "_" + node .name_property + ".py"
113- )
114-
115- write_source_py (validator_source , filepath , leading_newlines = 2 )
85+ filepath = opath .join (outdir , "validators" , "_validators.json" )
86+ with open (filepath , "w" ) as f :
87+ f .write (json .dumps (params , indent = 4 ))
11688
11789
11890def build_data_validator_params (base_trace_node : TraceNode ):
@@ -131,78 +103,16 @@ def build_data_validator_params(base_trace_node: TraceNode):
131103 # Get list of trace nodes
132104 # -----------------------
133105 tracetype_nodes = base_trace_node .child_compound_datatypes
134-
135- # Build class_map_repr string
136- # ---------------------------
137- # This is the repr-form of a dict from trace propert name string
138- # to the name of the trace datatype class in the graph_objs package.
139- buffer = StringIO ()
140- buffer .write ("{\n " )
141- for i , tracetype_node in enumerate (tracetype_nodes ):
142- sfx = "," if i < len (tracetype_nodes ) else ""
143- trace_name = tracetype_node .name_property
144- trace_datatype_class = tracetype_node .name_datatype_class
145- buffer .write (
146- f"""
147- '{ trace_name } ': '{ trace_datatype_class } '{ sfx } """
148- )
149-
150- buffer .write (
151- """
152- }"""
106+ class_strs_map = dict (
107+ [(node .name_property , node .name_datatype_class ) for node in tracetype_nodes ]
153108 )
154109
155- class_map_repr = buffer .getvalue ()
156-
157- # Build params dict
158- # -----------------
159- params = {
160- "class_strs_map" : class_map_repr ,
161- "plotly_name" : repr ("data" ),
162- "parent_name" : repr ("" ),
110+ return {
111+ "class_strs_map" : class_strs_map ,
112+ "plotly_name" : "data" ,
113+ "parent_name" : "" ,
163114 }
164115
165- return params
166-
167-
168- def build_data_validator_py (base_trace_node : TraceNode ):
169- """
170- Build source code for the DataValidator
171- (this is the validator that inputs a list of traces)
172-
173- Parameters
174- ----------
175- base_trace_node : PlotlyNode
176- PlotlyNode that is the parent of all of the individual trace nodes
177- Returns
178- -------
179- str
180- Source code string for DataValidator class
181- """
182-
183- # Get constructor params
184- # ----------------------
185- params = build_data_validator_params (base_trace_node )
186-
187- # Build source code
188- # -----------------
189- buffer = StringIO ()
190-
191- buffer .write (
192- f"""
193- import _plotly_utils.basevalidators
194-
195- class DataValidator(_plotly_utils.basevalidators.BaseDataValidator):
196-
197- def __init__(self, plotly_name={ params ['plotly_name' ]} ,
198- parent_name={ params ['parent_name' ]} ,
199- **kwargs):
200-
201- super().__init__({ params ['class_strs_map' ]} , plotly_name, parent_name, **kwargs)"""
202- )
203-
204- return buffer .getvalue ()
205-
206116
207117def get_data_validator_instance (base_trace_node : TraceNode ):
208118 """
@@ -223,42 +133,7 @@ def get_data_validator_instance(base_trace_node: TraceNode):
223133 # We need to eval the values to convert out of the repr-form of the
224134 # params. e.g. '3' -> 3
225135 params = build_data_validator_params (base_trace_node )
226- eval_params = {k : eval (repr_val ) for k , repr_val in params .items ()}
227136
228137 # Build and return BaseDataValidator instance
229138 # -------------------------------------------
230- return _plotly_utils .basevalidators .BaseDataValidator (** eval_params )
231-
232-
233- def write_data_validator_py (outdir , base_trace_node : TraceNode ):
234- """
235- Construct and write out the DataValidator
236- (this is the validator that inputs a list of traces)
237-
238- Parameters
239- ----------
240- outdir : str
241- Root outdir in which the top-level validators package should reside
242- base_trace_node : PlotlyNode
243- PlotlyNode that is the parent of all of the individual trace nodes
244- Returns
245- -------
246- None
247- """
248- # Validate inputs
249- # ---------------
250- if base_trace_node .node_path :
251- raise ValueError (
252- "Expected root trace node.\n "
253- 'Received node with path "%s"' % base_trace_node .path_str
254- )
255-
256- # Build Source
257- # ------------
258- source = build_data_validator_py (base_trace_node )
259-
260- # Write file
261- # ----------
262- # filepath = opath.join(outdir, "validators", "__init__.py")
263- filepath = opath .join (outdir , "validators" , "_data.py" )
264- write_source_py (source , filepath , leading_newlines = 2 )
139+ return _plotly_utils .basevalidators .BaseDataValidator (** params )
0 commit comments