| Index: third_party/jinja2/parser.py
|
| diff --git a/third_party/jinja2/parser.py b/third_party/jinja2/parser.py
|
| index f60cd018c51fff457dfaea5283b78267a4a0eefd..d24da180ea61aed5aca443cf641658a068a9064c 100644
|
| --- a/third_party/jinja2/parser.py
|
| +++ b/third_party/jinja2/parser.py
|
| @@ -11,10 +11,9 @@
|
| from jinja2 import nodes
|
| from jinja2.exceptions import TemplateSyntaxError, TemplateAssertionError
|
| from jinja2.lexer import describe_token, describe_token_expr
|
| -from jinja2._compat import next, imap
|
| +from jinja2._compat import imap
|
|
|
|
|
| -#: statements that callinto
|
| _statement_keywords = frozenset(['for', 'if', 'block', 'extends', 'print',
|
| 'macro', 'include', 'from', 'import',
|
| 'set'])
|
| @@ -169,9 +168,12 @@ class Parser(object):
|
| """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)
|
| + if self.stream.skip_if('assign'):
|
| + expr = self.parse_tuple()
|
| + return nodes.Assign(target, expr, lineno=lineno)
|
| + body = self.parse_statements(('name:endset',),
|
| + drop_needle=True)
|
| + return nodes.AssignBlock(target, body, lineno=lineno)
|
|
|
| def parse_for(self):
|
| """Parse a for loop."""
|
| @@ -312,6 +314,8 @@ class Parser(object):
|
| arg.set_ctx('param')
|
| if self.stream.skip_if('assign'):
|
| defaults.append(self.parse_expression())
|
| + elif defaults:
|
| + self.fail('non-default argument follows default argument')
|
| args.append(arg)
|
| self.stream.expect('rparen')
|
|
|
| @@ -434,8 +438,8 @@ class Parser(object):
|
| 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'):
|
| + 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:
|
| @@ -771,7 +775,7 @@ class Parser(object):
|
| else:
|
| ensure(dyn_args is None and dyn_kwargs is None)
|
| if self.stream.current.type == 'name' and \
|
| - self.stream.look().type == 'assign':
|
| + self.stream.look().type == 'assign':
|
| key = self.stream.current.value
|
| self.stream.skip(2)
|
| value = self.parse_expression()
|
| @@ -824,11 +828,11 @@ class Parser(object):
|
| 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'):
|
| + 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()]
|
|
|