From ccae0559b4ab43be063b34cc0f0d95106173d284 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 5 Oct 2008 23:08:58 +0200 Subject: [PATCH] Various cleanups and added custom cycler. --HG-- branch : trunk --- CHANGES | 2 ++ docs/templates.rst | 42 ++++++++++++++++++++++++++++++++++++++++++ jinja2/__init__.py | 5 +++-- jinja2/bccache.py | 9 ++++----- jinja2/debug.py | 18 ------------------ jinja2/defaults.py | 5 +++-- jinja2/environment.py | 25 +++++++++++++++++++++---- jinja2/exceptions.py | 39 ++++++++++++++++++++++++++------------- jinja2/filters.py | 28 ++++++++++++++++++---------- jinja2/loaders.py | 9 +++++---- jinja2/runtime.py | 8 ++++---- jinja2/utils.py | 37 +++++++++++++++++++++++++++++++++++++ tests/test_debug.py | 4 ++-- tests/test_filters.py | 4 ++-- tests/test_security.py | 20 ++++++++------------ tests/test_various.py | 13 +++++++++++++ 16 files changed, 190 insertions(+), 78 deletions(-) diff --git a/CHANGES b/CHANGES index 7a5d0c2..c0c7139 100644 --- a/CHANGES +++ b/CHANGES @@ -37,6 +37,8 @@ Version 2.1 - inclusions and imports "with context" forward all variables now, not only the initial context. +- added a cycle helper called `cycle`. + Version 2.0 ----------- (codename jinjavitus, released on July 17th 2008) diff --git a/docs/templates.rst b/docs/templates.rst index 0c01eee..d797fec 100644 --- a/docs/templates.rst +++ b/docs/templates.rst @@ -482,6 +482,9 @@ each time through the loop by using the special `loop.cycle` helper::
  • {{ row }}
  • {% endfor %} +With Jinja 2.1 an extra `cycle` helper exists that allows loop-unbound +cycling. For more information have a look at the :ref:`builtin-globals`. + .. _loop-filtering: Unlike in Python it's not possible to `break` or `continue` in a loop. You @@ -999,6 +1002,7 @@ List of Builtin Tests .. jinjatests:: +.. _builtin-globals: List of Global Functions ------------------------ @@ -1038,6 +1042,44 @@ The following functions are available in the global scope by default: A convenient alternative to dict literals. ``{'foo': 'bar'}`` is the same as ``dict(foo='bar')``. +.. class:: cycler(\*items) + + The cycler allows you to cycle among values similar to how `loop.cycle` + works. Unlike `loop.cycle` however you can use this cycler outside of + loops or over multiple loops. + + This is for example very useful if you want to show a list of folders and + files, with the folders on top, but both in the same list with alteranting + row colors. + + The following example shows how `cycler` can be used:: + + {% set row_class = cycler('odd', 'even') %} + + + A cycler has the following attributes and methods: + + .. method:: reset() + + Resets the cycle to the first item. + + .. method:: next() + + Goes one item a head and returns the then current item. + + .. attribute:: current + + Returns the current item. + + **new in Jinja 2.1** + Extensions ---------- diff --git a/jinja2/__init__.py b/jinja2/__init__.py index 0a3ff6f..95b2d5b 100644 --- a/jinja2/__init__.py +++ b/jinja2/__init__.py @@ -59,8 +59,9 @@ from jinja2.utils import Markup, escape, clear_caches, \ __all__ = [ 'Environment', 'Template', 'BaseLoader', 'FileSystemLoader', 'PackageLoader', 'DictLoader', 'FunctionLoader', 'PrefixLoader', - 'ChoiceLoader', 'Undefined', 'DebugUndefined', 'StrictUndefined', - 'TemplateError', 'UndefinedError', 'TemplateNotFound', + 'ChoiceLoader', 'BytecodeCache', 'FileSystemBytecodeCache', + 'MemcachedBytecodeCache', 'Undefined', 'DebugUndefined', + 'StrictUndefined', 'TemplateError', 'UndefinedError', 'TemplateNotFound', 'TemplateSyntaxError', 'TemplateAssertionError', 'environmentfilter', 'contextfilter', 'Markup', 'escape', 'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined' diff --git a/jinja2/bccache.py b/jinja2/bccache.py index e11bad5..2c57616 100644 --- a/jinja2/bccache.py +++ b/jinja2/bccache.py @@ -24,6 +24,7 @@ try: from hashlib import sha1 except ImportError: from sha import new as sha1 +from jinja2.utils import open_if_exists bc_version = 1 @@ -193,17 +194,15 @@ class FileSystemBytecodeCache(BytecodeCache): return path.join(self.directory, self.pattern % bucket.key) def load_bytecode(self, bucket): - filename = self._get_cache_filename(bucket) - if path.exists(filename): - f = file(filename, 'rb') + f = open_if_exists(self._get_cache_filename(bucket), 'rb') + if f is not None: try: bucket.load_bytecode(f) finally: f.close() def dump_bytecode(self, bucket): - filename = self._get_cache_filename(bucket) - f = file(filename, 'wb') + f = file(self._get_cache_filename(bucket), 'wb') try: bucket.write_bytecode(f) finally: diff --git a/jinja2/debug.py b/jinja2/debug.py index f503c21..53dac4d 100644 --- a/jinja2/debug.py +++ b/jinja2/debug.py @@ -35,24 +35,6 @@ def translate_exception(exc_info): 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 = '