- added a bunch of new docstrings to the Jinja classes. Makes fun now to
use pydoc :-)
+- fixed severe memcaching bug. Formerly it wasn't possible to use memcaching
+ without enabling disk cache.
+
Version 1.0
-----------
.. admonition:: note
- Filters have a pretty low priority. If you want to add fitered values
- you have to put them into parentheses. The same applies if you want to access
- attributes:
+ The filter operator has a pretty low priority. If you want to add fitered
+ values you have to put them into parentheses. The same applies if you want
+ to access attributes or return values:
.. sourcecode:: jinja
wrong:
{{ foo|filter.attribute }}
+*new in Jinja 1.1*:
+
+Because the application can provide additional filters you can get a documentation
+of all the provided filters by calling ``debug.filters()``:
+
+.. sourcecode:: jinja
+
+ {{ debug.filters() }}
+ -> returns a plain text representation of all the filters
+
+ {{ debug.filters(False) }}
+ -> same as above but without the builtin ones.
+
Tests
=====
``/`` divide the left operand by the right one.
``{{ 1 / 2 }}`` would return ``0.5``.
``//`` divide the left operand by the right one and return a truncated
- integer result: ``{{ 20 // 7 }}`` is ``2``.
+ integer result: ``{{ 20 // 7 }}`` is ``2``. (*new in
+ Jinja 1.1*)
``*`` multiply the left operand with the right one.
``{{ 2 * 2 }}`` would return ``4``.
``**`` raise the left operand to the power of the right
If you receive an error, check if you have a typo in your code. If not, have
a look at the `installation`_ page for troubleshooting.
+Basically the important method on a template is the `render` method. It
+takes either a dict or keyword arguments. All keyword arguments appear
+in the template as variables.
+
+So these two snippets do the same:
+
+.. sourcecode:: python
+
+ tmpl.render(
+ knights='we say nih',
+ spam='and eggs'
+ )
+
+.. sourcecode:: python
+
+ tmpl.render({
+ 'knights': 'we say nih',
+ 'spam': 'and eggs'
+ })
+
The Environment
===============
- `Internationalization <i18n.txt>`_
+ - `Recipies <devrecipies.txt>`_
+
- Template Designer Documentation:
- `Syntax Reference <designerdoc.txt>`_
class Context(object):
"""
- Dict like object.
+ Dict like object containing the variables for the template.
"""
def __init__(self, _environment_, *args, **kwargs):
self._stack = [_environment_.globals, dict(*args, **kwargs), {}]
self.globals, self.initial, self.current = self._stack
+ # translator function added by the environment rendering function
+ self.translate_func = None
+
# cache object used for filters and tests
self.cache = {}
"""
from jinja.filters import FILTERS as DEFAULT_FILTERS
from jinja.tests import TESTS as DEFAULT_TESTS
-from jinja.utils import debug_context, safe_range, generate_lorem_ipsum, \
+from jinja.utils import debug_helper, safe_range, generate_lorem_ipsum, \
watch_changes, flush
DEFAULT_NAMESPACE = {
'range': safe_range,
- 'debug': debug_context,
+ 'debug': debug_helper,
'lipsum': generate_lorem_ipsum,
'watchchanges': watch_changes,
'flush': flush
# if a string is ASCII only we yield it as string
# in other cases as unicode. This works around
# problems with datetimeobj.strftime()
+ # also escape newlines in strings
+ t_data = t_data.replace('\n', '\\n')
try:
str(t_data)
except UnicodeError:
' def translate(s, p=None, n=None, r=None):\n'
' if p is None:\n'
' return translator.gettext(s) % (r or {})\n'
- ' return translator.ngettext(s, p, r[n]) % (r or {})'
+ ' return translator.ngettext(s, p, r[n]) % (r or {})\n'
+ ' context.translate_func = translate'
)
# add body lines and "generator hook"
buf = []
write = lambda x: buf.append(self.indent(x))
- write('if not %r in context.current:' % name)
+ write('if %r not in context.current:' % name)
self.indention += 1
write(self.nodeinfo(node))
if node.seq.__class__ in (ast.Tuple, ast.List):
self.indention += 1
write('yield None')
self.indention -= 2
- write('yield %s' % self.filter('u\'\'.join(filtered())',
+ write('yield %s' % self.filter('buffereater(filtered)()',
node.filters))
return '\n'.join(buf)
else:
replacements = 'None'
return self.indent(self.nodeinfo(node)) + '\n' +\
- self.indent('yield translate(%r, %r, %r, %s)' % (
+ self.indent('yield context.translate_func(%r, %r, %r, %s)' % (
node.singular,
node.plural,
node.indicator,
return self.constants[node.name]
elif node.name == '_':
self.require_translations = True
- return 'translate'
+ return 'context.translate_func'
return 'context[%r]' % node.name
def handle_compare(self, node):
else:
deque = None
+try:
+ set
+except NameError:
+ from sets import Set as set
+
#: number of maximal range items
MAX_RANGE = 1000000
return getattr(obj, name)
-def debug_context(env, context):
- """
- Use this function in templates to get a printed context.
- """
- from pprint import pformat
- return pformat(context.to_dict())
-debug_context.jinja_context_callable = True
-
-
def safe_range(start, stop=None, step=None):
"""
"Safe" form of range that does not generate too large lists.
return result
+class DebugHelper(object):
+ """
+ Debugging Helper. Available in the template as "debug".
+ """
+ jinja_context_callable = True
+ jinja_allowed_attributes = ['filters']
+
+ def __init__(self):
+ raise TypeError('cannot create %r instances' %
+ self.__class__.__name__)
+
+ def __call__(self, env, context):
+ """Print a nice representation of the context."""
+ from pprint import pformat
+ return pformat(context.to_dict())
+
+ def filters(self, env, context, builtins=True):
+ """List the filters."""
+ from inspect import getdoc
+ strip = set()
+ if not builtins:
+ from jinja.defaults import DEFAULT_FILTERS
+ strip = set(DEFAULT_FILTERS.values())
+ filters = env.filters.items()
+ filters.sort(lambda a, b: cmp(a[0].lower(), b[0].lower()))
+ result = []
+ for name, f in filters:
+ if f in strip:
+ continue
+ doc = '\n'.join(' ' + x for x in (getdoc(f) or '').splitlines())
+ result.append('`%s`\n\n%s' % (name, doc))
+ return '\n\n'.join(result)
+ filters.jinja_context_callable = True
+
+ def __str__(self):
+ print 'use debug() for debugging the context'
+
+
+#: the singleton instance of `DebugHelper`
+debug_helper = object.__new__(DebugHelper)
+
+
class TracebackLoader(object):
"""
Fake importer that just returns the source of a template.