def test_if_branching_multi_scope(): for_loop = nodes.For( nodes.Name("item", "store"), nodes.Name("seq", "load"), [ nodes.If( nodes.Name("expression", "load"), [nodes.Assign(nodes.Name("x", "store"), nodes.Const(42))], [], [], ), nodes.Include(nodes.Const("helper.html"), True, False), ], [], None, False, ) tmpl = nodes.Template( [nodes.Assign(nodes.Name("x", "store"), nodes.Const(23)), for_loop]) tmpl_sym = symbols_for_node(tmpl) for_sym = symbols_for_node(for_loop, tmpl_sym) assert for_sym.stores == set(["item", "x"]) assert for_sym.loads == { "l_1_x": ("alias", "l_0_x"), "l_1_item": ("param", None), "l_1_expression": ("resolve", "expression"), }
def parse_formrow(self, parser, tag): lineno = tag.lineno field = parser.parse_expression() template_name = None if not parser.stream.current.test('block_end'): template_name = parser.parse_expression() else: template_name = nodes.Call( nodes.Name('get_formrow_template', 'load'), [], [ nodes.Keyword('caller_template', nodes.Const(parser.name)), nodes.Keyword('form', nodes.Name('form_utils_form', 'load')) ], None, None, ) if not parser.stream.current.test('block_end'): raise TemplateSyntaxError("Too many arguments", lineno) node = nodes.Scope(lineno=lineno) assignments = [nodes.Assign(nodes.Name('field', 'store'), field)] node.body = assignments + [ nodes.Include(template_name, True, False) ] return node.set_lineno(lineno)
def parse(self, parser): """ Parse the referred template and the namespace. """ token = next(parser.stream) lineno = token.lineno parser.stream.expect('name:to') template = parser.parse_expression() parser.stream.expect('name:as') namespace = next(parser.stream).value includeNode = nodes.Include(lineno=lineno) includeNode.with_context = True includeNode.ignore_missing = False includeNode.template = template temp = parser.free_identifier(lineno) return [ nodes.Assign( nodes.Name(temp.name, 'store'), nodes.Name(MARKINGS, 'load') ).set_lineno(lineno), nodes.Assign( nodes.Name(MARKINGS, 'store'), nodes.Const({})).set_lineno(lineno), nodes.Assign( nodes.Name(namespace, 'store'), nodes.Const({})).set_lineno(lineno), nodes.CallBlock( self.call_method('_push_resource', args=[ nodes.Name(namespace, 'load'), nodes.Name('site', 'load'), nodes.Name('resource', 'load'), template]), [], [], []).set_lineno(lineno), nodes.Assign( nodes.Name('resource', 'store'), nodes.Getitem(nodes.Name(namespace, 'load'), nodes.Const('resource'), 'load') ).set_lineno(lineno), nodes.CallBlock( self.call_method('_assign_reference', args=[ nodes.Name(MARKINGS, 'load'), nodes.Name(namespace, 'load')]), [], [], [includeNode]).set_lineno(lineno), nodes.Assign(nodes.Name('resource', 'store'), nodes.Getitem(nodes.Name(namespace, 'load'), nodes.Const('parent_resource'), 'load') ).set_lineno(lineno), nodes.Assign( nodes.Name(MARKINGS, 'store'), nodes.Name(temp.name, 'load') ).set_lineno(lineno), ]
def parse_include(self): node = nodes.Include(lineno=next(self.stream).lineno) node.template = self.parse_expression() if self.stream.current.test('name:ignore') and \ self.stream.look().test('name:missing'): node.ignore_missing = True self.stream.skip(2) else: node.ignore_missing = False return self.parse_import_context(node, True)
def parse(self, parser): token = next(parser.stream) template = parser.parse_expression() # Create an include node for Jinja to parse it and properly import the # template. It won't interpret it if we just use an output node instead. node = nodes.Include(lineno=token.lineno) node.template = nodes.Const(f"{token.value[8:]}::{template.value}") node.ignore_missing = False node.with_context = True return node
def parse(self, parser): stream = parser.stream lineno = stream.next().lineno print(lineno) name = parser.parse_expression() objvar = nodes.Name('obj', 'load', lineno=lineno) print name assignments = [] has_property_details_kwargs = {} property_stack = self.get_property_stack(name) if property_stack: print('property_stack', property_stack) property_var = nodes.Name('property', 'store', lineno=lineno) property_node = nodes.Const(property_stack[-1]) property_details_node = self.call_method( 'get_property_details', args=[objvar, property_node]) assignments.append( nodes.Assign(property_var, property_details_node, lineno=lineno)) has_property_details_kwargs['property'] = property_var get_template_args = [objvar] properties_args = [name] if stream.next_if('name:as'): as_type = parser.parse_expression() get_template_args.append(as_type) if stream.next_if('name:with'): with_node = parser.parse_expression() print("with_node", with_node) properties_args.append(with_node) properties_var = nodes.Name('properties', 'store', lineno=lineno) properties_node = self.call_method('get_properties', args=properties_args, kwargs=has_property_details_kwargs) assignments.append( nodes.Assign(properties_var, properties_node, lineno=lineno)) call_node = self.call_method('get_template_list', args=get_template_args, kwargs=has_property_details_kwargs) scope = nodes.Scope(lineno=lineno) assign_obj = nodes.Assign(objvar, name, lineno=lineno) assignments.append(assign_obj) scope.body = assignments + [ nodes.Include(call_node, True, False, lineno=lineno) ] print(scope) return scope
def include_relative(token: Token, parser: Parser) -> nodes.Node: """The {% include_relative ... %} tag""" node = nodes.Include(lineno=token.lineno) path = parser.parse_expression() if parser.stream.filename: node.template = nodes.Add( nodes.Add( nodes.Const(os.path.dirname(parser.stream.filename)), nodes.Const(os.path.sep), ), path, ) else: node.template = path node.ignore_missing = False return parser.parse_import_context(node, True)
def test_if_branching_multi_scope(): for_loop = nodes.For(nodes.Name('item', 'store'), nodes.Name('seq', 'load'), [ nodes.If(nodes.Name('expression', 'load'), [ nodes.Assign(nodes.Name('x', 'store'), nodes.Const(42))], []), nodes.Include(nodes.Const('helper.html'), True, False) ], [], None, False) tmpl = nodes.Template([ nodes.Assign(nodes.Name('x', 'store'), nodes.Const(23)), for_loop ]) tmpl_sym = symbols_for_node(tmpl) for_sym = symbols_for_node(for_loop, tmpl_sym) assert for_sym.stores == set(['item', 'x']) assert for_sym.loads == { 'l_1_x': ('alias', 'l_0_x'), 'l_1_item': ('param', None), 'l_1_expression': ('resolve', 'expression'), }
def parse_form(self, parser, tag): lineno = tag.lineno form_instance = parser.parse_expression() template_name = nodes.Call( nodes.Name('get_formlayout_template', 'load'), [], [ nodes.Keyword('caller_template', nodes.Const(parser.name)), nodes.Keyword('form', form_instance), ], None, None, ) has_body = False if not parser.stream.current.test('block_end'): parser.stream.expect('name:using') if parser.stream.current.test('block_end'): has_body = True if not parser.stream.current.test('block_end'): template_name = parser.parse_expression() if not parser.stream.current.test('block_end'): raise TemplateSyntaxError("Too many arguments", lineno) body = None if has_body: body = parser.parse_statements(['name:endform'], drop_needle=True) else: body = nodes.Include(template_name, True, False) body = [body] node = nodes.Scope(lineno=lineno) assignments = [ nodes.Assign(nodes.Name('form_utils_form', 'store'), form_instance) ] node.body = assignments + body return node.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_include(self): node = nodes.Include(lineno=self.stream.next().lineno) node.template = self.parse_expression() return self.parse_import_context(node, True)
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', }