def _make_node(self, singular, plural, variables, plural_expr, vars_referenced, num_called_num): """Generates a useful node from the data provided.""" # no variables referenced? no need to escape for old style # gettext invocations only if there are vars. if not vars_referenced and not self.environment.newstyle_gettext: singular = singular.replace('%%', '%') if plural: plural = plural.replace('%%', '%') # singular only: if plural_expr is None: gettext = nodes.Name('gettext', 'load') node = nodes.Call(gettext, [nodes.Const(singular)], [], None, None) # singular and plural else: ngettext = nodes.Name('ngettext', 'load') node = nodes.Call( ngettext, [nodes.Const(singular), nodes.Const(plural), plural_expr], [], None, None) # in case newstyle gettext is used, the method is powerful # enough to handle the variable expansion and autoescape # handling itself if self.environment.newstyle_gettext: for key, value in iteritems(variables): # the function adds that later anyways in case num was # called num, so just skip it. if num_called_num and key == 'num': continue node.kwargs.append(nodes.Keyword(key, value)) # otherwise do that here else: # mark the return value as safe if we are in an # environment with autoescaping turned on node = nodes.MarkSafeIfAutoescape(node) if variables: node = nodes.Mod( node, nodes.Dict([ nodes.Pair(nodes.Const(key), value) for key, value in variables.items() ])) return nodes.Output([node])
def parse(self, parser): list_of_paths = getattr(settings, 'LATEX_GRAPHICSPATH', [settings.BASE_DIR]) value = '\graphicspath{ ' + ' '.join( map(format_path_for_latex, list_of_paths)) + ' }' node = nodes.Output(lineno=next(parser.stream).lineno) node.nodes = [nodes.MarkSafe(nodes.Const(value))] return node
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 parse(self, parser): lineno = parser.stream.next().lineno files = [] output = nodes.Const(None) filters = nodes.Const(None) # parse the arguments first = True while parser.stream.current.type != 'block_end': if not first: parser.stream.expect('comma') first = False # lookahead to see if this is an assignment (an option) if parser.stream.current.test( 'name') and parser.stream.look().test('assign'): name = parser.stream.next().value parser.stream.skip() value = parser.parse_expression() if name == 'filters': filters = value elif name == 'filter': filters = value warnings.warn( 'The "filter" option of the {%% assets %%} ' 'template tag has been renamed to ' '"filters" for consistency reasons ' '(line %s).' % lineno, DeprecationWarning) elif name == 'output': output = value else: parser.fail('Invalid keyword argument: %s' % name) # otherwise assume a source file is given, which may # be any expression, except note that strings are handled # separately above else: files.append(parser.parse_expression()) # parse the contents of this tag, and return a block body = parser.parse_statements(['name:endassets'], drop_needle=True) return nodes.CallBlock( self.call_method('_render_assets', args=[filters, output, nodes.List(files)]), [nodes.Name('ASSET_URL', 'store')], [], body).\ set_lineno(lineno)
def parse(self, parser): lineno = next(parser.stream).lineno body = parser.parse_statements(["name:endreplacetabs"], drop_needle=True) return nodes.CallBlock(self.call_method("_process", [nodes.Const(" ")]), [], [], body, lineno=lineno)
def parse(self, parser): last_indent = nodes.Const(parser.stream.current.last_indent) lineno = next(parser.stream).lineno body = parser.parse_statements(["name:endautoindent"], drop_needle=True) return nodes.CallBlock(self.call_method("_autoindent", [last_indent]), [], [], body, lineno=lineno)
def parse(self, parser): lineno = next(parser.stream).lineno args = [parser.parse_expression()] if parser.stream.skip_if("comma"): args.append(parser.parse_expression) else: args.append(nodes.Const(None)) node = self.call_method('_generate_routes', args, lineno=lineno) return nodes.CallBlock(node, [], [], [], lineno=lineno)
def parse(self, parser): lineno = next(parser.stream).lineno args = [parser.parse_expression()] return nodes.Output([ nodes.MarkSafe(nodes.Const('assets/')), nodes.MarkSafe(args[0]), ], lineno=lineno)
def parse(self, parser): lineno = parser.stream.next().lineno args = [] mode = parser.parse_expression().name args.append(nodes.Const(mode)) body = parser.parse_statements(['name:endcompress'], drop_needle=True) return nodes.CallBlock(self.call_method('_compress', args), [], [], body).set_lineno(lineno)
def parse(self, parser): lineno = parser.stream.current.lineno tag_name = parser.stream.current.value additional_params = [ nodes.Keyword('_context', nodes.ContextReference()), nodes.Keyword('_template', nodes.Const(parser.name)), nodes.Keyword('_lineno', nodes.Const(lineno)), nodes.Keyword('_tag_name', nodes.Const(tag_name)), ] self.init_parser(parser) args, kwargs, target = self.parse_args(parser) kwargs.extend(additional_params) block_call = self.call_method('render_wrapper', args, kwargs) return self.output(parser, block_call, target, tag_name=tag_name, lineno=lineno)
def parse_compare(self): token = self.stream.current if token.type == 'name': if token.value in ('true', 'false', 'True', 'False'): node = nodes.Const(token.value in ('true', 'True'), lineno=token.lineno) elif token.value in ('none', 'None'): node = nodes.Const(None, lineno=token.lineno) else: node = nodes.Name(token.value, 'load', lineno=token.lineno) next(self.stream) elif token.type == 'lparen': next(self.stream) node = self.parse_expression() self.stream.expect('rparen') else: self.fail("unexpected token '%s'" % (token, ), token.lineno) return node
def parse(self, parser): lineno = next(parser.stream).lineno namearg = parser.parse_expression() if isinstance(namearg, nodes.Name): namearg = nodes.Const(namearg.name) ctx_ref = jinja2.nodes.ContextReference() args = [ctx_ref, namearg] body = parser.parse_statements(['name:endpjaxblock'], drop_needle=True) return nodes.CallBlock(self.call_method('_process', args), [], [], body).set_lineno(lineno)
def parse(self, parser): token = next(parser.stream) lineno = token.lineno filename = parser.name error = parser.parse_expression() args = [error, nodes.Const(filename), nodes.Const(lineno)] try: body = parser.parse_statements(["name:endtry"], drop_needle=True) node = nodes.CallBlock(self.call_method("_handle_body", args), [], [], body).set_lineno(lineno) except Exception as e: # that was expected self._logger.exception("Caught exception while parsing template") node = nodes.CallBlock(self.call_method("_handle_error", [nodes.Const(self._format_error(error, e, filename, lineno))]), [], [], []).set_lineno(lineno) return node
def _empty_extension_parse(self, open_token_condition, parser): args = [ nodes.ContextReference(), nodes.Const(parser.filename), nodes.Const(parser.stream.current.lineno) ] kwargs = {} name_token = parser.stream.expect(open_token_condition) automata_state = AutomataState.Expect_Name while parser.stream.current.type != TOKEN_BLOCK_END: if automata_state == AutomataState.Expect_Name: name_token = parser.stream.expect(TOKEN_NAME) automata_state = AutomataState.Expect_Assign elif automata_state == AutomataState.Expect_Assign: parser.stream.skip_if(TOKEN_ASSIGN) automata_state = AutomataState.Expect_Value elif automata_state == AutomataState.Expect_Value: value_token = parser.stream.next_if(TOKEN_FLOAT) if value_token: kwargs[name_token.value] = value_token.value else: value_token = parser.stream.next_if(TOKEN_INTEGER) if value_token: kwargs[name_token.value] = value_token.value else: value_token = parser.stream.expect(TOKEN_STRING) kwargs[name_token.value] = value_token.value automata_state = AutomataState.Expect_Comma elif automata_state == AutomataState.Expect_Comma: parser.stream.skip_if(TOKEN_COMMA) automata_state = AutomataState.Expect_Name lineno = parser.stream.current.lineno return nodes.CallBlock( self.call_method('_process_markup', args, [ nodes.Keyword(name, nodes.Const(value)) for name, value in kwargs.items() ]), [], [], []).set_lineno(lineno)
def parse(self, parser): lineno = next(parser.stream).lineno parts = [parser.stream.expect('name').value] while parser.stream.current.type != 'block_end': parser.stream.expect('dot') parts.append(parser.stream.expect('name').value) body = parser.parse_statements(['name:endeditable'], drop_needle=True) call = self.call_method( '_editable_loader', [nodes.Name(parts[0], 'load'), nodes.Const(parts[1:]), nodes.Const(not body)]) output_nodes = [ nodes.Output([nodes.MarkSafe(call)]) ] output_nodes.extend(body) output_nodes.extend([ nodes.Output([nodes.MarkSafe(nodes.TemplateData('</span>'))]), ]) block_name = '%s_%s_%d' %(parts[-2], parts[-1], random.randint(0, 500)) return nodes.Block(block_name, output_nodes, True)
def parse(self, parser): tag = parser.stream.next() path = parser.parse_expression() return nodes.Output([ self.call_method('_render', [ path, nodes.Const(tag.value), nodes.Name('_current_app', 'load') ]), ]).set_lineno(tag.lineno)
def parse(self, parser): lineno = six.next(parser.stream).lineno while not six.next(parser.stream).test('block_end'): pass body = nodes.Const(six.next(parser.stream).value) while not parser.stream.current.test('block_end'): six.next(parser.stream) return nodes.Output([ self.call_method('_django', args=[body], kwargs=[]), ]).set_lineno(lineno=lineno)
def _parse_trans(self, parser, lineno): string = parser.stream.expect(lexer.TOKEN_STRING) string = nodes.Const(string.value, lineno=string.lineno) is_noop = False context = None as_var = None for token in iter(lambda: parser.stream.next_if(lexer.TOKEN_NAME), None): if token.value == 'noop' and not is_noop: if context is not None: parser.fail("noop translation can't have context", lineno=token.lineno) is_noop = True elif token.value == 'context' and context is None: if is_noop: parser.fail("noop translation can't have context", lineno=token.lineno) context = parser.stream.expect(lexer.TOKEN_STRING) context = nodes.Const(context.value, lineno=context.lineno) elif token.value == 'as' and as_var is None: as_var = parser.stream.expect(lexer.TOKEN_NAME) as_var = nodes.Name(as_var.value, 'store', lineno=as_var.lineno) else: parser.fail("expected 'noop', 'context' or 'as'", lineno=token.lineno) if is_noop: output = string elif context is not None: func = nodes.Name('pgettext', 'load', lineno=lineno) output = nodes.Call(func, [context, string], [], None, None, lineno=lineno) else: func = nodes.Name('gettext', 'load') output = nodes.Call(func, [string], [], None, None, lineno=lineno) if as_var is None: return nodes.Output([output], lineno=lineno) else: return nodes.Assign(as_var, output, lineno=lineno)
def parse(self, parser): """ Parse Jinja statement tag defined in `self.tags` (default: css, js). This accually tries to build corresponding html script tag or collect script file name in jinja2 environment variable. If you use bundles it is important to call ``get_css_bundle`` or ``get_js_bundle`` in template after all occurrences of script tags (e.g. {% css ... %}, {% js ...%}). """ tag = parser.stream.current.value lineno = next(parser.stream).lineno default_bundle_name = u"%s" % (self.environment.default_bundle_name) default_bundle_name.encode('utf-8') bundle_name = nodes.Const(default_bundle_name) #parse filename if parser.stream.current.type != 'block_end': value = parser.parse_expression() # get first optional argument: bundle_name if parser.stream.skip_if('comma'): bundle_name = parser.parse_expression() if isinstance(bundle_name, nodes.Name): bundle_name = nodes.Name(bundle_name.name, 'load') else: value = parser.parse_tuple() args = [nodes.Const(tag), value, bundle_name] # Return html tag with link to corresponding script file. if self.environment.use_bundle is False: value = value.value if callable(self.environment.collection_templates[tag]): node = self.environment.collection_templates[tag](value) else: node = self.environment.collection_templates[tag] % value return nodes.Output( [nodes.MarkSafeIfAutoescape(nodes.Const(node))]) # Call :meth:`_update` to collect names of used scripts. return nodes.CallBlock( self.call_method('_update', args=args, lineno=lineno), [], [], '')
def parse(self, parser): tag = parser.stream.current.value lineno = next(parser.stream).lineno if parser.stream.current.type == 'block_end': args = [nodes.Const(True)] else: args = [parser.parse_expression()] body = parser.parse_statements(['name:end%s' % tag], drop_needle=True) call = self.call_method('_proofread', args) return nodes.CallBlock(call, [], [], body, lineno=lineno)
def parse(self, parser): lineno = next(parser.stream).lineno args = [parser.parse_expression()] if parser.stream.skip_if('comma'): args.append(parser.parse_expression()) else: args.append(nodes.Const(0)) body = [] return nodes.CallBlock(self.call_method('_image', args), [], [], body).set_lineno(lineno)
def parse_experiment(self, parser): """Parse {% experiment ... %} tags""" lineno = parser.stream.current.lineno # list of nodes that will be used when calling the callback: args = [] # get tag parameters: while parser.stream.current.type != 'block_end': if parser.stream.skip_if('comma'): continue # just ignore commas # {% experiment %} tag only accepts strings, i.e. Const: args.append(nodes.Const(parser.stream.current.value)) next(parser.stream) # verify tag syntax: tokens = [nodes.Const('experiment')] + args try: _parse_token_contents(list(map(attrgetter('value'), tokens))) except ValueError: raise TemplateSyntaxError( "Syntax should be like: " "{% experiment experiment_name" " alternative [weight=val] [user=val] %}", lineno, ) # fill in default values: while len(args) < 4: args.append(nodes.Const(None)) # additional args: args.append(nodes.ContextReference()) # parse the body of the block up to `endexperiment` and # drop the needle (which will always be `endexperiment`): body = parser.parse_statements(['name:endexperiment'], drop_needle=True) # Jinja2 callbacky nodey magic: call_node = self.call_method('render_experiment', args, lineno=lineno) return nodes.CallBlock(call_node, [], [], body).set_lineno(lineno)
def parse(self, parser): tag = parser.stream.next() attrs = self.parse_attrs(parser) attrs = nodes.Dict([nodes.Pair(nodes.Const(k), v) for k,v in attrs.items()]) body = parser.parse_statements(['name:end'+tag.value], drop_needle=True) return [nodes.CallBlock(self.call_method('_call_simple_block', args=[attrs]), [], [], body).set_lineno(tag.lineno)]
def parse(self, parser): token = next(parser.stream) lineno = token.lineno name = next(parser.stream).value args = [nodes.Name('entry', 'load'), nodes.Const(name)] body = parser.parse_statements(['name:endmark'], drop_needle=True) return nodes.CallBlock(self.call_method('_set_attr', args=args), [], [], body).set_lineno(lineno)
def buffer_node(self, parser, uri, default): node_id = self.create_node_id(uri.value, default.value) for node in self._node_storage: if node.items[0].value == node_id: break else: self._node_storage.append(self.create_tuple(node_id, uri, default)) return nodes.Getitem(nodes.Name(DJEDI_NODE_STORAGE, 'load'), nodes.Const(node_id), None)
def fake_parse_expression(): '''This method mocks parse expression and returns expected named parameters.''' syntax_ex = TemplateSyntaxError("unexpected end of tag", lineno=mock_lineno) self._parse_index += 1 if self._parse_index == 1: if mock_template is None: raise syntax_ex if not mock_template: return return nodes.Name(*["template", environment]) if self._parse_index == 2: if mock_template is None: raise syntax_ex if not mock_template: return return nodes.Const(mock_template) if self._parse_index == 3: if not mock_url: raise syntax_ex return nodes.Name(*["url", environment]) if self._parse_index == 4: return nodes.Const(mock_url) if self._parse_index == 5: if not mock_runtime: raise syntax_ex return nodes.Name(*["runtime", environment]) if self._parse_index == 6: return nodes.Const(mock_runtime)
def parse(self, parser): token = next(parser.stream) defaults = parser.parse_expression() if parser.stream.skip_if('name:with'): errors = parser.parse_expression() else: errors = nodes.Const({}) body = parser.parse_statements(['name:endformfill'], drop_needle=True) return nodes.CallBlock( self.call_method('_formfill_support', [defaults, errors]), [], [], body).set_lineno(token.lineno)
def parse(self, parser): lineno = next(parser.stream).lineno args = [parser.parse_expression()] # 解析标签参数,包括 timeout if parser.stream.skip_if('comma'): args.append(parser.parse_expression()) else: args.append(nodes.Const('%s%s' % (parser.filename, lineno))) vary_on = [] while parser.stream.skip_if('comma'): vary_on.append(parser.parse_expression()) if vary_on: args.append(nodes.List(vary_on)) else: args.append(nodes.Const([])) body = parser.parse_statements(['name:endcache'], drop_needle=True) return nodes.CallBlock(self.call_method('_cache', args), [], [], body).set_lineno(lineno)
def _parse_qblock(self, parser, lineno): name = parser.parse_assign_target(name_only=True).name body = parser.parse_statements(['name:endqblock'], drop_needle=True) return nodes.If( nodes.Compare( # name in __blocks__ nodes.Const(name), [nodes.Operand('in', nodes.Name('__blocks__', 'load'))]), body, [], # elif_ [] # orelse ).set_lineno(lineno)
def parse_kwargs(parser): """ Parses keyword arguments in tags. """ name = parser.stream.expect('name').value parser.stream.expect('assign') if parser.stream.current.test('string'): value = parser.parse_expression() else: value = nodes.Const(parser.stream.next().value) return (name, value)