return self.type
elif self.type in reverse_operators:
return reverse_operators[self.type]
- return '%s:%s' % (self.type, self.value)
+ elif self.type is 'name':
+ return self.value
+ return self.type
def test(self, expr):
"""Test a token against a token expression. This can either be a
def expect(self, expr):
"""Expect a given token type and return it"""
if not self.current.test(expr):
+ if ':' in expr:
+ expr = expr.split(':')[1]
+ if self.current.type is 'eof':
+ raise TemplateSyntaxError('unexpected end of template, '
+ 'expected %r.' % expr,
+ self.current.lineno,
+ self.filename)
raise TemplateSyntaxError("expected token %r, got %r" %
- (expr, self.current),
+ (expr, str(self.current)),
self.current.lineno,
self.filename)
try:
return exc_info[:2] + (result_tb or initial_tb,)
+def translate_syntax_error(error):
+ """When passed a syntax error it will generate a new traceback with
+ more debugging information.
+ """
+ filename = error.filename
+ if filename is None:
+ filename = '<template>'
+ elif isinstance(filename, unicode):
+ filename = filename.encode('utf-8')
+ code = compile('\n' * (error.lineno - 1) + 'raise __jinja_exception__',
+ filename, 'exec')
+ try:
+ exec code in {'__jinja_exception__': error}
+ except:
+ exc_info = sys.exc_info()
+ return exc_info[:2] + (exc_info[2].tb_next,)
+
+
def fake_exc_info(exc_info, filename, lineno, tb_back=None):
"""Helper for `translate_exception`."""
exc_type, exc_value, tb = exc_info
from jinja2.optimizer import optimize
from jinja2.compiler import generate
from jinja2.runtime import Undefined, Context, concat
-from jinja2.debug import translate_exception
+from jinja2.debug import translate_exception, translate_syntax_error
+from jinja2.exceptions import TemplateSyntaxError
from jinja2.utils import import_string, LRUCache, Markup, missing
except (TypeError, LookupError):
return self.undefined(obj=obj, name=argument)
- def parse(self, source, name=None):
+ def parse(self, source, filename=None):
"""Parse the sourcecode and return the abstract syntax tree. This
tree of nodes is used by the compiler to convert the template into
executable source- or bytecode. This is useful for debugging or to
extract information from templates.
"""
- return Parser(self, source, name).parse()
+ try:
+ return Parser(self, source, filename).parse()
+ except TemplateSyntaxError, e:
+ exc_type, exc_value, tb = translate_syntax_error(e)
+ raise exc_type, exc_value, tb
def lex(self, source, name=None):
"""Lex the given sourcecode and return a generator that yields
mainly used internally.
"""
if isinstance(source, basestring):
- source = self.parse(source, name)
+ source = self.parse(source, filename)
if self.optimized:
node = optimize(source, self, globals or {})
source = generate(node, self, name, filename)
class TemplateSyntaxError(TemplateError):
"""Raised to tell the user that there is a problem with the template."""
- def __init__(self, message, lineno, name):
+ def __init__(self, message, lineno, filename):
TemplateError.__init__(self, '%s (line %s)' % (message, lineno))
self.message = message
self.lineno = lineno
- self.name = name
+ self.filename = filename
class TemplateAssertionError(TemplateSyntaxError):