autoescape no longer is a plain boolean value but can also be a function
to enable or disable autoescaping for certain filenames (or file
extensions for that matter)
--HG--
branch : trunk
diff --git a/jinja2/compiler.py b/jinja2/compiler.py
index 2952b66..117bd8c 100644
--- a/jinja2/compiler.py
+++ b/jinja2/compiler.py
@@ -761,7 +761,7 @@
def visit_Template(self, node, frame=None):
assert frame is None, 'no root frame allowed'
- eval_ctx = EvalContext(self.environment)
+ eval_ctx = EvalContext(self.environment, self.name)
from jinja2.runtime import __all__ as exported
self.writeline('from __future__ import division')
diff --git a/jinja2/environment.py b/jinja2/environment.py
index a250185..25cec88 100644
--- a/jinja2/environment.py
+++ b/jinja2/environment.py
@@ -160,7 +160,13 @@
`autoescape`
If set to true the XML/HTML autoescaping feature is enabled by
default. For more details about auto escaping see
- :class:`~jinja2.utils.Markup`.
+ :class:`~jinja2.utils.Markup`. As of Jinja 2.4 this can also
+ be a callable that is passed the template name and has to
+ return `True` or `False` depending on autoescape should be
+ enabled by default.
+
+ .. versionchanged:: 2.4
+ `autoescape` can now be a function
`loader`
The template loader for this environment.
diff --git a/jinja2/nodes.py b/jinja2/nodes.py
index 15461e8..b6696c7 100644
--- a/jinja2/nodes.py
+++ b/jinja2/nodes.py
@@ -72,8 +72,11 @@
to it in extensions.
"""
- def __init__(self, environment):
- self.autoescape = environment.autoescape
+ def __init__(self, environment, template_name=None):
+ if callable(environment.autoescape):
+ self.autoescape = environment.autoescape(template_name)
+ else:
+ self.autoescape = environment.autoescape
self.volatile = False
def save(self):
diff --git a/jinja2/runtime.py b/jinja2/runtime.py
index 318e654..fef7b25 100644
--- a/jinja2/runtime.py
+++ b/jinja2/runtime.py
@@ -77,7 +77,7 @@
def __getitem__(self, name):
blocks = self.__context.blocks[name]
- wrap = self.__context.environment.autoescape and \
+ wrap = self.__context.eval_ctx.autoescape and \
Markup or (lambda x: x)
return BlockReference(name, self.__context, blocks, 0)
@@ -114,7 +114,7 @@
self.parent = parent
self.vars = {}
self.environment = environment
- self.eval_ctx = EvalContext(self.environment)
+ self.eval_ctx = EvalContext(self.environment, name)
self.exported_vars = set()
self.name = name
@@ -257,7 +257,7 @@
@internalcode
def __call__(self):
rv = concat(self._stack[self._depth](self._context))
- if self._context.environment.autoescape:
+ if self._context.eval_ctx.autoescape:
rv = Markup(rv)
return rv
diff --git a/jinja2/testsuite/api.py b/jinja2/testsuite/api.py
index 194e9a1..4b49819 100644
--- a/jinja2/testsuite/api.py
+++ b/jinja2/testsuite/api.py
@@ -17,7 +17,7 @@
from jinja2 import Environment, Undefined, DebugUndefined, \
StrictUndefined, UndefinedError, Template, meta, \
- is_undefined, Template
+ is_undefined, Template, DictLoader
from jinja2.utils import Cycler
env = Environment()
@@ -76,6 +76,23 @@
assert env.get_or_select_template([t]) is t
assert env.get_or_select_template(t) is t
+ def test_autoescape_autoselect(self):
+ def select_autoescape(name):
+ if name is None or '.' not in name:
+ return False
+ return name.endswith('.html')
+ env = Environment(autoescape=select_autoescape,
+ loader=DictLoader({
+ 'test.txt': '{{ foo }}',
+ 'test.html': '{{ foo }}'
+ }))
+ t = env.get_template('test.txt')
+ assert t.render(foo='<foo>') == '<foo>'
+ t = env.get_template('test.html')
+ assert t.render(foo='<foo>') == '<foo>'
+ t = env.from_string('{{ foo }}')
+ assert t.render(foo='<foo>') == '<foo>'
+
class MetaTestCase(JinjaTestCase):