From 40cf47cac490692ce6961922082b00c51dfa2b99 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Wed, 4 Apr 2007 13:50:09 +0200 Subject: [PATCH] [svn] some changes in jinja regarding silent and non silent failure, the exception fun and documented block.super on the webpage --HG-- branch : trunk --- CHANGES | 4 ++++ docs/src/designerdoc.txt | 8 ++++++++ docs/src/devintro.txt | 10 ++++++++++ jinja/datastructure.py | 31 ++++++++++++++++--------------- jinja/environment.py | 17 +++++++++++++---- jinja/loaders.py | 2 ++ jinja/translators/python.py | 2 ++ 7 files changed, 55 insertions(+), 19 deletions(-) diff --git a/CHANGES b/CHANGES index b63041c..435d009 100644 --- 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 ----------- diff --git a/docs/src/designerdoc.txt b/docs/src/designerdoc.txt index c59987c..3bb5719 100644 --- a/docs/src/designerdoc.txt +++ b/docs/src/designerdoc.txt @@ -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 ======== diff --git a/docs/src/devintro.txt b/docs/src/devintro.txt index ca9859b..ea7819a 100644 --- a/docs/src/devintro.txt +++ b/docs/src/devintro.txt @@ -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 diff --git a/jinja/datastructure.py b/jinja/datastructure.py index cd93568..908a1c6 100644 --- a/jinja/datastructure.py +++ b/jinja/datastructure.py @@ -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 diff --git a/jinja/environment.py b/jinja/environment.py index 6fdd369..ab268da 100644 --- a/jinja/environment.py +++ b/jinja/environment.py @@ -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): """ diff --git a/jinja/loaders.py b/jinja/loaders.py index b11e9f9..b55fb0e 100644 --- a/jinja/loaders.py +++ b/jinja/loaders.py @@ -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) diff --git a/jinja/translators/python.py b/jinja/translators/python.py index 9d7b5c3..3f3133c 100644 --- a/jinja/translators/python.py +++ b/jinja/translators/python.py @@ -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) -- 2.26.2