to workaround problems with `datetime.strftime` which only accepts
binary strings.
+- developer friendly traceback is now toggleable
+
+- silent variable name failure is now toggleable
+
Version 1.0
-----------
{{ undefined.attribute().attribute_too[42] }}
still returns `undefined`.
+Starting with Jinja 1.1 it's possible to control the `undefined` behavior
+in the Jinja environment, thus on the application side. If you receive
+a `TemplateRuntimeError` when operating on an undefined variable the
+environment was created with `silent` disabled.
+
+In a non silent environment the error you get tells you the line number
+and the name of the variable / attribute which could not be found.
+
Escaping
========
`tests` dict of tests of the default tests if not defined.
`context_class` the context class this template should use. See
the `context documentation`_ for more details.
+`silent` set this to `False` if you want to receive errors
+ for missing template variables or attributes.
+ Defaults to `False`. *new in Jinja 1.1*
+`friendly_traceback` Set this to `False` to disable the developer
+ friendly traceback rewriting. Whenever an
+ runtime or syntax error occours jinja will try
+ to make a developer friendly traceback that shows
+ the error in the template line. This however can
+ be annoying when debugging broken functions which
+ are called from the template. *new in Jinja 1.1*
========================= ==================================================
All of these variables except those marked with a star (*) are modifiable after
return result
def __getitem__(self, name):
- if name.startswith('::'):
+ if not name.startswith('::'):
+ # because the stack is usually quite small we better use [::-1]
+ # which is faster than reversed() somehow.
+ for d in self._stack[::-1]:
+ if name in d:
+ rv = d[name]
+ if rv.__class__ is Deferred:
+ rv = rv(self, name)
+ # never touch the globals!
+ if d is self.globals:
+ self.initial[name] = rv
+ else:
+ d[name] = rv
+ return rv
+ if self.environment.silent:
return Undefined
- # because the stack is usually quite small we better use [::-1]
- # which is faster than reversed() somehow.
- for d in self._stack[::-1]:
- if name in d:
- rv = d[name]
- if rv.__class__ is Deferred:
- rv = rv(self, name)
- # never touch the globals!
- if d is self.globals:
- self.initial[name] = rv
- else:
- d[name] = rv
- return rv
- return Undefined
+ raise TemplateRuntimeError('%r is not defined' % name)
def __setitem__(self, name, value):
self.current[name] = value
from jinja.datastructure import Undefined, Markup, Context, FakeTranslator
from jinja.utils import escape, collect_translations, get_attribute
from jinja.exceptions import FilterNotFound, TestNotFound, \
- SecurityException, TemplateSyntaxError
+ SecurityException, TemplateSyntaxError, TemplateRuntimeError
from jinja.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
loader=None,
filters=None,
tests=None,
- context_class=Context):
+ context_class=Context,
+ silent=True,
+ friendly_traceback=True):
# lexer / parser information
self.block_start_string = block_start_string
self.tests = tests is None and DEFAULT_TESTS.copy() or tests
self.default_filters = default_filters or []
self.context_class = context_class
+ self.silent = silent
+ self.friendly_traceback = friendly_traceback
# global namespace
self.globals = namespace is None and DEFAULT_NAMESPACE.copy() \
try:
rv = PythonTranslator.process(self, Parser(self, source).parse())
except TemplateSyntaxError, e:
- # if errors occour raise a better traceback
+ # on syntax errors rewrite the traceback if wanted
+ if not self.friendly_traceback:
+ raise
from jinja.utils import raise_syntax_error
__traceback_hide__ = True
raise_syntax_error(e, self, source)
return get_attribute(obj, name)
except (AttributeError, SecurityException):
pass
- return Undefined
+ if self.silent:
+ return Undefined
+ raise TemplateRuntimeError('attribute %r or object %r not defined' % (
+ name, obj))
def get_attributes(self, obj, attributes):
"""
try:
return self.loader.load(self.environment, name, translator)
except TemplateSyntaxError, e:
+ if not self.environment.friendly_traceback:
+ raise
__traceback_hide__ = True
raise_syntax_error(e, self.environment)
try:
return capture_generator(self.generate_func(ctx))
except:
+ if not self.environment.friendly_traceback:
+ raise
# debugging system:
# on any exception we first get the current exception information
# and skip the internal frames (currently either one (python2.5)