From: Kevin Brown Date: Sat, 16 May 2020 19:55:56 +0000 (-0400) Subject: Add proper parsing for {% for %} parameters X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a3aa821a5f3b3cffd7a166ead8794279d8cc645c;p=thirdparty%2Fjinja.git 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. --- diff --git a/src/jinja2/new_parser.py b/src/jinja2/new_parser.py index ea1117bf..6d0fb901 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')