self.translated_source = translated_source
self.generate_func = None
- def source(self):
- """The original sourcecode for this template."""
- return self.environment.loader.get_source(self.code.co_filename)
- source = property(source, doc=source.__doc__)
-
def dump(self, stream=None):
"""Dump the template into python bytecode."""
if stream is not None:
def nodeinfo(self, node):
"""
- Return a comment that helds the node informations.
+ Return a comment that helds the node informations or None
+ if there is no need to add a debug comment.
"""
- return '# DEBUG(filename=%r, lineno=%s)' % (
+ rv = '# DEBUG(filename=%s, lineno=%s)' % (
node.filename,
node.lineno
)
+ if rv != self.last_debug_comment:
+ self.last_debug_comment = rv
+ return rv
def filter(self, s, filter_nodes):
"""
def reset(self):
self.indention = 0
self.last_cycle_id = 0
+ self.last_debug_comment = None
def translate(self):
self.reset()
"""
Handle data around nodes.
"""
- return self.indent(self.nodeinfo(node)) + '\n' + \
- self.indent('yield %r' % node.text)
+ nodeinfo = self.nodeinfo(node) or ''
+ if nodeinfo:
+ nodeinfo = self.indent(nodeinfo) + '\n'
+ return nodeinfo + self.indent('yield %r' % node.text)
def handle_node_list(self, node):
"""
"""
buf = [self.handle_node(n) for n in node]
if buf:
- return '\n'.join([self.indent(self.nodeinfo(node))] + buf)
- return ''
+ nodeinfo = self.nodeinfo(node)
+ if nodeinfo:
+ buf = [self.indent(nodeinfo)] + buf
+ return '\n'.join(buf)
def handle_for_loop(self, node):
"""
"""
buf = []
write = lambda x: buf.append(self.indent(x))
- write(self.nodeinfo(node))
+ nodeinfo = self.nodeinfo(node)
+ if nodeinfo:
+ write(nodeinfo)
write('ctx_push()')
# recursive loops
# handle real loop code
self.indention += 1
- buf.append(self.indent(self.nodeinfo(node.body)))
+ nodeinfo = self.nodeinfo(node.body)
+ if nodeinfo:
+ write(nodeinfo)
buf.append(self.handle_node(node.body))
self.indention -= 1
if node.else_:
write('if not context[\'loop\'].iterated:')
self.indention += 1
- buf.append(self.indent(self.nodeinfo(node.else_)))
+ nodeinfo = self.nodeinfo(node.else_)
+ if nodeinfo:
+ write(nodeinfo)
buf.append(self.handle_node(node.else_))
self.indention -= 1
"""
buf = []
write = lambda x: buf.append(self.indent(x))
- write(self.nodeinfo(node))
+ nodeinfo = self.nodeinfo(node)
+ if nodeinfo:
+ write(nodeinfo)
for idx, (test, body) in enumerate(node.tests):
write('%sif %s:' % (
idx and 'el' or '',
self.handle_node(test)
))
self.indention += 1
- write(self.nodeinfo(node))
+ nodeinfo = self.nodeinfo(body)
+ if nodeinfo:
+ write(nodeinfo)
buf.append(self.handle_node(body))
self.indention -= 1
if node.else_ is not None:
write('else:')
self.indention += 1
- write(self.nodeinfo(node))
+ nodeinfo = self.nodeinfo(node.else_)
+ if nodeinfo:
+ write(nodeinfo)
buf.append(self.handle_node(node.else_))
self.indention -= 1
return '\n'.join(buf)
write('if not %r in context.current:' % name)
self.indention += 1
- write(self.nodeinfo(node))
+ nodeinfo = self.nodeinfo(node)
+ if nodeinfo:
+ write(nodeinfo)
if node.seq.__class__ in (ast.Tuple, ast.List):
write('context.current[%r] = CycleContext(%s)' % (
name,
"""
Handle a print statement.
"""
- return self.indent(self.nodeinfo(node)) + '\n' + \
- self.indent('yield finish_var(%s)' %
- self.handle_node(node.variable))
+ nodeinfo = self.nodeinfo(node) or ''
+ if nodeinfo:
+ nodeinfo = self.indent(nodeinfo) + '\n'
+ return nodeinfo + self.indent('yield finish_var(%s)' %
+ self.handle_node(node.variable))
def handle_macro(self, node):
"""
write('def macro(*args):')
self.indention += 1
- write(self.nodeinfo(node))
+ nodeinfo = self.nodeinfo(node)
+ if nodeinfo:
+ write(nodeinfo)
if node.arguments:
write('argcount = len(args)')
else:
write('ctx_push()')
- write(self.nodeinfo(node.body))
+ nodeinfo = self.nodeinfo(node.body)
+ if nodeinfo:
+ write(nodeinfo)
buf.append(self.handle_node(node.body))
write('ctx_pop()')
write('if False:')
"""
Handle variable assignments.
"""
- return self.indent(self.nodeinfo(node)) + '\n' + \
- self.indent('context[%r] = %s' % (
+ nodeinfo = self.nodeinfo(node) or ''
+ if nodeinfo:
+ nodeinfo = self.indent(nodeinfo) + '\n'
+ return nodeinfo + self.indent('context[%r] = %s' % (
node.name,
self.handle_node(node.expr)
))
write = lambda x: buf.append(self.indent(x))
write('def filtered():')
self.indention += 1
- write(self.nodeinfo(node))
write('ctx_push()')
- write(self.nodeinfo(node.body))
+ nodeinfo = self.nodeinfo(node.body)
+ if nodeinfo:
+ write(nodeinfo)
buf.append(self.handle_node(node.body))
write('ctx_pop()')
write('if False:')
write = lambda x: buf.append(self.indent(x))
write('ctx_push()')
- write(self.nodeinfo(node.body))
+ nodeinfo = self.nodeinfo(node.body)
+ if nodeinfo:
+ write(nodebody)
buf.append(self.handle_node(node.body))
write('ctx_pop()')
return '\n'.join(buf)
replacements = '{%s}' % ', '.join(replacements)
else:
replacements = 'None'
- return self.indent(self.nodeinfo(node)) + '\n' + \
- self.indent('yield translate(%r, %r, %r, %s)' % (
+ nodeinfo = self.nodeinfo(node) or ''
+ if nodeinfo:
+ nodeinfo = self.indent(nodeinfo) + '\n'
+ return nodeinfo + self.indent('yield translate(%r, %r, %r, %s)' % (
node.singular,
node.plural,
node.indicator,
return wrapped
-def raise_template_exception(template, exception, filename, lineno, context):
+def raise_template_exception(exception, filename, lineno, context):
"""
Raise an exception "in a template". Return a traceback
object.
globals = {
'__name__': filename,
'__file__': filename,
- '__loader__': TracebackLoader(template),
+ '__loader__': TracebackLoader(context.environment,
+ filename),
'__exception_to_raise__': exception
}
try:
"""
sourcelines = template.translated_source.splitlines()
startpos = traceback.tb_lineno - 1
- args = None
+ filename = None
# looks like we loaded the template from string. we cannot
# do anything here.
if startpos > len(sourcelines):
while startpos > 0:
m = _debug_info_re.search(sourcelines[startpos])
if m is not None:
- args = m.groups()
+ filename, lineno = m.groups()
+ if filename == 'None':
+ filename = ''
+ if lineno == 'None':
+ lineno = 0
+ else:
+ lineno = int(lineno)
break
startpos -= 1
# no traceback information found, reraise unchanged
- if args is None:
+ if filename is None:
return traceback
- return raise_template_exception(template, exc_value, args[0],
- int(args[1] or 0), context)
+ return raise_template_exception(exc_value, filename,
+ lineno, context)
class TracebackLoader(object):
Fake importer that just returns the source of a template.
"""
- def __init__(self, template):
- self.template = template
+ def __init__(self, environment, filename):
+ self.loader = environment.loader
+ self.filename = filename
def get_source(self, impname):
- return self.template.source
+ return self.loader.get_source(self.filename)
class CacheDict(object):