def parse_subscript(self, node):
     token = next(self.stream)
     if token.type == 'dot':
         attr_token = self.stream.current
         next(self.stream)
         if attr_token.type == 'name':
             return nodes.Getattr(node, attr_token.value, 'load',
                                  lineno=token.lineno)
         elif attr_token.type != 'integer':
             self.fail('expected name or number', attr_token.lineno)
         arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
         return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
     if token.type == 'lbracket':
         priority_on_attribute = False
         args = []
         while self.stream.current.type != 'rbracket':
             if args:
                 self.stream.expect('comma')
             args.append(self.parse_subscribed())
         self.stream.expect('rbracket')
         if len(args) == 1:
             arg = args[0]
         else:
             arg = nodes.Tuple(args, 'load', lineno=token.lineno)
         return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
     self.fail('expected subscript expression', self.lineno)
Example #2
0
File: parser.py Project: slide/main
 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_expression()]
     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_primary(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 == 'string':
         next(self.stream)
         buf = [token.value]
         lineno = token.lineno
         while self.stream.current.type == 'string':
             buf.append(self.stream.current.value)
             next(self.stream)
         node = nodes.Const(''.join(buf), lineno=lineno)
     elif token.type in ('integer', 'float'):
         next(self.stream)
         node = nodes.Const(token.value, lineno=token.lineno)
     elif token.type == 'lparen':
         next(self.stream)
         node = self.parse_tuple(explicit_parentheses=True)
         self.stream.expect('rparen')
     elif token.type == 'lbracket':
         node = self.parse_list()
     elif token.type == 'lbrace':
         node = self.parse_dict()
     else:
         self.fail("unexpected '%s'" % describe_token(token), token.lineno)
     return node
Example #4
0
 def next(self):
     token = self.stream.current
     if token.type is TOKEN_EOF:
         self.stream.close()
         raise StopIteration()
     next(self.stream)
     return token
 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_expression()]
     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
Example #6
0
File: parser.py Project: slide/main
 def parse_subscript(self, node):
     token = next(self.stream)
     if token.type == "dot":
         attr_token = self.stream.current
         next(self.stream)
         if attr_token.type == "name":
             return nodes.Getattr(node, attr_token.value, "load", lineno=token.lineno)
         elif attr_token.type != "integer":
             self.fail("expected name or number", attr_token.lineno)
         arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
         return nodes.Getitem(node, arg, "load", lineno=token.lineno)
     if token.type == "lbracket":
         priority_on_attribute = False
         args = []
         while self.stream.current.type != "rbracket":
             if args:
                 self.stream.expect("comma")
             args.append(self.parse_subscribed())
         self.stream.expect("rbracket")
         if len(args) == 1:
             arg = args[0]
         else:
             arg = nodes.Tuple(args, "load", lineno=token.lineno)
         return nodes.Getitem(node, arg, "load", lineno=token.lineno)
     self.fail("expected subscript expression", self.lineno)
    def parse_statements(self, end_tokens, drop_needle=False):
        """Parse multiple statements into a list until one of the end tokens
        is reached.  This is used to parse the body of statements as it also
        parses template data if appropriate.  The parser checks first if the
        current token is a colon and skips it if there is one.  Then it checks
        for the block end and parses until if one of the `end_tokens` is
        reached.  Per default the active token in the stream at the end of
        the call is the matched end token.  If this is not wanted `drop_needle`
        can be set to `True` and the end token is removed.
        """
        # the first token may be a colon for python compatibility
        self.stream.skip_if('colon')

        # in the future it would be possible to add whole code sections
        # by adding some sort of end of statement token and parsing those here.
        self.stream.expect('block_end')
        result = self.subparse(end_tokens)

        # we reached the end of the template too early, the subparser
        # does not check for this, so we do that now
        if self.stream.current.type == 'eof':
            self.fail_eof(end_tokens)

        if drop_needle:
            next(self.stream)
        return result
Example #8
0
File: parser.py Project: slide/main
 def parse_primary(self, with_postfix=True):
     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 == "string":
         next(self.stream)
         buf = [token.value]
         lineno = token.lineno
         while self.stream.current.type == "string":
             buf.append(self.stream.current.value)
             next(self.stream)
         node = nodes.Const("".join(buf), lineno=lineno)
     elif token.type in ("integer", "float"):
         next(self.stream)
         node = nodes.Const(token.value, lineno=token.lineno)
     elif token.type == "lparen":
         next(self.stream)
         node = self.parse_tuple()
         self.stream.expect("rparen")
     elif token.type == "lbracket":
         node = self.parse_list()
     elif token.type == "lbrace":
         node = self.parse_dict()
     else:
         self.fail("unexpected token '%s'" % (token,), token.lineno)
     if with_postfix:
         node = self.parse_postfix(node)
     return node
Example #9
0
 def __init__(self, generator, name, filename):
     self._next = iter(generator).next
     self._pushed = deque()
     self.name = name
     self.filename = filename
     self.closed = False
     self.current = Token(1, TOKEN_INITIAL, '')
     next(self)
 def parse_add(self):
     lineno = self.stream.current.lineno
     left = self.parse_sub()
     while self.stream.current.type == 'add':
         next(self.stream)
         right = self.parse_sub()
         left = nodes.Add(left, right, lineno=lineno)
         lineno = self.stream.current.lineno
     return left
 def parse_sub(self):
     lineno = self.stream.current.lineno
     left = self.parse_concat()
     while self.stream.current.type == 'sub':
         next(self.stream)
         right = self.parse_concat()
         left = nodes.Sub(left, right, lineno=lineno)
         lineno = self.stream.current.lineno
     return left
 def parse_concat(self):
     lineno = self.stream.current.lineno
     args = [self.parse_mul()]
     while self.stream.current.type == 'tilde':
         next(self.stream)
         args.append(self.parse_mul())
     if len(args) == 1:
         return args[0]
     return nodes.Concat(args, lineno=lineno)
 def parse_mul(self):
     lineno = self.stream.current.lineno
     left = self.parse_div()
     while self.stream.current.type == 'mul':
         next(self.stream)
         right = self.parse_div()
         left = nodes.Mul(left, right, lineno=lineno)
         lineno = self.stream.current.lineno
     return left
 def parse_floordiv(self):
     lineno = self.stream.current.lineno
     left = self.parse_mod()
     while self.stream.current.type == 'floordiv':
         next(self.stream)
         right = self.parse_mod()
         left = nodes.FloorDiv(left, right, lineno=lineno)
         lineno = self.stream.current.lineno
     return left
 def parse_pow(self):
     lineno = self.stream.current.lineno
     left = self.parse_unary()
     while self.stream.current.type == 'pow':
         next(self.stream)
         right = self.parse_unary()
         left = nodes.Pow(left, right, lineno=lineno)
         lineno = self.stream.current.lineno
     return left
Example #16
0
 def parse_statements(self, end_tokens, drop_needle = False):
     self.stream.skip_if('colon')
     self.stream.expect('block_end')
     result = self.subparse(end_tokens)
     if self.stream.current.type == 'eof':
         self.fail_eof(end_tokens)
     if drop_needle:
         next(self.stream)
     return result
 def parse_mod(self):
     lineno = self.stream.current.lineno
     left = self.parse_pow()
     while self.stream.current.type == 'mod':
         next(self.stream)
         right = self.parse_pow()
         left = nodes.Mod(left, right, lineno=lineno)
         lineno = self.stream.current.lineno
     return left
Example #18
0
 def expect(self, expr):
     if not self.current.test(expr):
         expr = describe_token_expr(expr)
         if self.current.type is TOKEN_EOF:
             raise TemplateSyntaxError('unexpected end of template, expected %r.' % expr, self.current.lineno, self.name, self.filename)
         raise TemplateSyntaxError('expected token %r, got %r' % (expr, describe_token(self.current)), self.current.lineno, self.name, self.filename)
     try:
         return self.current
     finally:
         next(self)
Example #19
0
File: parser.py Project: slide/main
 def parse_unary(self):
     token_type = self.stream.current.type
     lineno = self.stream.current.lineno
     if token_type == "sub":
         next(self.stream)
         node = self.parse_unary()
         return nodes.Neg(node, lineno=lineno)
     if token_type == "add":
         next(self.stream)
         node = self.parse_unary()
         return nodes.Pos(node, lineno=lineno)
     return self.parse_primary()
Example #20
0
    def parse(self, parser):
        lineno = next(parser.stream).lineno
        num_called_num = False
        plural_expr = None
        variables = {}
        while parser.stream.current.type != 'block_end':
            if variables:
                parser.stream.expect('comma')
            if parser.stream.skip_if('colon'):
                break
            name = parser.stream.expect('name')
            if name.value in variables:
                parser.fail('translatable variable %r defined twice.' % name.value, name.lineno, exc=TemplateAssertionError)
            if parser.stream.current.type == 'assign':
                next(parser.stream)
                variables[name.value] = var = parser.parse_expression()
            else:
                variables[name.value] = var = nodes.Name(name.value, 'load')
            if plural_expr is None:
                plural_expr = var
                num_called_num = name.value == 'num'

        parser.stream.expect('block_end')
        plural = plural_names = None
        have_plural = False
        referenced = set()
        singular_names, singular = self._parse_block(parser, True)
        if singular_names:
            referenced.update(singular_names)
            if plural_expr is None:
                plural_expr = nodes.Name(singular_names[0], 'load')
                num_called_num = singular_names[0] == 'num'
        if parser.stream.current.test('name:pluralize'):
            have_plural = True
            next(parser.stream)
            if parser.stream.current.type != 'block_end':
                name = parser.stream.expect('name')
                if name.value not in variables:
                    parser.fail('unknown variable %r for pluralization' % name.value, name.lineno, exc=TemplateAssertionError)
                plural_expr = variables[name.value]
                num_called_num = name.value == 'num'
            parser.stream.expect('block_end')
            plural_names, plural = self._parse_block(parser, False)
            next(parser.stream)
            referenced.update(plural_names)
        else:
            next(parser.stream)
        for var in referenced:
            if var not in variables:
                variables[var] = nodes.Name(var, 'load')

        if not have_plural:
            plural_expr = None
        elif plural_expr is None:
            parser.fail('pluralize without variables', lineno)
        node = self._make_node(singular, plural, variables, plural_expr, bool(referenced), num_called_num and have_plural)
        node.set_lineno(lineno)
        return node
Example #21
0
 def parse_unary(self, with_postfix=True):
     token_type = self.stream.current.type
     lineno = self.stream.current.lineno
     if token_type == 'sub':
         next(self.stream)
         node = nodes.Neg(self.parse_unary(False), lineno=lineno)
     elif token_type == 'add':
         next(self.stream)
         node = nodes.Pos(self.parse_unary(False), lineno=lineno)
     else:
         node = self.parse_primary()
     if with_postfix:
         node = self.parse_postfix(node)
     return node
 def parse_set(self):
     """Parse an assign statement."""
     lineno = next(self.stream).lineno
     target = self.parse_assign_target()
     self.stream.expect('assign')
     expr = self.parse_tuple()
     return nodes.Assign(target, expr, lineno=lineno)
Example #23
0
    def visit_Assign(self, node, frame):
        self.newline(node)
        if frame.toplevel:
            assignment_frame = frame.copy()
            assignment_frame.toplevel_assignments = set()
        else:
            assignment_frame = frame
        self.visit(node.target, assignment_frame)
        self.write(' = ')
        self.visit(node.node, frame)
        if frame.toplevel:
            public_names = [ x for x in assignment_frame.toplevel_assignments if not x.startswith('_') ]
            if len(assignment_frame.toplevel_assignments) == 1:
                name = next(iter(assignment_frame.toplevel_assignments))
                self.writeline('context.vars[%r] = l_%s' % (name, name))
            else:
                self.writeline('context.vars.update({')
                for idx, name in enumerate(assignment_frame.toplevel_assignments):
                    if idx:
                        self.write(', ')
                    self.write('%r: l_%s' % (name, name))

                self.write('})')
            if public_names:
                if len(public_names) == 1:
                    self.writeline('context.exported_vars.add(%r)' % public_names[0])
                else:
                    self.writeline('context.exported_vars.update((%s))' % ', '.join(map(repr, public_names)))
Example #24
0
    def __call__(self, *args, **kwargs):
        arguments = []
        for idx, name in enumerate(self.arguments):
            try:
                value = args[idx]
            except:
                try:
                    value = kwargs.pop(name)
                except:
                    try:
                        value = self.defaults[idx - self._argument_count]
                    except:
                        value = self._environment.undefined("parameter %r was not provided" % name, name=name)
            arguments.append(value)

        # it's important that the order of these arguments does not change
        # if not also changed in the compiler's `function_scoping` method.
        # the order is caller, keyword arguments, positional arguments!
        if self.caller:
            caller = kwargs.pop("caller", None)
            if caller is None:
                caller = self._environment.undefined("No caller defined", name="caller")
            arguments.append(caller)
        if self.catch_kwargs:
            arguments.append(kwargs)
        elif kwargs:
            raise TypeError("macro %r takes no keyword argument %r" % (self.name, next(iter(kwargs))))
        if self.catch_varargs:
            arguments.append(args[self._argument_count :])
        elif len(args) > self._argument_count:
            raise TypeError("macro %r takes not more than %d argument(s)" % (self.name, len(self.arguments)))
        return self._func(*arguments)
 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
Example #26
0
 def look(self):
     """Look at the next token."""
     old_token = next(self)
     result = self.current
     self.push(result)
     self.current = old_token
     return result
Example #27
0
 def parse(self, parser):
     return nodes.Output([self.call_method('_dump', [
         nodes.EnvironmentAttribute('sandboxed'),
         self.attr('ext_attr'),
         nodes.ImportedName(__name__ + '.importable_object'),
         nodes.ContextReference()
     ])]).set_lineno(next(parser.stream).lineno)
Example #28
0
    def __call__(self, *args, **kwargs):
        arguments = list(args[:self._argument_count])
        off = len(arguments)
        if off != self._argument_count:
            for idx, name in enumerate(self.arguments[len(arguments):]):
                try:
                    value = kwargs.pop(name)
                except KeyError:
                    try:
                        value = self.defaults[idx - self._argument_count + off]
                    except IndexError:
                        value = self._environment.undefined('parameter %r was not provided' % name, name=name)

                arguments.append(value)

        if self.caller:
            caller = kwargs.pop('caller', None)
            if caller is None:
                caller = self._environment.undefined('No caller defined', name='caller')
            arguments.append(caller)
        if self.catch_kwargs:
            arguments.append(kwargs)
        elif kwargs:
            raise TypeError('macro %r takes no keyword argument %r' % (self.name, next(iter(kwargs))))
        if self.catch_varargs:
            arguments.append(args[self._argument_count:])
        elif len(args) > self._argument_count:
            raise TypeError('macro %r takes not more than %d argument(s)' % (self.name, len(self.arguments)))
        return self._func(*arguments)
Example #29
0
 def parse(self, parser):
     node = nodes.NamespaceNode(lineno = next(parser.stream).lineno)
     namespace = []
     while not parser.is_tuple_end():
         namespace.append(parser.stream.next().value)
     node.namespace = "".join(namespace)
     return node
 def parse_context():
     if self.stream.current.value in ('with', 'without') and \
        self.stream.look().test('name:context'):
         node.with_context = next(self.stream).value == 'with'
         self.stream.skip()
         return True
     return False
Example #31
0
 def parse_block(self):
     node = nodes.Block(lineno=next(self.stream).lineno)
     node.name = self.stream.expect('name').value
     node.scoped = self.stream.skip_if('name:scoped')
     node.body = self.parse_statements(('name:endblock', ),
                                       drop_needle=True)
     self.stream.skip_if('name:' + node.name)
     return node
Example #32
0
 def parse_import_context(self, node, default):
     if self.stream.current.test_any('name:with', 'name:without') and \
             self.stream.look().test('name:context'):
         node.with_context = next(self.stream).value == 'with'
         self.stream.skip()
     else:
         node.with_context = default
     return node
Example #33
0
 def parse(self, parser):
     node = nodes.ScopedEvalContextModifier(lineno=next(parser.stream).lineno)
     node.options = [
         nodes.Keyword('autoescape', parser.parse_expression())
     ]
     node.body = parser.parse_statements(('name:endautoescape',),
                                         drop_needle=True)
     return nodes.Scope([node])
Example #34
0
    def parse_call(self, node):
        token = self.stream.expect('lparen')
        args = []
        kwargs = []
        dyn_args = dyn_kwargs = None
        require_comma = False

        def ensure(expr):
            if not expr:
                self.fail('invalid syntax for function call expression',
                          token.lineno)

        while self.stream.current.type != 'rparen':
            if require_comma:
                self.stream.expect('comma')
                # support for trailing comma
                if self.stream.current.type == 'rparen':
                    break
            if self.stream.current.type == 'mul':
                ensure(dyn_args is None and dyn_kwargs is None)
                next(self.stream)
                dyn_args = self.parse_expression()
            elif self.stream.current.type == 'pow':
                ensure(dyn_kwargs is None)
                next(self.stream)
                dyn_kwargs = self.parse_expression()
            else:
                ensure(dyn_args is None and dyn_kwargs is None)
                if self.stream.current.type == 'name' and \
                    self.stream.look().type == 'assign':
                    key = self.stream.current.value
                    self.stream.skip(2)
                    value = self.parse_expression()
                    kwargs.append(nodes.Keyword(key, value,
                                                lineno=value.lineno))
                else:
                    ensure(not kwargs)
                    args.append(self.parse_expression())

            require_comma = True
        self.stream.expect('rparen')

        if node is None:
            return args, kwargs, dyn_args, dyn_kwargs
        return nodes.Call(node, args, kwargs, dyn_args, dyn_kwargs,
                          lineno=token.lineno)
Example #35
0
 def parse_context():
     if self.stream.current.value in (
             'with',
             'without') and self.stream.look().test('name:context'):
         node.with_context = next(self.stream).value == 'with'
         self.stream.skip()
         return True
     return False
Example #36
0
 def parse_print(self):
     node = nodes.Output(lineno=next(self.stream).lineno)
     node.nodes = []
     while self.stream.current.type != 'block_end':
         if node.nodes:
             self.stream.expect('comma')
         node.nodes.append(self.parse_expression())
     return node
Example #37
0
 def parse_statements(self, end_tokens, drop_needle=False):
     """Parse multiple statements into a list until one of the end tokens
     is reached.  This is used to parse the body of statements as it also
     parses template data if appropriate.  The parser checks first if the
     current token is a colon and skips it if there is one.  Then it checks
     for the block end and parses until if one of the `end_tokens` is
     reached.  Per default the active token in the stream at the end of
     the call is the matched end token.  If this is not wanted `drop_needle`
     can be set to `True` and the end token is removed.
     """
     self.stream.skip_if('colon')
     self.stream.expect('block_end')
     result = self.subparse(end_tokens)
     if self.stream.current.type == 'eof':
         self.fail_eof(end_tokens)
     if drop_needle:
         next(self.stream)
     return result
Example #38
0
 def parse(self, parser):
     return nodes.Output([
         self.call_method('_dump', [
             nodes.EnvironmentAttribute('sandboxed'),
             self.attr('ext_attr'),
             nodes.ImportedName(__name__ + '.importable_object'),
             nodes.ContextReference()
         ])
     ]).set_lineno(next(parser.stream).lineno)
Example #39
0
 def expect(self, expr):
     """Expect a given token type and return it.  This accepts the same
     argument as :meth:`jinja2.lexer.Token.test`.
     """
     if not self.current.test(expr):
         expr = describe_token_expr(expr)
         if self.current.type is TOKEN_EOF:
             raise TemplateSyntaxError(
                 'unexpected end of template, expected %r.' % expr,
                 self.current.lineno, self.name, self.filename)
         raise TemplateSyntaxError(
             'expected token %r, got %r' %
             (expr, describe_token(self.current)), self.current.lineno,
             self.name, self.filename)
     try:
         return self.current
     finally:
         next(self)
def inject_toc(app, doctree, docname):
    titleiter = iter(doctree.traverse(nodes.title))
    try:
        # skip first title, we are not interested in that one
        next(titleiter)
        title = next(titleiter)
        # and check if there is at least another title
        next(titleiter)
    except StopIteration:
        return
    tocnode = nodes.section('')
    tocnode['classes'].append('toc')
    toctitle = nodes.section('')
    toctitle['classes'].append('toctitle')
    toctitle.append(nodes.title(text='Table Of Contents'))
    tocnode.append(toctitle)
    tocnode += doctree.document.settings.env.get_toc_for(docname)[0][1]
    title.parent.insert(title.parent.children.index(title), tocnode)
Example #41
0
 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)
Example #42
0
 def expect(self, expr):
     """Expect a given token type and return it.  This accepts the same
     argument as :meth:`jinja2.lexer.Token.test`.
     """
     if not self.current.test(expr):
         if ':' in expr:
             expr = expr.split(':')[1]
         if self.current.type is TOKEN_EOF:
             raise TemplateSyntaxError(
                 'unexpected end of template, '
                 'expected %r.' % expr, self.current.lineno, self.name,
                 self.filename)
         raise TemplateSyntaxError(
             "expected token %r, got %r" % (expr, str(self.current)),
             self.current.lineno, self.name, self.filename)
     try:
         return self.current
     finally:
         next(self)
Example #43
0
 def parse_filter(self, node, start_inline=False):
     while self.stream.current.type == 'pipe' or start_inline:
         if not start_inline:
             next(self.stream)
         token = self.stream.expect('name')
         name = token.value
         while self.stream.current.type == 'dot':
             next(self.stream)
             name += '.' + self.stream.expect('name').value
         if self.stream.current.type == 'lparen':
             args, kwargs, dyn_args, dyn_kwargs = self.parse_call(None)
         else:
             args = []
             kwargs = []
             dyn_args = dyn_kwargs = None
         node = nodes.Filter(node, name, args, kwargs, dyn_args,
                             dyn_kwargs, lineno=token.lineno)
         start_inline = False
     return node
Example #44
0
 def parse_compare(self):
     lineno = self.stream.current.lineno
     expr = self.parse_add()
     ops = []
     while 1:
         token_type = self.stream.current.type
         if token_type in _compare_operators:
             next(self.stream)
             ops.append(nodes.Operand(token_type, self.parse_add()))
         elif self.stream.skip_if('name:in'):
             ops.append(nodes.Operand('in', self.parse_add()))
         elif self.stream.current.test('name:not') and \
              self.stream.look().test('name:in'):
             self.stream.skip(2)
             ops.append(nodes.Operand('notin', self.parse_add()))
         else:
             break
         lineno = self.stream.current.lineno
     if not ops:
         return expr
     return nodes.Compare(expr, ops, lineno=lineno)
Example #45
0
 def parse_call_block(self):
     node = nodes.CallBlock(lineno=next(self.stream).lineno)
     if self.stream.current.type == 'lparen':
         self.parse_signature(node)
     else:
         node.args = []
         node.defaults = []
     node.call = self.parse_expression()
     if not isinstance(node.call, nodes.Call):
         self.fail('expected call', node.lineno)
     node.body = self.parse_statements(('name:endcall', ), drop_needle=True)
     return node
Example #46
0
 def parse_block(self):
     node = nodes.Block(lineno=next(self.stream).lineno)
     node.name = self.stream.expect('name').value
     node.scoped = self.stream.skip_if('name:scoped')
     if self.stream.current.type == 'sub':
         self.fail(
             'Block names in Jinja have to be valid Python identifiers and may not contain hyphens, use an underscore instead.'
         )
     node.body = self.parse_statements(('name:endblock', ),
                                       drop_needle=True)
     self.stream.skip_if('name:' + node.name)
     return node
Example #47
0
    def parse_statements(self, end_tokens, drop_needle=False):
        """Parse multiple statements into a list until one of the end tokens
        is reached.  This is used to parse the body of statements as it also
        parses template data if appropriate.  The parser checks first if the
        current token is a colon and skips it if there is one.  Then it checks
        for the block end and parses until if one of the `end_tokens` is
        reached.  Per default the active token in the stream at the end of
        the call is the matched end token.  If this is not wanted `drop_needle`
        can be set to `True` and the end token is removed.
        """
        # the first token may be a colon for python compatibility
        self.stream.skip_if('colon')

        # in the future it would be possible to add whole code sections
        # by adding some sort of end of statement token and parsing those here.
        self.stream.expect('block_end')
        result = self.subparse(end_tokens)

        if drop_needle:
            next(self.stream)
        return result
Example #48
0
    def _parse_block(self, parser, allow_pluralize):
        referenced = []
        buf = []
        while 1:
            if parser.stream.current.type == 'data':
                buf.append(parser.stream.current.value.replace('%', '%%'))
                next(parser.stream)
            elif parser.stream.current.type == 'variable_begin':
                next(parser.stream)
                name = parser.stream.expect('name').value
                referenced.append(name)
                buf.append('%%(%s)s' % name)
                parser.stream.expect('variable_end')
            elif parser.stream.current.type == 'block_begin':
                next(parser.stream)
                if parser.stream.current.test('name:endtrans'):
                    break
                elif parser.stream.current.test('name:pluralize'):
                    if allow_pluralize:
                        break
                    parser.fail(
                        'a translatable section can have only one pluralize section'
                    )
                parser.fail(
                    'control structures in translatable sections are not allowed'
                )
            elif parser.stream.eos:
                parser.fail('unclosed translation block')

        return (referenced, concat(buf))
Example #49
0
    def _parse_block(self, parser, allow_pluralize):
        """Parse until the next block tag with a given name."""
        referenced = []
        buf = []
        while 1:
            if parser.stream.current.type == 'data':
                buf.append(parser.stream.current.value.replace('%', '%%'))
                next(parser.stream)
            elif parser.stream.current.type == 'variable_begin':
                next(parser.stream)
                name = parser.stream.expect('name').value
                referenced.append(name)
                buf.append('%%(%s)s' % name)
                parser.stream.expect('variable_end')
            elif parser.stream.current.type == 'block_begin':
                next(parser.stream)
                if parser.stream.current.test('name:endtrans'):
                    break
                elif parser.stream.current.test('name:pluralize'):
                    if allow_pluralize:
                        break
                    parser.fail('a translatable section can have only one '
                                'pluralize section')
                parser.fail('control structures in translatable sections are '
                            'not allowed')
            elif parser.stream.eos:
                parser.fail('unclosed translation block')
            else:
                assert False, 'internal parser error'

        return referenced, concat(buf)
Example #50
0
    def parse_subscribed(self):
        lineno = self.stream.current.lineno

        if self.stream.current.type == 'colon':
            next(self.stream)
            args = [None]
        else:
            node = self.parse_expression()
            if self.stream.current.type != 'colon':
                return node
            next(self.stream)
            args = [node]

        if self.stream.current.type == 'colon':
            args.append(None)
        elif self.stream.current.type not in ('rbracket', 'comma'):
            args.append(self.parse_expression())
        else:
            args.append(None)

        if self.stream.current.type == 'colon':
            next(self.stream)
            if self.stream.current.type not in ('rbracket', 'comma'):
                args.append(self.parse_expression())
            else:
                args.append(None)
        else:
            args.append(None)

        return nodes.Slice(lineno=lineno, *args)
Example #51
0
 def parse(self, parser):
     node = nodes.Scope(lineno=next(parser.stream).lineno)
     assignments = []
     while parser.stream.current.type != 'block_end':
         lineno = parser.stream.current.lineno
         if assignments:
             parser.stream.expect('comma')
         target = parser.parse_assign_target()
         parser.stream.expect('assign')
         expr = parser.parse_expression()
         assignments.append(nodes.Assign(target, expr, lineno=lineno))
     node.body = assignments + \
         list(parser.parse_statements(('name:endwith',),
                                      drop_needle=True))
     return node
Example #52
0
    def parse_block(self):
        node = nodes.Block(lineno=next(self.stream).lineno)
        node.name = self.stream.expect('name').value
        node.scoped = self.stream.skip_if('name:scoped')

        # common problem people encounter when switching from django
        # to jinja.  we do not support hyphens in block names, so let's
        # raise a nicer error message in that case.
        if self.stream.current.type == 'sub':
            self.fail('Block names in Jinja have to be valid Python '
                      'identifiers and may not contain hypens, use an '
                      'underscore instead.')

        node.body = self.parse_statements(('name:endblock',), drop_needle=True)
        self.stream.skip_if('name:' + node.name)
        return node
Example #53
0
 def parse_for(self):
     """Parse a for loop."""
     lineno = self.stream.expect('name:for').lineno
     target = self.parse_assign_target(extra_end_rules=('name:in',))
     self.stream.expect('name:in')
     iter = self.parse_tuple(with_condexpr=False,
                             extra_end_rules=('name:recursive',))
     test = None
     if self.stream.skip_if('name:if'):
         test = self.parse_expression()
     recursive = self.stream.skip_if('name:recursive')
     body = self.parse_statements(('name:endfor', 'name:else'))
     if next(self.stream).value == 'endfor':
         else_ = []
     else:
         else_ = self.parse_statements(('name:endfor',), drop_needle=True)
     return nodes.For(target, iter, body, else_, test,
                      recursive, lineno=lineno)
Example #54
0
 def parse_if(self):
     """Parse an if construct."""
     node = result = nodes.If(lineno=self.stream.expect('name:if').lineno)
     while 1:
         node.test = self.parse_tuple(with_condexpr=False)
         node.body = self.parse_statements(('name:elif', 'name:else',
                                            'name:endif'))
         token = next(self.stream)
         if token.test('name:elif'):
             new_node = nodes.If(lineno=self.stream.current.lineno)
             node.else_ = [new_node]
             node = new_node
             continue
         elif token.test('name:else'):
             node.else_ = self.parse_statements(('name:endif',),
                                                drop_needle=True)
         else:
             node.else_ = []
         break
     return result
Example #55
0
    def parse_from(self):
        node = nodes.FromImport(lineno=next(self.stream).lineno)
        node.template = self.parse_expression()
        self.stream.expect('name:import')
        node.names = []

        def parse_context():
            if self.stream.current.value in (
                    'with',
                    'without') and self.stream.look().test('name:context'):
                node.with_context = next(self.stream).value == 'with'
                self.stream.skip()
                return True
            return False

        while 1:
            if node.names:
                self.stream.expect('comma')
            if self.stream.current.type == 'name':
                if parse_context():
                    break
                target = self.parse_assign_target(name_only=True)
                if target.name.startswith('_'):
                    self.fail(
                        'names starting with an underline can not be imported',
                        target.lineno,
                        exc=TemplateAssertionError)
                if self.stream.skip_if('name:as'):
                    alias = self.parse_assign_target(name_only=True)
                    node.names.append((target.name, alias.name))
                else:
                    node.names.append(target.name)
                if parse_context() or self.stream.current.type != 'comma':
                    break
            else:
                break

        if not hasattr(node, 'with_context'):
            node.with_context = False
            self.stream.skip_if('comma')
        return node
Example #56
0
    def subparse(self, end_tokens=None):
        body = []
        data_buffer = []
        add_data = data_buffer.append

        if end_tokens is not None:
            self._end_token_stack.append(end_tokens)

        def flush_data():
            if data_buffer:
                lineno = data_buffer[0].lineno
                body.append(nodes.Output(data_buffer[:], lineno=lineno))
                del data_buffer[:]

        try:
            while self.stream:
                token = self.stream.current
                if token.type == 'data':
                    if token.value:
                        add_data(
                            nodes.TemplateData(token.value,
                                               lineno=token.lineno))
                    next(self.stream)
                elif token.type == 'variable_begin':
                    next(self.stream)
                    add_data(self.parse_tuple(with_condexpr=True))
                    self.stream.expect('variable_end')
                elif token.type == 'block_begin':
                    flush_data()
                    next(self.stream)
                    if end_tokens is not None and \
                       self.stream.current.test_any(*end_tokens):
                        return body
                    rv = self.parse_statement()
                    if isinstance(rv, list):
                        body.extend(rv)
                    else:
                        body.append(rv)
                    self.stream.expect('block_end')
                else:
                    raise AssertionError('internal parsing error')

            flush_data()
        finally:
            if end_tokens is not None:
                self._end_token_stack.pop()

        return body
Example #57
0
    def __call__(self, *args, **kwargs):
        # try to consume the positional arguments
        arguments = list(args[:self._argument_count])
        off = len(arguments)

        # if the number of arguments consumed is not the number of
        # arguments expected we start filling in keyword arguments
        # and defaults.
        if off != self._argument_count:
            for idx, name in enumerate(self.arguments[len(arguments):]):
                try:
                    value = kwargs.pop(name)
                except KeyError:
                    try:
                        value = self.defaults[idx - self._argument_count + off]
                    except IndexError:
                        value = self._environment.undefined(
                            'parameter %r was not provided' % name, name=name)
                arguments.append(value)

        # it's important that the order of these arguments does not change
        # if not also changed in the compiler's `function_scoping` method.
        # the order is caller, keyword arguments, positional arguments!
        if self.caller:
            caller = kwargs.pop('caller', None)
            if caller is None:
                caller = self._environment.undefined('No caller defined',
                                                     name='caller')
            arguments.append(caller)
        if self.catch_kwargs:
            arguments.append(kwargs)
        elif kwargs:
            raise TypeError('macro %r takes no keyword argument %r' %
                            (self.name, next(iter(kwargs))))
        if self.catch_varargs:
            arguments.append(args[self._argument_count:])
        elif len(args) > self._argument_count:
            raise TypeError('macro %r takes not more than %d argument(s)' %
                            (self.name, len(self.arguments)))
        return self._func(*arguments)
Example #58
0
    def __call__(self, *args, **kwargs):
        arguments = []
        for idx, name in enumerate(self.arguments):
            try:
                value = args[idx]
            except:
                try:
                    value = kwargs.pop(name)
                except:
                    try:
                        value = self.defaults[idx - self._argument_count]
                    except:
                        value = self._environment.undefined(
                            'parameter %r was not provided' % name, name=name)
            arguments.append(value)

        # it's important that the order of these arguments does not change
        # if not also changed in the compiler's `function_scoping` method.
        # the order is caller, keyword arguments, positional arguments!
        if self.caller:
            caller = kwargs.pop('caller', None)
            if caller is None:
                caller = self._environment.undefined('No caller defined',
                                                     name='caller')
            arguments.append(caller)
        if self.catch_kwargs:
            arguments.append(kwargs)
        elif kwargs:
            raise TypeError('macro %r takes no keyword argument %r' %
                            (self.name, next(iter(kwargs))))
        if self.catch_varargs:
            arguments.append(args[self._argument_count:])
        elif len(args) > self._argument_count:
            raise TypeError('macro %r takes not more than %d argument(s)' %
                            (self.name, len(self.arguments)))
        return self._func(*arguments)
Example #59
0
 def parse(self, parser):
     token = next(parser.stream)
     if token.value == 'break':
         return nodes.Break(lineno=token.lineno)
     return nodes.Continue(lineno=token.lineno)
Example #60
0
 def parse(self, parser):
     node = nodes.ExprStmt(lineno=next(parser.stream).lineno)
     node.node = parser.parse_tuple()
     return node