--- /dev/null
+================
+Filter Functions
+================
+
+Filters are a powerful feature of Jinja taken from django which probably took
+it from UNIX. The idea is that you "pipe" a value through some filters to
+do something with it. For example convert it to upper case, escape it or
+replace a substring.
+
+Jinja comes with some builtin filters explained in the `designer documentation`_.
+
+Writing Filters
+===============
+
+A filter basically is a factory function. Thus a function that returns another
+function. We do this because filters can get an unlimited amount of position
+arguments and aditionally should gain access to the environment, context and
+piped value. A simple filter looks like this:
+
+.. sourcecode:: python
+
+ def do_join(d=u''):
+ def wrapped(env, context, value):
+ tmp = []
+ for item in value:
+ tmp.append(env.to_unicode(item))
+ return d.join(tmp)
+ return wrapped
+
+Now you have to register that filter on an environment:
+
+.. sourcecode:: python
+
+ env.filters['join'] = do_join
+
+In fact this filter is already bundled so you won't see any effect. But its
+should explain how such a filter looks like. The template designer can just
+trigger the outer code (eg: call do_join with or without arguments). The
+returned function is then processed by the jinja template engine once all
+filters are created.
+
+If you want to create filters that just operate on string (in fact unicode
+objects) you can use the `stringfilter` decorator:
+
+.. sourcecode:: python
+
+ from jinja.filters import stringfilter
+
+ @stringfilter
+ def do_strip(value):
+ return value.strip()
+
+The wrapped function is created internally by the decorator, any positional
+arguments are forwarded to the filter function. The first argument is always
+the value already converted into a string.
+
+.. _designer documentation: designerdoc.txt
--- /dev/null
+============
+Installation
+============
+
+Jinja requires at least Python 2.3 to work correctly.
+
+Installing a released version
+=============================
+
+As a Python egg (via easy_install)
+----------------------------------
+
+You can install the most recent Jinja version using `easy_install`_::
+
+ sudo easy_install Jinja
+
+This will install a Jinja egg in your Python installation's site-packages
+directory.
+
+
+From the tarball release
+-------------------------
+
+1. Download the most recent tarball from the `download page`_
+2. Unpack the tarball
+3. ``sudo python setup.py install``
+
+Note that the last command will automatically download and install
+`setuptools`_ if you don't already have it installed. This requires a working
+internet connection.
+
+This will install Jinja into your Python installation's site-packages directory.
+
+
+Installing the development version
+==================================
+
+If you want to play around with the code
+----------------------------------------
+
+1. Install `Subversion`_
+2. ``svn co http://trac.pocoo.org/repos/jinja/trunk jinja``
+3. ``cd jinja``
+4. ``ln -s jinja /usr/lib/python2.X/site-packages``
+
+As an alternative to steps 4 you can also do ``python setup.py develop``
+which will install the package via setuptools in development mode.
+
+If you just want the latest features and use them
+-------------------------------------------------
+
+::
+
+ sudo easy_install Jinja==dev
+
+This will install a Jinja egg containing the latest Subversion trunk code
+in your Python installation's site-packages directory. Every time the command
+is run, the sources are updated from Subversion.
+
+
+.. _download page: http://jinja.pocoo.org/download/
+.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
+.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall
+.. _Subversion: http://subversion.tigris.org/
===============
[[list_of_loaders]]
+
+Developing Loaders
+==================
+
+Template loaders are just normal python classes that have to provide some
+functions used to load and translate templates. Here a simple loader implementation
+you can use as base for your own loader:
+
+.. sourcecode:: python
+
+ from os.path import join
+ from jinja.parser import Parser
+ from jinja.exceptions import TemplateNotFound
+
+ class SimpleLoader(object):
+ """
+ Slimmed down version of the included `FileSystemLoader`.
+ """
+
+ def __init__(self, searchpath):
+ self.searchpath = searchpath
+
+ def get_source(self, environment, name, parent):
+ """
+ The get_source function is unused at the moment. However future
+ versions of jinja will use this function for the debugging
+ system. It also works as helper functions for `parse` and
+ `load`.
+ """
+ filename = join(self.searchpath, name)
+ if not path.exists(filename):
+ raise TemplateNotFound(name)
+ f = codecs.open(filename, 'r', environment.template_charset)
+ try:
+ return f.read()
+ finally:
+ f.close()
+
+ def parse(self, environment, name, parent):
+ """
+ Load and parse a template and return the syntax tree.
+ """
+ source = self.get_source(environment, name, parent)
+ return Parser(environment, source, name).parse()
+
+ def load(self, environment, name, translator):
+ """
+ Parse and translate a template. Currently only translation to
+ python code is possible, later jinja versions however will
+ support translating templates to javascript too.
+ """
+ return translator.process(environment, self.parse(environment, name, None))
+
+
+.. admonition:: Note
+
+ Once a loader is bound to an environment you have to omit the environment
+ argument for the public functions `get_source`, `parse` and `load`.
--- /dev/null
+==============
+Test Functions
+==============
+
+Additionally to filters Jinja also supports test functions. Test functions
+always return either ``True`` or ``False``. Inside the template they are available
+using the `is` operator.
+
+Jinja comes with some builtin tests listed in the `designer documentation`_.
+
+Writing Test Functions
+======================
+
+Test functions look exactly like filters mentioned in the `filter documentation`_:
+
+.. sourcecode:: python
+
+ def is_even():
+ def wrapped(env, context, value):
+ return value % 2 == 0
+ return wrapped
+
+Now you have to register that test on an environment:
+
+.. sourcecode:: python
+
+ env.tests['even'] = is_even
+
+.. _designer documentation: designerdoc.txt
+.. _filter documentation: filters.txt
--- /dev/null
+===========
+Translators
+===========
+
+Jinja translates the template sourcecode into executable python code behind
+the secenes. This is done by the python translator which is currently the
+only shipped translator. Because the interface isn't stable it's also not
+recommended to write other translators. However for the next Jinja version
+a JavaScript translator is planned which allows you to translate Jinja
+templates into executable JavaScript code.
Jinja Sandboxed Template Engine
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
from jinja.environment import Environment
--- /dev/null
+# -*- coding: utf-8 -*-
+"""
+ jinja.bakerplugin
+ ~~~~~~~~~~~~~~~~~
+
+ Provide a bridge to baker. Baker is used by some frameworks (namely
+ CherryPy, TurboGears and Pylons) to load templates.
+
+ :copyright: 2007 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+from jinja import Environment
+
+
+class ConfigurationError(Exception):
+ """
+ Raised if an configuration error occoured.
+ """
+
+
+class JinjaPlugin(object):
+ """
+ Implementation of the Plugin API
+ """
+ extension = 'html'
+
+ def __init__(self, extra_vars_func=None, options=None):
+ self.get_extra_vars = extra_vars_func
+ options = options or {}
+ self.extension = options.get('jinja.extension', JinjaPlugin.extension)
+ if 'jinja.environment' in options:
+ self.environment = options['jinja.environment']
+ else:
+ # this wonderful piece of code was brought to you by the turbogears
+ # ppl who want to put template configuration stuff into goddamn
+ # text/plain configuration files.
+ if 'jinja.environment.loader' in options:
+ loader = options['jinja.environment.loader']
+ else:
+ loadername = options.get('jinja.loader') or 'FileSystemLoader'
+ if '.' in loadername:
+ p = loadername.rsplit('.', 1)
+ loadercls = getattr(__import__(p[0], '', '', ['']), p[1])
+ else:
+ from jinja import loaders
+ loadercls = getattr(loaders, loadername)
+ loaderoptions = {}
+ for k, v in options.iteritems():
+ if k.startswith('jinja.loader.'):
+ loaderoptions[k[14:]] = v
+ loader = loadercls(**loaderoptions)
+ self.environment = Environment(
+ block_start_string=options.get('jinja.block_start_string', '{%'),
+ block_end_string=options.get('jinja.block_end_string', '%}'),
+ variable_start_string=options.get('jinja.variable_start_string', '{{'),
+ variable_end_string=options.get('jinja.variable_end_string', '}}'),
+ comment_start_string=options.get('jinja.comment_start_string', '{#'),
+ comment_end_string=options.get('jinja.comment_end_string', '#}'),
+ trim_blocks=str(options.get('jinja.trim_blocks')).lower() in
+ ('true', 'on', 'yes', '1'),
+ template_charset=options.get('jinja.template_charset', 'utf-8'),
+ charset=options.get('jinja.charset', 'utf-8'),
+ namespace=options.get('jinja.namespace'),
+ loader=loader,
+ filters=options.get('jinja.filters'),
+ tests=options.get('jinja.tests')
+ )
+
+ def load_template(self, templatename, template_string=None):
+ """
+ Find a template specified in python 'dot' notation, or load one from
+ a string.
+ """
+ if template_string is not None:
+ return self.environment.from_string(template_string)
+
+ # Translate TG dot notation to normal / template path
+ if '/' not in templatename and '.' not in templatename:
+ templatename = '/' + templatename.replace('.', '/') + '.' + self.extension
+
+ return self.environment.get_template(templatename)
+
+ def render(self, info, format='html', fragment=False, template=None):
+ """
+ Render a template.
+ """
+ if isinstance(template, basestring):
+ template = self.load_template(template)
+
+ if self.get_extra_vars:
+ info.update(self.get_extra_vars())
+
+ return template.render(**info)
Module that helds several data types used in the template engine.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
Jinja default filters and tags.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
from jinja.filters import FILTERS as DEFAULT_FILTERS
from jinja.tests import TESTS as DEFAULT_TESTS
+#: for global objects in later jinja releases. (add stuff like debug())
DEFAULT_NAMESPACE = {
- 'range': xrange
}
Provides a class that holds runtime and parsing time options.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
import re
Get or set the template loader.
"""
self._loader = LoaderWrapper(self, value)
- loader = property(lambda s: s._loader.loader, loader, loader.__doc__)
+ loader = property(lambda s: s._loader, loader, loader.__doc__)
def parse(self, source, filename=None):
"""Function that creates a new parser and parses the source."""
Jinja exceptions.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
Bundled jinja filters.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
from random import choice
jinja.lexer
~~~~~~~~~~~
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
import re
Jinja loader classes.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
Additional nodes for jinja. Look like nodes from the ast.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
from compiler import ast
Implements the template parser.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
import re
Jinja test functions. Used with the "is" operator.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
import re
The submodules of this module provide translators for the jinja ast
which basically just is the python ast with a few more nodes.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
This module translates a jinja ast into python code.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
from compiler import ast
Utility functions.
- :copyright: 2006 by Armin Ronacher.
+ :copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
import re
setup(
name = 'Jinja',
- version = '0.9',
- url = 'http://wsgiarea.pocoo.org/jinja/',
+ version = '1.0',
+ url = 'http://jinja.pocoo.org/',
license = 'BSD',
author = 'Armin Ronacher',
author_email = 'armin.ronacher@active-4.com',
description = 'A small but fast and easy to use stand-alone template engine written in pure python.',
- long_description = '''\
-Jinja is a small but very fast and easy to use stand-alone template engine
-written in pure Python.
-
-Since version 0.6 it uses a new parser that increases parsing performance
-a lot by caching the nodelists on disk if wanted.
-
-It includes multiple template inheritance and other features like simple
-value escaping.
-
-
-Template Syntax
-===============
-
-This is a small example template in which you can see how Jinja's syntax
-looks like::
-
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
- <head>
- <title>My Webpage</title>
- </head
- <body>
- <ul id="navigation">
- {% for item in navigation %}
- <li><a href="{{ item.href }}">{{ item.caption|e }}</a></li>
- {% endfor %}
- </ul>
-
- <h1>My Webpage</h1>
- {{ variable }}
- </body>
- </html>
-
-
-Usage
-=====
-
-Here is a small example::
-
- from jinja import Template, Context, FileSystemLoader
-
- t = Template('mytemplate', FileSystemLoader('/path/to/the/templates'))
- c = Context({
- 'navigation' [
- {'href': '#', 'caption': 'Index'},
- {'href': '#', 'caption': 'Spam'}
- ],
- 'variable': '<strong>hello world</strong>'
- })
- print t.render(c)
-
-
-Unicode Support
-===============
-
-Jinja comes with built-in Unicode support. As a matter of fact, the return
-value of ``Template.render()`` will be a Python unicode object.
-
-You can still output ``str`` objects as well when you encode the result::
-
- s = t.render(c).encode('utf-8')
-
-For more examples check out the `documentation`_ on the `jinja webpage`_.
-
-.. _documentation: http://wsgiarea.pocoo.org/jinja/docs/
-.. _jinja webpage: http://wsgiarea.pocoo.org/jinja/
-''',
- keywords = 'wsgi web templateengine templates',
- packages = ['jinja'],
- platforms = 'any',
+ zip_safe = True,
classifiers = [
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
- 'Topic :: Internet :: WWW/HTTP',
- 'Topic :: Internet :: WWW/HTTP :: Dynamic Content'
- ]
+ 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Topic :: Text Processing :: Markup :: HTML'
+ ],
+ keywords = ['python.templating.engines'],
+ packages = ['jinja'],
+ extras_require = {'plugin': ['setuptools>=0.6a2']},
+ entry_points='''
+ [python.templating.engines]
+ jinja = jinja.bakerplugin:JinjaPlugin[plugin]
+ '''
)