the basic use cases. The `Undefined` object in that module exists for
backwards compatibility and is an alias for `SilentUndefined`.
+To create your own undefined singleton do something like this:
+
+.. sourcecode:: jinja
+
+ from jinja.datastructure import AbstractUndefinedType, make_undefined
+
+ class MyUndefinedType(AbstractUndefindedType):
+ __slots__ = ()
+
+ def __iter__(self):
+ return iter(int, 0)
+
+ def __reduce__(self):
+ return 'MyUndefined'
+
+ MyUndefined = make_undefined(MyUndefinedType)
+
+The only thing you have to do is to override `__reduce__` so that it returns
+the name of the singleton instance and create the instance using
+`make_undefined`. Everything else is up to you. Note that currently attributes
+on undefined objects are available in the Jinja layer too which however
+will change in one of the next Jinja versions. So if you put a `foo` attribute
+on your undefined singleton you will be able to do ``{{ undefined.foo }}``
+by now but certainly not in the future.
+
+This limitation currently exists because undefined is treated as normal object
+and thus affected by normal getattr calls.
+
+
Automatic Escaping
==================
:copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
-import re
from jinja.lexer import Lexer
from jinja.parser import Parser
from jinja.loaders import LoaderWrapper
from jinja.datastructure import SilentUndefined, Markup, Context, FakeTranslator
from jinja.utils import collect_translations, get_attribute
from jinja.exceptions import FilterNotFound, TestNotFound, \
- SecurityException, TemplateSyntaxError, TemplateRuntimeError
+ SecurityException, TemplateSyntaxError
from jinja.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
Python code. This code is wrapped within a `Template` class that
allows you to render it.
"""
- from jinja.parser import Parser
from jinja.translators.python import PythonTranslator
try:
rv = PythonTranslator.process(self, Parser(self, source).parse())
(name, salt or '')).hexdigest())
+
+def _loader_missing(*args, **kwargs):
+ """Helper function for `LoaderWrapper`."""
+ raise RuntimeError('no loader defined')
+
+
+
class LoaderWrapper(object):
"""
Wraps a loader so that it's bound to an environment.
self.environment = environment
self.loader = loader
if self.loader is None:
- self.get_source = self.parse = self.load = self._loader_missing
+ self.get_source = self.parse = self.load = _loader_missing
self.available = False
else:
self.available = True
raise RuntimeError('no loader defined')
def __nonzero__(self):
- return self.loader is not None
+ return self.available
class BaseLoader(object):
--- /dev/null
+import jdebug
+from jinja import Environment, DictLoader
+
+base_tmpl = """
+{% block content %}Default{% endblock %}
+"""
+
+### condition is inside of block
+
+test1 = """
+{% extends 'base' %}
+
+{% block content %}
+ {% if False %}
+ {{ throw_exception() }}
+ {% endif %}
+{% endblock %}
+"""
+
+### block is inside of condition
+
+test2 = """
+{% extends 'base' %}
+
+{% if False %}
+ {% block content %}
+ {{ throw_exception() }}
+ {% endblock %}
+{% endif %}
+"""
+
+class TestException(Exception):
+ pass
+
+def throw_exception():
+ raise TestException()
+
+env = Environment(
+ loader=DictLoader(dict(base=base_tmpl))
+)
+
+if __name__ == '__main__':
+ for name in 'test1', 'test2':
+ template_body = globals().get(name)
+ template = env.from_string(template_body)
+ try:
+ print 'Rendering template:\n"""%s"""' % template_body
+ template.render(throw_exception=throw_exception)
+ except TestException:
+ print 'Result: throw_exception() was called'
+ else:
+ print 'Result: throw_exception() was not called'
+ print
+
+ print 'First template illustrates that condition is working well'
+ print 'The question is - why {% block %} is being evalueted '\
+ 'in false condition in second template?'