]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Add proper parsing for {% for %} parameters
authorKevin Brown <kevin@kevin-brown.com>
Sat, 16 May 2020 19:55:56 +0000 (15:55 -0400)
committerKevin Brown <kevin@kevin-brown.com>
Sat, 16 May 2020 21:08:09 +0000 (17:08 -0400)
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.

src/jinja2/new_parser.py

index ea1117bf868133ac6d4525e29d2952a0be2d6fc4..6d0fb901a80b5122513c63588b7c13c7877ee56a 100644 (file)
@@ -233,7 +233,6 @@ def parse_block_filter(ast):
     )\r
 \r
 def parse_block_for(ast):\r
-    target = None\r
     iter = None\r
     body = ast['contents']\r
     else_ = []\r
@@ -242,39 +241,76 @@ def parse_block_for(ast):
 \r
     block_parameters = ast['start']['parameters']\r
 \r
-    if block_parameters[0]['value']['operator'] == 'in':\r
-        block_parameters[0:1] = [\r
-            {\r
-                "value": block_parameters[0]['value']['left']\r
-            },\r
-            {\r
-                "value": {\r
-                    "variable": "in"\r
-                }\r
-            },\r
-            {\r
-                "value": block_parameters[0]['value']['right']\r
-            },\r
-        ]\r
+    target = []\r
+    for param_number, param in enumerate(block_parameters):\r
+        if param['value']['variable'] == 'in':\r
+            break\r
+\r
+        if param['value']['operator'] == 'in':\r
+            block_parameters[param_number:param_number + 1] = [\r
+                {\r
+                    "value": param['value']['left']\r
+                },\r
+                {\r
+                    "value": {\r
+                        "variable": "in"\r
+                    }\r
+                },\r
+                {\r
+                    "value": param['value']['right']\r
+                },\r
+            ]\r
+\r
+            target.append(\r
+                parse_variable(\r
+                    param['value']['left'],\r
+                    variable_context='store'\r
+                )\r
+            )\r
 \r
-    if block_parameters[1]['value']['variable'] != 'in':\r
-        raise\r
+            break\r
 \r
-    target = parse_variable(block_parameters[0]['value'], variable_context='store')\r
-    iter = parse_variable(block_parameters[2]['value'])\r
+        target.append(parse_variable(param['value'], variable_context='store'))\r
+\r
+    if len(target) == 0:\r
+        raise TemplateSyntaxError(\r
+            "expected token 'in'",\r
+            lineno=lineno_from_parseinfo(ast['start']['parseinfo'])\r
+        )\r
 \r
-    if not isinstance(target, (nodes.Name, nodes.Tuple)):\r
+    if len(target) == len(block_parameters):\r
         raise TemplateSyntaxError(\r
             "expected token 'in'",\r
-            lineno=target.lineno\r
+            lineno=target[1].lineno\r
         )\r
 \r
-    if len(block_parameters) > 3:\r
-        if block_parameters[3]['value']['variable'] == 'if':\r
-            test = parse_conditional_expression(block_parameters[4]['value'])\r
+    if len(target) == 1:\r
+        target = target[0]\r
+    else:\r
+        target = nodes.Tuple(\r
+            target,\r
+            'store',\r
+            lineno=target[0].lineno\r
+        )\r
+    param_number += 2\r
+\r
+    iter = parse_variable(block_parameters[param_number]['value'])\r
+    param_number += 1\r
+\r
+    if len(block_parameters) > param_number + 1:\r
+        if block_parameters[param_number]['value']['variable'] == 'if':\r
+            param_number += 1\r
+\r
+            test = parse_conditional_expression(\r
+                block_parameters[param_number]['value']\r
+            )\r
+            param_number += 1\r
+\r
+    if len(block_parameters) > param_number + 2:\r
+        raise\r
 \r
-    if len(block_parameters) > 3:\r
-        recursive = block_parameters[-1]['value']['variable'] == 'recursive'\r
+    if len(block_parameters) == param_number + 1:\r
+        recursive = block_parameters[param_number]['value']['variable'] == 'recursive'\r
 \r
     else_ = _split_contents_at_block(ast['contents'], 'else')\r
 \r