55from jinja2 import Environment , FileSystemLoader , meta
66from jinja2 .nodes import Block , For , Name , Tuple
77
8- log = logging .getLogger ('volt.generator.py' )
9- log .setLevel (logging .DEBUG )
8+ from volt import config
109
11- environment = Environment ( loader = FileSystemLoader ( "templates/" ) )
10+ log = logging . getLogger ( "volt.generator.py" )
1211
1312
1413@dataclass
@@ -29,7 +28,9 @@ class Context:
2928all_components : list [GeneratedComponent ] = []
3029
3130
32- def get_block_children (block : Block , template_name : str , referenced_templates : Iterator [str | None ], top_level : bool ) -> Iterable [Block ]:
31+ def get_block_children (
32+ block : Block , template_name : str , referenced_templates : Iterator [str | None ], top_level : bool
33+ ) -> Iterable [Block ]:
3334 blocks : list [Block ] = []
3435
3536 child_blocks = block .iter_child_nodes ()
@@ -40,7 +41,7 @@ def get_block_children(block: Block, template_name: str, referenced_templates: I
4041 blocks .append (child_block )
4142 blocks .extend (get_block_children (child_block , template_name , referenced_templates , top_level = False ))
4243
43- # We want to make sure that we are excluding fields that are captured by parents. Since we are inheriting from
44+ # We want to make sure that we are excluding fields that are captured by parents. Since we are inheriting from
4445 # these components, we don't want to require them on on the child components as well
4546 parent_fields : list [str ] = []
4647 for parent_block in blocks :
@@ -52,13 +53,10 @@ def get_block_children(block: Block, template_name: str, referenced_templates: I
5253 # in which case we name it the file name
5354 formatted_template_name = template_name_as_title (template_name )
5455 name = formatted_template_name + name_as_title (block .name )
55- # if block.name == "content":
56- # name = template_name[: template_name.find(".")].title()
57-
5856
5957 parent_components = [formatted_template_name + name_as_title (block .name ) for block in blocks ]
6058 # If we have an 'extends' at the top level, we ensure this is added as a parent component to any component
61- # at that same 'top level', so as to ensure any fields in extended templates are also required as part of the
59+ # at that same 'top level', so as to ensure any fields in extended templates are also required as part of the
6260 # dataclass context
6361 if top_level :
6462 for referenced_template in referenced_templates :
@@ -82,6 +80,7 @@ def name_as_title(name: str) -> str:
8280 name = f"{ name .replace ('_' , ' ' ).title ().replace (' ' , '' )} "
8381 return name
8482
83+
8584def template_name_as_title (template_name : str ) -> str :
8685 return template_name [: template_name .find ("." )].title ().replace ("_" , "" )
8786
@@ -126,11 +125,12 @@ def get_block_fields(block: Block) -> list[str]:
126125
127126 return fields
128127
128+
129129# TODO: Check against templates without blocks
130- def generate () :
130+ def _generate ( environment : Environment , import_types : bool ) -> str :
131131 context = Context (
132132 components = [],
133- import_types = True ,
133+ import_types = import_types ,
134134 )
135135
136136 if environment .loader is None :
@@ -155,28 +155,50 @@ def generate():
155155 parent_components .append (template_name_as_title (template_name ) + name_as_title (block .name ))
156156
157157 name = template_name_as_title (template_name )
158- all_components .append (GeneratedComponent (
159- name = name ,
160- template_name = template_name ,
161- block_name = "content" ,
162- parent_components = parent_components ,
163- fields = [],
164- ))
158+ all_components .append (
159+ GeneratedComponent (
160+ name = name ,
161+ template_name = template_name ,
162+ block_name = "content" ,
163+ parent_components = parent_components ,
164+ fields = [],
165+ )
166+ )
167+
168+ # Add all components without parents
169+ for c in all_components :
170+ if len (list (c .parent_components )) != 0 :
171+ continue
172+ context .components .append (c )
165173
174+ while len (all_components ) != len (context .components ):
175+ for c in all_components :
176+ if c in context .components :
177+ continue
178+ if not all (pc in [cc .name for cc in context .components ] for pc in c .parent_components ):
179+ continue
166180
167- for component in all_components :
168- log .warning (f"component created: { component } " )
169- context .components .append (component )
181+ context .components .append (c )
170182
171183 parent_dir = Path (__file__ ).parent
172- gen_environment = Environment (loader = FileSystemLoader (parent_dir ))
173- template_file = "components.py.j2"
184+ gen_environment = Environment (loader = FileSystemLoader (parent_dir ), trim_blocks = True , lstrip_blocks = True )
185+ template_file = "components.py.j2"
174186 template = gen_environment .get_template (template_file )
175187 output = template .render (asdict (context ))
188+ return output
189+
176190
191+ def generate ():
192+ templates_location = Path (config .templates_location )
193+ if not templates_location .is_dir ():
194+ raise Exception (f"{ config .templates_location } must be a directory" )
195+
196+ environment = Environment (loader = FileSystemLoader (templates_location ))
197+ output = _generate (environment , config .require_component_types )
177198 with open ("components_gen.py" , "w" ) as f :
178199 len_written = f .write (output )
179200 assert len_written == len (output )
180201
202+
181203if __name__ == "__main__" :
182204 generate ()
0 commit comments