[svn] some changes in jinja regarding silent and non silent failure, the exception...
authorArmin Ronacher <armin.ronacher@active-4.com>
Wed, 4 Apr 2007 11:50:09 +0000 (13:50 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Wed, 4 Apr 2007 11:50:09 +0000 (13:50 +0200)
--HG--
branch : trunk

CHANGES
docs/src/designerdoc.txt
docs/src/devintro.txt
jinja/datastructure.py
jinja/environment.py
jinja/loaders.py
jinja/translators/python.py

diff --git a/CHANGES b/CHANGES
index b63041ca6ac8f04345ea8086e036cdf0c1216ad0..435d009da43631ae538b135dac6046f3eebeed7e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -21,6 +21,10 @@ Version 1.1
   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
 -----------
index c59987ce5e00fdbc21979b0546e7d343ce21c3c7..3bb5719079837680ef71ef1d05bfcdee54ca3a3c 100644 (file)
@@ -688,6 +688,14 @@ attribute calls return undefined, calling too:
     {{ 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
 ========
 
index ca9859b60efeebe3c658bb89079d3eb07fc43ac2..ea7819a747ddfa5e5c463ed5958425b11842aad0 100644 (file)
@@ -74,6 +74,16 @@ Here the possible initialization parameters:
 `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
index cd93568281fc062b6e2463ac1de9489d6c76d9a0..908a1c62a961a46bf01843eb58fc38a8b6ef6497 100644 (file)
@@ -176,22 +176,23 @@ class Context(object):
         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
index 6fdd369aa2a6ef98030833c761b30b847a284594..ab268da1b496ca6b0b66a6ffffb63b3f4ce17e46 100644 (file)
@@ -15,7 +15,7 @@ from jinja.loaders import LoaderWrapper
 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
 
 
@@ -40,7 +40,9 @@ class Environment(object):
                  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
@@ -59,6 +61,8 @@ class Environment(object):
         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() \
@@ -91,7 +95,9 @@ class Environment(object):
         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)
@@ -180,7 +186,10 @@ class Environment(object):
                 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):
         """
index b11e9f9bdb2d2e492e1daee8f32fda5e52368976..b55fb0e5b74deca392ead6428ebc11f09dc16322 100644 (file)
@@ -84,6 +84,8 @@ class LoaderWrapper(object):
         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)
 
index 9d7b5c34d5b4fd72560c5d1b3e7db9c3c2f2a826..3f3133c35e3b83ebd2a87bddfeccfdda30b8ae60 100644 (file)
@@ -84,6 +84,8 @@ class Template(object):
         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)