1818class CompiledParam (BaseModel ):
1919 # this is minimalistic so the output json is more compact
2020 type : str
21- value : Optional [Any ] # solved value, if available
21+ value : Optional [Any ] = None # solved value, if available
22+ value_excluded : Optional [bool ] = None # true if value excluded, None otherwise to skip the field
23+ doc : Optional [str ] = None # doc specified by its parent block, if available
2224
2325
24- class CompiledPortArray (RootModel [Dict [str , Union ["CompiledPort" , "CompiledPortArray" ]]]):
25- pass
26+ class CompiledPortArray (BaseModel ):
27+ doc : Optional [str ] = None # doc specified by its parent block, if available
28+ elts : Dict [str , Union ["CompiledPort" , "CompiledPortArray" ]]
2629
2730
2831class CompiledPort (BaseModel ):
2932 path : PathType # provide the full path to allow searchability
3033 cls : str # self class
3134 # path of connected port, if connected
3235 # for block ports, this is the link, if connected to one
33- connected_path : Optional [Union [PathType , List [PathType ]]]
36+ connected_path : Optional [Union [PathType , List [PathType ]]] = None
37+ doc : Optional [str ] = None # doc specified by its parent block, if available
3438 # note, link ports do not have parameters (they inherit parameters from connected ports and are deduplicated here)
3539 params : Dict [str , CompiledParam ]
3640 ports : Dict [str , Union ["CompiledPort" , CompiledPortArray ]]
@@ -48,6 +52,7 @@ class CompiledBlock(BaseModel):
4852 path : PathType # provide the full path to allow searchability
4953 cls : str # self class
5054 superclasses : List [str ] # all superclasses
55+ doc : Optional [str ] = None # docstring, if available
5156 params : Dict [str , CompiledParam ]
5257 ports : Dict [str , Union [CompiledPortArray , CompiledPort ]]
5358 blocks : Dict [str , "CompiledBlock" ] # sub-blocks
@@ -108,14 +113,10 @@ def _param_value_to_json(cls, value: Any) -> Any:
108113
109114 def _param_to_compiled (self , path : Path , elt : edgir .ValInit ) -> CompiledParam :
110115 if path .params [- 1 ] in self ._EXCLUDED_PARAM_VALUES :
111- value : Optional [ Any ] = "<excluded>"
116+ return CompiledParam ( type = self . _param_to_type ( elt ), value_excluded = True )
112117 else :
113118 value = self ._param_value_to_json (self ._design .get_value (path .to_local_path ()))
114-
115- return CompiledParam (
116- type = self ._param_to_type (elt ),
117- value = value ,
118- )
119+ return CompiledParam (type = self ._param_to_type (elt ), value = value )
119120
120121 @override
121122 def transform_block (
@@ -126,16 +127,40 @@ def transform_block(
126127 blocks : Mapping [str , CompiledBlock ],
127128 links : Mapping [str , CompiledLink ],
128129 ) -> CompiledBlock :
130+ ports_dict = dict (ports )
131+ params_dict = {
132+ param_pair .name : self ._param_to_compiled (context .path .append_param (param_pair .name ), param_pair .value )
133+ for param_pair in elt .params
134+ }
135+
136+ meta_docs = elt .meta .members .node .get ("_docs" )
137+ if meta_docs is not None :
138+ block_doc = meta_docs .members .node .get ("" )
139+ if block_doc is not None :
140+ block_doc = block_doc .text_leaf
141+
142+ for param_name , param_value in params_dict .items ():
143+ if param_name in meta_docs .members .node :
144+ param_doc = meta_docs .members .node .get (param_name )
145+ if param_doc is not None :
146+ param_value .doc = param_doc .text_leaf
147+
148+ for port_name , port_value in ports_dict .items ():
149+ if port_name in meta_docs .members .node :
150+ port_doc = meta_docs .members .node .get (port_name )
151+ if port_doc is not None :
152+ port_value .doc = port_doc .text_leaf
153+ else :
154+ block_doc = None
155+
129156 return CompiledBlock (
130157 path = self ._path_to_path (context .path ),
131158 cls = self ._libpath_to_str (elt .self_class ),
132159 superclasses = [self ._libpath_to_str (cls ) for cls in elt .superclasses ]
133160 + [self ._libpath_to_str (cls ) for cls in elt .super_superclasses ],
134- params = {
135- param_pair .name : self ._param_to_compiled (context .path .append_param (param_pair .name ), param_pair .value )
136- for param_pair in elt .params
137- },
138- ports = dict (ports ),
161+ doc = block_doc ,
162+ params = params_dict ,
163+ ports = ports_dict ,
139164 blocks = dict (blocks ),
140165 links = dict (links ),
141166 )
@@ -179,7 +204,7 @@ def transform_port(
179204 ports = dict (ports ),
180205 )
181206 elif isinstance (elt , edgir .PortArray ):
182- return CompiledPortArray (dict (ports ))
207+ return CompiledPortArray (elts = dict (ports ))
183208 else :
184209 raise ValueError (f"unknown port type { type (elt )} " )
185210
@@ -219,8 +244,13 @@ def postprocess_serialized_json(json_str: str) -> str:
219244 json_str ,
220245 )
221246 json_str = re .sub (
222- r'\{\s*"type":\s*"(\S+)",\s*"value":\s*(.+)\s*\}' ,
223- lambda m : rf'{{ "type": "{ m .group (1 )} ", "value": { m .group (2 )} }}' ,
247+ r'\{\s*("type":\s*"\S+"),\s*("value":\s*.+)\s*\}' ,
248+ lambda m : rf"{{ { m .group (1 )} , { m .group (2 )} }}" ,
249+ json_str ,
250+ )
251+ json_str = re .sub (
252+ r'\{\s*("type":\s*"\S+"),\s*("value":\s*.+),\s*("doc":\s*.+)\s*\}' ,
253+ lambda m : rf"{{ { m .group (1 )} , { m .group (2 )} , { m .group (3 )} }}" ,
224254 json_str ,
225255 )
226256 return json_str
0 commit comments