def parse_test(self, node): token = next(self.stream) if self.stream.current.test('name:not'): next(self.stream) negated = True else: negated = False name = self.stream.expect('name').value while self.stream.current.type == 'dot': next(self.stream) name += '.' + self.stream.expect('name').value dyn_args = dyn_kwargs = None kwargs = [] if self.stream.current.type == 'lparen': args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None) elif (self.stream.current.type in ('name', 'string', 'integer', 'float', 'lparen', 'lbracket', 'lbrace') and not self.stream.current.test_any( 'name:else', 'name:or', 'name:and')): if self.stream.current.test('name:is'): self.fail('You cannot chain multiple tests with is') args = [self.parse_primary()] else: args = [] node = nodes.Test(node, name, args, kwargs, dyn_args, dyn_kwargs, lineno=token.lineno) if negated: node = nodes.Not(node, lineno=token.lineno) return node
def unless(token: "Token", parser: "Parser") -> nodes.Node: """The unless tag {% unless ... %} ... {% endunless %} Args: token: The token matches tag name parser: The parser Returns: The parsed node """ node = result = nodes.If(lineno=token.lineno) while True: node.test = nodes.Not( parser.parse_tuple(with_condexpr=False), lineno=token.lineno, ) node.body = parser.parse_statements( ("name:elif", "name:elsif", "name:else", "name:endunless") ) node.elif_ = [] node.else_ = [] token = next(parser.stream) if token.test_any("name:elif", "name:elsif"): node = nodes.If(lineno=parser.stream.current.lineno) result.elif_.append(node) continue if token.test("name:else"): result.else_ = parser.parse_statements( ("name:endunless",), drop_needle=True ) break return result
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_unary(self): token_type = self.stream.current.type lineno = self.stream.current.lineno if token_type is 'name' and self.stream.current.value == 'not': self.stream.next() node = self.parse_unary() return nodes.Not(node, lineno=lineno) if token_type is 'sub': self.stream.next() node = self.parse_unary() return nodes.Neg(node, lineno=lineno) if token_type is 'add': self.stream.next() node = self.parse_unary() return nodes.Pos(node, lineno=lineno) return self.parse_primary()
def parse_test(self, node): token = next(self.stream) if self.stream.current.test("name:not"): next(self.stream) negated = True else: negated = False name = self.stream.expect("name").value while self.stream.current.type == "dot": next(self.stream) name += "." + self.stream.expect("name").value dyn_args = dyn_kwargs = None kwargs = [] if self.stream.current.type == "lparen": args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None) elif self.stream.current.type in ( "name", "string", "integer", "float", "lparen", "lbracket", "lbrace", ) and not self.stream.current.test_any("name:else", "name:or", "name:and"): if self.stream.current.test("name:is"): self.fail("You cannot chain multiple tests with is") args = [self.parse_primary()] else: args = [] node = nodes.Test(node, name, args, kwargs, dyn_args, dyn_kwargs, lineno=token.lineno) if negated: node = nodes.Not(node, lineno=token.lineno) return node
def parse(self, parser): lineno = next(parser.stream).lineno # Get the block selection from the tag argument. block_selection = parser.parse_expression() # Make "Name" node for "For" node target. block_name = nodes.Name('_ext_ob_blknm', 'store') # For each block, add an "If" node checking if it matches the target. # Also record the original "default" ordering of the blocks. blocks = [] block_names = [] for node in parser.parse_statements(['name:endorderblocks'], drop_needle=True): if isinstance(node, nodes.Block): blocks.append(nodes.If( nodes.Compare( block_name, [nodes.Operand('eq', nodes.Const(node.name))]), [node], [])) block_names.append(node.name) # Make a "For" node iterating over the given block selection. If the # block selection is undefined or None then use the original ordering. return nodes.For( block_name, nodes.CondExpr( nodes.And( nodes.Test(block_selection, 'defined', [], [], None, None), nodes.Not( nodes.Test(block_selection, 'none', [], [], None, None)), ), block_selection, nodes.Tuple([nodes.Const(x) for x in block_names], 'store')), blocks, [], None, False)
def parse_not(self): if self.stream.current.test('name:not'): lineno = next(self.stream).lineno return nodes.Not(self.parse_not(), lineno=lineno) return self.parse_compare()
class Builtin(object): def __init__(self, name): self.name = name def __repr__(self): return self.name # Fields used by nodes.If(). IF_NODE_FIELDS = { 'test': nodes.Not( nodes.Call(nodes.Const(Builtin('isinstance')), [ nodes.Name(DJEDI_NODE_STORAGE, 'load'), nodes.Const(Builtin('dict')), ], [], None, None)), 'body': [ nodes.Assign(nodes.Name(DJEDI_NODE_STORAGE, 'store'), nodes.Dict([])), ], } # Construct the Jinja2 AST equivalent of: # # if not isinstance(DJEDI_NODE_STORAGE, dict): # DJEDI_NODE_STORAGE = {} # if nodes.If.fields == ('test', 'body', 'elif_', 'else_'): # Jinja 2.10 added the "elif" field to If() DJEDI_NODE_STORAGE_NODE = (