def parse(self, parser): m = nodes.Macro(lineno=next(parser.stream).lineno) name = parser.parse_assign_target(name_only=True).name m.name = f"default_{name}" parser.parse_signature(m) m.body = parser.parse_statements(("name:enddefaultmacro",), drop_needle=True) if_stmt = nodes.If( nodes.Not(nodes.Name(name, "load")), [nodes.Macro(name, m.args, m.defaults, m.body)], [], [], ) return [m, if_stmt]
def parse_macro(self): node = nodes.Macro(lineno=next(self.stream).lineno) node.name = self.parse_assign_target(name_only=True).name self.parse_signature(node) node.body = self.parse_statements(('name:endmacro', ), drop_needle=True) return node
def parse_load(self, parser): filter_name = parser.stream.current.value lineno = next(parser.stream).lineno if filter_name not in self.environment.filters: parser.fail("Unable to parse {0}".format(filter_name), lineno) parser.stream.expect("name:as") target = parser.parse_assign_target() macro_name = "_" + parser.free_identifier().name macro_body = parser.parse_statements(("name:endload", ), drop_needle=True) return [ nodes.Macro(macro_name, [], [], macro_body).set_lineno(lineno), nodes.Assign( target, nodes.Filter( nodes.Call( nodes.Name(macro_name, "load").set_lineno(lineno), [], [], None, None, ).set_lineno(lineno), filter_name, [], [], None, None, ).set_lineno(lineno), ).set_lineno(lineno), ]
def parse_part(self, parser, token): node = nodes.Macro(lineno=token.lineno) part_name = parser.stream.expect('name').value node.name = "compopart_" + part_name parser.parse_signature(node) node.args = [ nodes.Name("self", "param"), nodes.Name("has_caller", "param") ] + node.args # + [nodes.Name("caller", "param")] assign_node = nodes.Assign() assign_node.target = nodes.Name("dummy", "store") call_node = nodes.Call() call_node.node = nodes.Getattr() call_node.node.node = nodes.Name("self", "load") call_node.node.attr = "overwrite_compopart" # calls the method "self.overwrite_compopart()" from the components call_node.node.ctx = "load" call_node.args = [ nodes.Const(part_name), nodes.Name('compopart_' + part_name, 'load') ] call_node.kwargs = [] call_node.dyn_args = None call_node.dyn_kwargs = None assign_node.node = call_node node.body = parser.parse_statements(('name:endcompopart', ), drop_needle=True) return [node, assign_node]
def parse_componentdef(self, parser, token): node = nodes.Macro(lineno=token.lineno) node.name = "main" parser.parse_signature(node) node.args = [ nodes.Name("self", "param"), nodes.Name("has_caller", "param") ] + node.args # + [nodes.Name("caller", "param")] node.body = parser.parse_statements(('name:endcompodef', ), drop_needle=True) return node
def parse_componentpart(self, parser, token): node = nodes.Macro(lineno=token.lineno) node.name = "compopart_" + parser.stream.expect('name').value parser.parse_signature(node) node.args = [ nodes.Name("self", "param"), nodes.Name("has_caller", "param") ] + node.args # + [nodes.Name("caller", "param")] node.body = parser.parse_statements(('name:endcompopartdef', ), drop_needle=True) return node
def _parse_query(self, parser, lineno): name = parser.parse_assign_target(with_tuple=False).name body = parser.parse_statements(['name:endquery'], drop_needle=True) # name, params, defaults, body return nodes.Macro(name, [nodes.Name('__blocks__', 'param')], [], body).set_lineno(lineno)
def test_complex(): title_block = nodes.Block( "title", [nodes.Output([nodes.TemplateData(u"Page Title")])], False) render_title_macro = nodes.Macro( "render_title", [nodes.Name("title", "param")], [], [ nodes.Output([ nodes.TemplateData(u'\n <div class="title">\n <h1>'), nodes.Name("title", "load"), nodes.TemplateData(u"</h1>\n <p>"), nodes.Name("subtitle", "load"), nodes.TemplateData(u"</p>\n "), ]), nodes.Assign(nodes.Name("subtitle", "store"), nodes.Const("something else")), nodes.Output([ nodes.TemplateData(u"\n <p>"), nodes.Name("subtitle", "load"), nodes.TemplateData(u"</p>\n </div>\n"), nodes.If( nodes.Name("something", "load"), [ nodes.Assign( nodes.Name("title_upper", "store"), nodes.Filter( nodes.Name("title", "load"), "upper", [], [], None, None, ), ), nodes.Output([ nodes.Name("title_upper", "load"), nodes.Call( nodes.Name("render_title", "load"), [nodes.Const("Aha")], [], None, None, ), ]), ], [], [], ), ]), ], ) for_loop = nodes.For( nodes.Name("item", "store"), nodes.Name("seq", "load"), [ nodes.Output([ nodes.TemplateData(u"\n <li>"), nodes.Name("item", "load"), nodes.TemplateData(u"</li>\n <span>"), ]), nodes.Include(nodes.Const("helper.html"), True, False), nodes.Output([nodes.TemplateData(u"</span>\n ")]), ], [], None, False, ) body_block = nodes.Block( "body", [ nodes.Output([ nodes.TemplateData(u"\n "), nodes.Call( nodes.Name("render_title", "load"), [nodes.Name("item", "load")], [], None, None, ), nodes.TemplateData(u"\n <ul>\n "), ]), for_loop, nodes.Output([nodes.TemplateData(u"\n </ul>\n")]), ], False, ) tmpl = nodes.Template([ nodes.Extends(nodes.Const("layout.html")), title_block, render_title_macro, body_block, ]) tmpl_sym = symbols_for_node(tmpl) assert tmpl_sym.refs == { "render_title": "l_0_render_title", } assert tmpl_sym.loads == { "l_0_render_title": ("undefined", None), } assert tmpl_sym.stores == set(["render_title"]) assert tmpl_sym.dump_stores() == { "render_title": "l_0_render_title", } macro_sym = symbols_for_node(render_title_macro, tmpl_sym) assert macro_sym.refs == { "subtitle": "l_1_subtitle", "something": "l_1_something", "title": "l_1_title", "title_upper": "l_1_title_upper", } assert macro_sym.loads == { "l_1_subtitle": ("resolve", "subtitle"), "l_1_something": ("resolve", "something"), "l_1_title": ("param", None), "l_1_title_upper": ("resolve", "title_upper"), } assert macro_sym.stores == set(["title", "title_upper", "subtitle"]) assert macro_sym.find_ref("render_title") == "l_0_render_title" assert macro_sym.dump_stores() == { "title": "l_1_title", "title_upper": "l_1_title_upper", "subtitle": "l_1_subtitle", "render_title": "l_0_render_title", } body_sym = symbols_for_node(body_block) assert body_sym.refs == { "item": "l_0_item", "seq": "l_0_seq", "render_title": "l_0_render_title", } assert body_sym.loads == { "l_0_item": ("resolve", "item"), "l_0_seq": ("resolve", "seq"), "l_0_render_title": ("resolve", "render_title"), } assert body_sym.stores == set([]) for_sym = symbols_for_node(for_loop, body_sym) assert for_sym.refs == { "item": "l_1_item", } assert for_sym.loads == { "l_1_item": ("param", None), } assert for_sym.stores == set(["item"]) assert for_sym.dump_stores() == { "item": "l_1_item", }
def parse(self, parser): # Get the component for the tag name that we matched on tag_name = parser.stream.current[2] component_class = self.environment.components[tag_name] field_names = [f.name for f in dataclasses.fields(component_class)] has_children = CHILDREN_FIELD_NAME in field_names lineno = next(parser.stream).lineno node = nodes.Scope(lineno=lineno) # list of `Pair` nodes for tag properties to update "component" dictionary component_dict_update_items = [] while parser.stream.current.type != 'block_end': lineno = parser.stream.current.lineno if component_dict_update_items: parser.stream.expect('comma') name = parser.stream.expect('name') parser.stream.expect('assign') value = parser.parse_expression() component_dict_update_items.append( nodes.Pair(nodes.Const(name.value), value)) # dictionary initialization in the "component" name prepare_component_dict = [ self._initialize_component_dict(component_class, lineno) ] if component_dict_update_items: component_dict_delta = nodes.Dict(component_dict_update_items) # `Getattr` for "update" function of the dictionary "component" update_component_dict_fun = nodes.Getattr( nodes.Name(TMP_COMPONENT_DICT_NAME, 'load'), 'update', 'load') # `Call` for `component.update(<prop name>, <prop value>)` call_component_dict_update = nodes.Call(update_component_dict_fun, [component_dict_delta], [], None, None) prepare_component_dict.append( nodes.ExprStmt(call_component_dict_update)) # assign `component = __component` and `__component = None` prepare_component_dict.extend([ nodes.Assign(nodes.Name(COMPONENT_DICT_NAME, 'store', lineno=lineno), nodes.Name(TMP_COMPONENT_DICT_NAME, 'load', lineno=lineno), lineno=lineno), nodes.Assign(nodes.Name(TMP_COMPONENT_DICT_NAME, 'store', lineno=lineno), nodes.Const(None, lineno=lineno), lineno=lineno) ]) if has_children: inner_block = list( parser.parse_statements(('name:end' + tag_name, ), drop_needle=True)) # create children() macro children_macro = nodes.Macro() children_macro.name = CHILDREN_MACRO_NAME children_macro.args = [] children_macro.defaults = [] children_macro.body = inner_block children_macro_nodes = [children_macro] else: children_macro_nodes = [] # include tag template include_tag = nodes.Include() # use `template` item of the "component" dictionary for template path include_tag.template = nodes.Getitem(nodes.Name(COMPONENT_DICT_NAME, 'load', lineno=lineno), nodes.Const(TEMPLATE_FIELD_NAME, lineno=lineno), 'load', lineno=lineno) include_tag.ignore_missing = False include_tag.with_context = True node.body = prepare_component_dict + children_macro_nodes + [ include_tag, ] return node
def test_complex(): title_block = nodes.Block('title', [ nodes.Output([nodes.TemplateData(u'Page Title')]) ], False) render_title_macro = nodes.Macro('render_title', [nodes.Name('title', 'param')], [], [ nodes.Output([ nodes.TemplateData(u'\n <div class="title">\n <h1>'), nodes.Name('title', 'load'), nodes.TemplateData(u'</h1>\n <p>'), nodes.Name('subtitle', 'load'), nodes.TemplateData(u'</p>\n ')]), nodes.Assign( nodes.Name('subtitle', 'store'), nodes.Const('something else')), nodes.Output([ nodes.TemplateData(u'\n <p>'), nodes.Name('subtitle', 'load'), nodes.TemplateData(u'</p>\n </div>\n'), nodes.If( nodes.Name('something', 'load'), [ nodes.Assign(nodes.Name('title_upper', 'store'), nodes.Filter(nodes.Name('title', 'load'), 'upper', [], [], None, None)), nodes.Output([ nodes.Name('title_upper', 'load'), nodes.Call(nodes.Name('render_title', 'load'), [ nodes.Const('Aha')], [], None, None)])], [])])]) for_loop = nodes.For( nodes.Name('item', 'store'), nodes.Name('seq', 'load'), [ nodes.Output([ nodes.TemplateData(u'\n <li>'), nodes.Name('item', 'load'), nodes.TemplateData(u'</li>\n <span>')]), nodes.Include(nodes.Const('helper.html'), True, False), nodes.Output([ nodes.TemplateData(u'</span>\n ')])], [], None, False) body_block = nodes.Block('body', [ nodes.Output([ nodes.TemplateData(u'\n '), nodes.Call(nodes.Name('render_title', 'load'), [ nodes.Name('item', 'load')], [], None, None), nodes.TemplateData(u'\n <ul>\n ')]), for_loop, nodes.Output([nodes.TemplateData(u'\n </ul>\n')])], False) tmpl = nodes.Template([ nodes.Extends(nodes.Const('layout.html')), title_block, render_title_macro, body_block, ]) tmpl_sym = symbols_for_node(tmpl) assert tmpl_sym.refs == { 'render_title': 'l_0_render_title', } assert tmpl_sym.loads == { 'l_0_render_title': ('undefined', None), } assert tmpl_sym.stores == set(['render_title']) assert tmpl_sym.dump_stores() == { 'render_title': 'l_0_render_title', } macro_sym = symbols_for_node(render_title_macro, tmpl_sym) assert macro_sym.refs == { 'subtitle': 'l_1_subtitle', 'something': 'l_1_something', 'title': 'l_1_title', 'title_upper': 'l_1_title_upper', } assert macro_sym.loads == { 'l_1_subtitle': ('resolve', 'subtitle'), 'l_1_something': ('resolve','something'), 'l_1_title': ('param', None), 'l_1_title_upper': ('resolve', 'title_upper'), } assert macro_sym.stores == set(['title', 'title_upper', 'subtitle']) assert macro_sym.find_ref('render_title') == 'l_0_render_title' assert macro_sym.dump_stores() == { 'title': 'l_1_title', 'title_upper': 'l_1_title_upper', 'subtitle': 'l_1_subtitle', 'render_title': 'l_0_render_title', } body_sym = symbols_for_node(body_block) assert body_sym.refs == { 'item': 'l_0_item', 'seq': 'l_0_seq', 'render_title': 'l_0_render_title', } assert body_sym.loads == { 'l_0_item': ('resolve', 'item'), 'l_0_seq': ('resolve', 'seq'), 'l_0_render_title': ('resolve', 'render_title'), } assert body_sym.stores == set([]) for_sym = symbols_for_node(for_loop, body_sym) assert for_sym.refs == { 'item': 'l_1_item', } assert for_sym.loads == { 'l_1_item': ('param', None), } assert for_sym.stores == set(['item']) assert for_sym.dump_stores() == { 'item': 'l_1_item', }