try:
# caching is only possible for the python translator. skip
# all other translators
- if translator is PythonTranslator:
- tmpl = None
-
- # auto reload enabled? check for the last change of
- # the template
- if self.__auto_reload:
- last_change = self.check_source_changed(environment, name)
- else:
- last_change = None
-
- # check if we have something in the memory cache and the
- # memory cache is enabled.
- if self.__memcache is not None and name in self.__memcache:
+ if translator is not PythonTranslator:
+ return super(CachedLoaderMixin, self).load(
+ environment, name, translator)
+
+ tmpl = None
+ save_to_disk = False
+ push_to_memory = False
+
+ # auto reload enabled? check for the last change of
+ # the template
+ if self.__auto_reload:
+ last_change = self.check_source_changed(environment, name)
+ else:
+ last_change = None
+
+ # check if we have something in the memory cache and the
+ # memory cache is enabled.
+ if self.__memcache is not None:
+ if name in self.__memcache:
tmpl = self.__memcache[name]
+ # if auto reload is enabled check if the template changed
if last_change is not None and \
last_change > self.__times[name]:
tmpl = None
+ push_to_memory = True
+ else:
+ push_to_memory = True
- # if diskcache is enabled look for an already compiled
- # template.
- if self.__cache_folder is not None:
- cache_fn = get_cachename(self.__cache_folder, name)
-
- # there is an up to date compiled template
- if tmpl is not None and last_change is None:
- try:
- cache_time = path.getmtime(cache_fn)
- except OSError:
- cache_time = -1
- if cache_time == -1 or last_change >= cache_time:
- f = file(cache_fn, 'rb')
- try:
- tmpl = Template.load(environment, f)
- finally:
- f.close()
-
- # no template so far, parse, translate and compile it
- elif tmpl is None:
- tmpl = super(CachedLoaderMixin, self).load(
- environment, name, translator)
-
- # save the compiled template
- f = file(cache_fn, 'wb')
+ # mem cache disabled or not cached by now
+ # try to load if from the disk cache
+ if tmpl is None and self.__cache_folder is not None:
+ cache_fn = get_cachename(self.__cache_folder, name)
+ if last_change is not None:
try:
- tmpl.dump(f)
+ cache_time = path.getmtime(cache_fn)
+ except OSError:
+ cache_time = -1
+ if last_change is None or last_change <= cache_time:
+ f = file(cache_fn, 'rb')
+ try:
+ tmpl = Template.load(environment, f)
finally:
f.close()
-
- # if memcaching is enabled push the template
- if tmpl is not None:
- if self.__memcache is not None:
- self.__times[name] = time.time()
- self.__memcache[name] = tmpl
- return tmpl
-
- # if we reach this point we don't have caching enabled or translate
- # to something else than python
- return super(CachedLoaderMixin, self).load(
- environment, name, translator)
+ else:
+ save_to_disk = True
+
+ # if we still have no template we load, parse and translate it.
+ if tmpl is None:
+ tmpl = super(CachedLoaderMixin, self).load(
+ environment, name, translator)
+
+ # save the compiled template on the disk if enabled
+ if save_to_disk:
+ f = file(cache_fn, 'wb')
+ try:
+ tmpl.dump(f)
+ finally:
+ f.close()
+
+ # if memcaching is enabled and the template not loaded
+ # we add that there.
+ if push_to_memory:
+ self.__times[name] = time.time()
+ self.__memcache[name] = tmpl
+ return tmpl
finally:
self.__lock.release()
RUNTIME_EXCEPTION_OFFSET
+#: regular expression for the debug symbols
+_debug_re = re.compile(r'^\s*\# DEBUG\(filename=(?P<filename>.*?), '
+ r'lineno=(?P<lineno>\d+)\)$')
+
+
try:
GeneratorExit
except NameError:
class GeneratorExit(Exception):
- pass
-
-
-#: regular expression for the debug symbols
-_debug_re = re.compile(r'^\s*\# DEBUG\(filename=(?P<filename>.*?), '
- r'lineno=(?P<lineno>\d+)\)$')
+ """For python2.3/python2.4 compatibility"""
def _to_tuple(args):
def render(self, *args, **kwargs):
"""Render a template."""
- return capture_generator(self._generate(*args, **kwargs))
+ ctx = self._prepare(*args, **kwargs)
+ try:
+ return capture_generator(self.generate_func(ctx))
+ except:
+ self._debug(ctx, *sys.exc_info())
def stream(self, *args, **kwargs):
"""Render a template as stream."""
- return TemplateStream(self._generate(*args, **kwargs))
-
- def _generate(self, *args, **kwargs):
- """Template generation helper"""
+ def proxy(ctx):
+ try:
+ for item in self.generate_func(ctx):
+ yield item
+ except GeneratorExit:
+ return
+ except:
+ self._debug(ctx, *sys.exc_info())
+ return TemplateStream(proxy(self._prepare(*args, **kwargs)))
+
+ def _prepare(self, *args, **kwargs):
+ """Prepare the template execution."""
# if there is no generation function we execute the code
# in a new namespace and save the generation function and
# debug information.
+ env = self.environment
if self.generate_func is None:
- ns = {'environment': self.environment}
+ ns = {'environment': env}
exec self.code in ns
self.generate_func = ns['generate']
self._debug_info = ns['debug_info']
- ctx = self.environment.context_class(self.environment, *args, **kwargs)
- try:
- for item in self.generate_func(ctx):
- yield item
- 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)
- # or two (python2.4 and lower)). After that we call a function
- # that creates a new traceback that is easier to debug.
- exc_type, exc_value, traceback = sys.exc_info()
-
- # if an exception is a GeneratorExit we just reraise it. If we
- # run on top of python2.3 or python2.4 a fake GeneratorExit
- # class is added for this module so that we don't get a NameError
- if exc_type is GeneratorExit:
- raise
+ return env.context_class(env, *args, **kwargs)
+ def _debug(self, ctx, exc_type, exc_value, traceback):
+ """Debugging Helper"""
+ # just modify traceback if we have that feature enabled
+ if self.environment.friendly_traceback:
+ # debugging system:
+ # on any exception we first skip the internal frames (currently
+ # either one (python2.5) or two (python2.4 and lower)). After that
+ # we call a function that creates a new traceback that is easier
+ # to debug.
for _ in xrange(RUNTIME_EXCEPTION_OFFSET):
traceback = traceback.tb_next
traceback = translate_exception(self, exc_type, exc_value,
traceback, ctx)
- raise exc_type, exc_value, traceback
+ raise exc_type, exc_value, traceback
class PythonTranslator(Translator):