env = context_or_env
namespace = {}
+ # generate an jinja unique filename used so that linecache
+ # gets data that doesn't interferes with other modules
+ if filename is None:
+ from random import randrange
+ vfilename = 'jinja://~%d' % randrange(0, 10000)
+ filename = '<string>'
+ else:
+ vfilename = 'jinja://%s' % filename
+
offset = '\n' * (lineno - 1)
code = compile(offset + 'raise __exception_to_raise__',
- filename or '<template>', 'exec')
+ vfilename or '<template>', 'exec')
+
+ loader = TracebackLoader(env, source, filename)
+ loader.update_linecache(vfilename)
globals = {
- '__name__': filename,
- '__file__': filename,
- '__loader__': TracebackLoader(env, source, filename),
+ '__name__': vfilename,
+ '__file__': vfilename,
+ '__loader__': loader,
'__exception_to_raise__': exception
}
try:
self.source = source
self.filename = filename
+ def update_linecache(self, virtual_filename):
+ """
+ Hacky way to let traceback systems know about the
+ Jinja template sourcecode. Very hackish indeed.
+ """
+ # check for linecache, not every implementation of python
+ # might have such an module.
+ try:
+ from linecache import cache
+ except ImportError:
+ return
+ data = self.get_source(None)
+ cache[virtual_filename] = (
+ len(data),
+ None,
+ data.splitlines(True),
+ virtual_filename
+ )
+
def get_source(self, impname):
+ source = ''
if self.source is not None:
- return self.source
+ source = self.source
elif self.loader is not None:
try:
- return self.loader.get_source(self.filename)
+ source = self.loader.get_source(self.filename)
except TemplateNotFound:
pass
- return ''
+ if isinstance(source, unicode):
+ source = source.encode('utf-8')
+ return source
class CacheDict(object):