summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Brown <kevin@kevin-brown.com>2020-05-16 15:55:56 -0400
committerKevin Brown <kevin@kevin-brown.com>2020-05-16 17:08:09 -0400
commita3aa821a5f3b3cffd7a166ead8794279d8cc645c (patch)
treecc251ff998071fcf68b73963c53f96c41013c097
parent140297e5473b217bda3ee2ff5027bff65fab8982 (diff)
downloadjinja2-a3aa821a5f3b3cffd7a166ead8794279d8cc645c.tar.gz
Add proper parsing for {% for %} parameters
Previously a lot of the parsing was done through implicit variable tuples, but that ended up causing a lot of special cases because we were only allowing variables in those tuples. Now that we are going to move towards having tuples be handled consitently, whether they are identifier tuples or tuple literals, the logic for handling the `{% for %}` block needed to be cleaned up.
-rw-r--r--src/jinja2/new_parser.py88
1 files changed, 62 insertions, 26 deletions
diff --git a/src/jinja2/new_parser.py b/src/jinja2/new_parser.py
index ea1117b..6d0fb90 100644
--- a/src/jinja2/new_parser.py
+++ b/src/jinja2/new_parser.py
@@ -233,7 +233,6 @@ def parse_block_filter(ast):
)
def parse_block_for(ast):
- target = None
iter = None
body = ast['contents']
else_ = []
@@ -242,39 +241,76 @@ def parse_block_for(ast):
block_parameters = ast['start']['parameters']
- if block_parameters[0]['value']['operator'] == 'in':
- block_parameters[0:1] = [
- {
- "value": block_parameters[0]['value']['left']
- },
- {
- "value": {
- "variable": "in"
- }
- },
- {
- "value": block_parameters[0]['value']['right']
- },
- ]
+ target = []
+ for param_number, param in enumerate(block_parameters):
+ if param['value']['variable'] == 'in':
+ break
+
+ if param['value']['operator'] == 'in':
+ block_parameters[param_number:param_number + 1] = [
+ {
+ "value": param['value']['left']
+ },
+ {
+ "value": {
+ "variable": "in"
+ }
+ },
+ {
+ "value": param['value']['right']
+ },
+ ]
+
+ target.append(
+ parse_variable(
+ param['value']['left'],
+ variable_context='store'
+ )
+ )
- if block_parameters[1]['value']['variable'] != 'in':
- raise
+ break
- target = parse_variable(block_parameters[0]['value'], variable_context='store')
- iter = parse_variable(block_parameters[2]['value'])
+ target.append(parse_variable(param['value'], variable_context='store'))
+
+ if len(target) == 0:
+ raise TemplateSyntaxError(
+ "expected token 'in'",
+ lineno=lineno_from_parseinfo(ast['start']['parseinfo'])
+ )
- if not isinstance(target, (nodes.Name, nodes.Tuple)):
+ if len(target) == len(block_parameters):
raise TemplateSyntaxError(
"expected token 'in'",
- lineno=target.lineno
+ lineno=target[1].lineno
)
- if len(block_parameters) > 3:
- if block_parameters[3]['value']['variable'] == 'if':
- test = parse_conditional_expression(block_parameters[4]['value'])
+ if len(target) == 1:
+ target = target[0]
+ else:
+ target = nodes.Tuple(
+ target,
+ 'store',
+ lineno=target[0].lineno
+ )
+ param_number += 2
+
+ iter = parse_variable(block_parameters[param_number]['value'])
+ param_number += 1
+
+ if len(block_parameters) > param_number + 1:
+ if block_parameters[param_number]['value']['variable'] == 'if':
+ param_number += 1
+
+ test = parse_conditional_expression(
+ block_parameters[param_number]['value']
+ )
+ param_number += 1
+
+ if len(block_parameters) > param_number + 2:
+ raise
- if len(block_parameters) > 3:
- recursive = block_parameters[-1]['value']['variable'] == 'recursive'
+ if len(block_parameters) == param_number + 1:
+ recursive = block_parameters[param_number]['value']['variable'] == 'recursive'
else_ = _split_contents_at_block(ast['contents'], 'else')