]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Disallow f(x, y=1, z) and similar nonsense 405/head
authorThiefMaster <adrian@planetcoding.net>
Thu, 5 Feb 2015 23:34:36 +0000 (00:34 +0100)
committerThiefMAster <adrian@planetcoding.net>
Fri, 6 Feb 2015 17:18:07 +0000 (18:18 +0100)
Python rejects such function definitions because it doesn't make much
sense to have arguments with no default values after arguments with
default values.

Jinja did allow them, but handled them improperly (associating the
default value with the wrong argument).

Due to how broken the current behavior is, it makes more sense to reject
templates containing such defintions instead of trying to handle them
properly. Both cases are going to break existing code containing such
definitions, but besides the fact that possibly no such code exists it
is better to fail with a clear error than to silently change the values
of arguments.

This fixes #364

CHANGES
jinja2/parser.py
jinja2/testsuite/core_tags.py

diff --git a/CHANGES b/CHANGES
index ffe0a925d781b546b359f605150d5db011aecc68..eaa6e6bf73d23658dada2daeeb62cafe1974d447 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -21,6 +21,10 @@ Version 2.8
 - Implemented a block ``set`` tag.
 - Default cache size was incrased to 400 from a low 50.
 - Fixed ``is number`` test to accept long integers in all Python versions.
+- Added a check for default arguments followed by non-default arguments. This
+  change makes ``{% macro m(x, y=1, z) %}...{% endmacro %}`` a syntax error. The
+  previous behavior for this code was broken anyway (resulting in the default
+  value being applied to `y`).
 
 Version 2.7.3
 -------------
index 2cf2bd2055d511b687a076ed7423326d8f02cc95..d24da180ea61aed5aca443cf641658a068a9064c 100644 (file)
@@ -314,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')
 
index ac0eb4cb2564e91e1176a58d8e46b9ca5863a67f..e1cff3bfcc9554b4f273ac3bf212060648ce854f 100644 (file)
@@ -244,6 +244,15 @@ class MacrosTestCase(JinjaTestCase):
 {{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
         assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
 
+    def test_arguments_defaults_nonsense(self):
+        self.assert_raises(TemplateSyntaxError, self.env.from_string, '''\
+{% macro m(a, b=1, c) %}a={{ a }}, b={{ b }}, c={{ c }}{% endmacro %}''')
+
+    def test_caller_defaults_nonsense(self):
+        self.assert_raises(TemplateSyntaxError, self.env.from_string, '''\
+{% macro a() %}{{ caller() }}{% endmacro %}
+{% call(x, y=1, z) a() %}{% endcall %}''')
+
     def test_varargs(self):
         tmpl = self.env.from_string('''\
 {% macro test() %}{{ varargs|join('|') }}{% endmacro %}\