From d6c016ba777aae9ac7f15afe3fabe9a54367fcde Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Mon, 29 Jan 2018 15:44:46 -0800 Subject: [PATCH] More closely match python splatting for calls In Python, it's legal to use splats in function calls like this: call_function('123', *b, c=5, **d) Prior to this change, jinja2 did not allow that. It mandated that all splatting had to take place at the end of the call: call_function('123', c=5, *b, **d) This commit allows both orders. Additionally, this commit adds tests for more things that are illegal: namely giving a function a positional argument after using a splat to unpack positional arguments or giving a function a named argument after using a double splat to unpack keyword arguments. --- jinja2/parser.py | 6 ++++-- tests/test_lexnparse.py | 9 +++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/jinja2/parser.py b/jinja2/parser.py index ed00d970..59be0730 100644 --- a/jinja2/parser.py +++ b/jinja2/parser.py @@ -777,16 +777,18 @@ class Parser(object): 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': + # Parsing a kwarg + ensure(dyn_kwargs is None) 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) + # Parsing an arg + ensure(dyn_args is None and dyn_kwargs is None and not kwargs) args.append(self.parse_expression()) require_comma = True diff --git a/tests/test_lexnparse.py b/tests/test_lexnparse.py index 7da72c0b..9326cb92 100644 --- a/tests/test_lexnparse.py +++ b/tests/test_lexnparse.py @@ -361,14 +361,19 @@ class TestSyntax(object): tests = [ (True, '*foo, bar'), (True, '*foo, *bar'), - (True, '*foo, bar=42'), (True, '**foo, *bar'), (True, '**foo, bar'), + (True, '**foo, **bar'), + (True, '**foo, bar=42'), (False, 'foo, bar'), (False, 'foo, bar=42'), (False, 'foo, bar=23, *args'), + (False, 'foo, *args, bar=23'), (False, 'a, b=c, *d, **e'), - (False, '*foo, **bar') + (False, '*foo, bar=42'), + (False, '*foo, **bar'), + (False, '*foo, bar=42, **baz'), + (False, 'foo, *args, bar=23, **baz'), ] for should_fail, sig in tests: if should_fail: -- 2.47.2