# HG changeset patch # User Steve Losh # Date 1276302732 14400 # Node ID 9a463602589daf9c4064c1896f8b53ae5c435c22 # Parent b2bd9c232faab577c948801c36c3f520bc1a279b Update jinja2 diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/.hgtags --- a/bundled/jinja2/.hgtags Fri Jun 11 20:14:01 2010 -0400 +++ b/bundled/jinja2/.hgtags Fri Jun 11 20:32:12 2010 -0400 @@ -6,3 +6,10 @@ b987be13b8f6603a2135e0f912e8aacb72f21181 2.2.1 2eb624b634a6bf62bc2b8e16a8eca3d41a515b34 2.3 140c54afc249d855745778f74011978bb9ba3439 2.3.1 +e3f873a9d3ffa75f147446db1cb580be2f6403dd 2.4 +d927a7499531e4c0f324a2dc34039f7c09877399 2.4.1 +3f3eadf15f616bf269a6bc2bd037a14e0faf3477 2.5 +3f3eadf15f616bf269a6bc2bd037a14e0faf3477 2.5 +0000000000000000000000000000000000000000 2.5 +0000000000000000000000000000000000000000 2.5 +0dd0062a64804df19c5bbcfc4fad860b2434e09b 2.5 diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/CHANGES --- a/bundled/jinja2/CHANGES Fri Jun 11 20:14:01 2010 -0400 +++ b/bundled/jinja2/CHANGES Fri Jun 11 20:32:12 2010 -0400 @@ -1,16 +1,51 @@ Jinja2 Changelog ================ +Version 2.6 +----------- +(codename to be selected, release date to be announced) + +- StopIteration exceptions raised by functions called from templates + are now intercepted and converted to undefineds. This solves a + lot of debugging grief. (StopIteration is used internally to + abort template execution) +- improved performance of macro calls slightly. + +Version 2.5 +----------- +(codename Incoherence, relased on May 29th 2010) + +- improved the sort filter (should have worked like this for a + long time) by adding support for case insensitive searches. +- fixed a bug for getattribute constant folding. +- support for newstyle gettext translations which result in a + nicer in-template user interface and more consistent + catalogs. (:ref:`newstyle-gettext`) +- it's now possible to register extensions after an environment + was created. + +Version 2.4.1 +------------- +(bugfix release, released on April 20th 2010) + +- fixed an error reporting bug for undefineds. + Version 2.4 ----------- -(codename to be selected, release date unknown) +(codename Correlation, released on April 13th 2010) - the environment template loading functions now transparently pass through a template object if it was passed to it. This makes it possible to import or extend from a template object that was passed to the template. - +- added a :class:`ModuleLoader` that can load templates from + precompiled sources. The environment now features a method + to compile the templates from a configured loader into a zip + file or folder. - the _speedups C extension now supports Python 3. +- added support for autoescaping toggling sections and support + for evaluation contexts (:ref:`eval-context`). +- extensions have a priority now. Version 2.3.1 ------------- diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/MANIFEST.in --- a/bundled/jinja2/MANIFEST.in Fri Jun 11 20:14:01 2010 -0400 +++ b/bundled/jinja2/MANIFEST.in Fri Jun 11 20:32:12 2010 -0400 @@ -6,3 +6,7 @@ recursive-include examples * recursive-include jinja2/testsuite/res * recursive-exclude docs/_build/doctrees * +recursive-exclude jinja2 *.pyc +recursive-exclude docs *.pyc +recursive-exclude jinja2 *.pyo +recursive-exclude docs *.pyo diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/artwork/jinjalogo.svg --- a/bundled/jinja2/artwork/jinjalogo.svg Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/Makefile --- a/bundled/jinja2/docs/Makefile Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html web pickle htmlhelp latex changes linkcheck - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview over all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - -clean: - -rm -rf _build/* - -html: - mkdir -p _build/html _build/doctrees - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html - @echo - @echo "Build finished. The HTML pages are in _build/html." - -pickle: - mkdir -p _build/pickle _build/doctrees - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle - @echo - @echo "Build finished; now you can process the pickle files" - -json: - mkdir -p _build/json _build/doctrees - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json - @echo - @echo "Build finished; now you can process the json files" - -web: pickle - -htmlhelp: - mkdir -p _build/htmlhelp _build/doctrees - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in _build/htmlhelp." - -latex: - mkdir -p _build/latex _build/doctrees - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex - @echo - @echo "Build finished; the LaTeX files are in _build/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - mkdir -p _build/changes _build/doctrees - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes - @echo - @echo "The overview file is in _build/changes." - -linkcheck: - mkdir -p _build/linkcheck _build/doctrees - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in _build/linkcheck/output.txt." diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_build/.ignore diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/.ignore diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/darkmetal.png Binary file bundled/jinja2/docs/_static/darkmetal.png has changed diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/headerbg.png Binary file bundled/jinja2/docs/_static/headerbg.png has changed diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/implementation.png Binary file bundled/jinja2/docs/_static/implementation.png has changed diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/jinja.js --- a/bundled/jinja2/docs/_static/jinja.js Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -$(function() { - - var - toc = $('#toc').show(), - items = $('#toc > ul').hide(); - - $('#toc h3') - .click(function() { - if (items.is(':visible')) { - items.animate({ - height: 'hide', - opacity: 'hide' - }, 300, function() { - toc.removeClass('expandedtoc'); - }); - } - else { - items.animate({ - height: 'show', - opacity: 'show' - }, 400); - toc.addClass('expandedtoc'); - } - }); - -}); diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/jinjabanner.png Binary file bundled/jinja2/docs/_static/jinjabanner.png has changed diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/metal.png Binary file bundled/jinja2/docs/_static/metal.png has changed diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/navigation.png Binary file bundled/jinja2/docs/_static/navigation.png has changed diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/note.png Binary file bundled/jinja2/docs/_static/note.png has changed diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/print.css --- a/bundled/jinja2/docs/_static/print.css Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -div.header, div.relnav, #toc { display: none; } -#contentwrapper { padding: 0; margin: 0; border: none; } -body { color: black; background-color: white; } -div.footer { border-top: 1px solid #888; color: #888; margin-top: 1cm; } -div.footer a { text-decoration: none; } diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/style.css --- a/bundled/jinja2/docs/_static/style.css Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,390 +0,0 @@ -body { - background-color: #222; - margin: 0; - padding: 0; - font-family: 'Georgia', serif; - font-size: 15px; - color: #eee; -} - -div.footer { - border-top: 1px solid #111; - padding: 8px; - font-size: 11px; - text-align: center; - letter-spacing: 0.5px; -} - -div.footer a { - color: #eee; -} - -div.header { - margin: 0 -15px 0 -15px; - background: url(headerbg.png) repeat-x; - border-top: 6px solid #D20000; -} - -div.relnav { - border-bottom: 1px solid #111; - background: url(navigation.png); - margin: 0 -15px 0 -15px; - padding: 2px 20px 0 28px; - line-height: 25px; - color: #aaa; - font-size: 12px; - text-align: center; -} - -div.relnav a { - color: #eee; - font-weight: bold; - text-decoration: none; -} - -div.relnav a:hover { - text-decoration: underline; -} - -#content { - background-color: white; - color: #111; - border-bottom: 1px solid black; - background: url(watermark.png) center 0; - padding: 0 15px 0 15px; - margin: 0; -} - -h1 { - margin: 0; - padding: 15px 0 0 0; -} - -h1.heading { - margin: 0; - padding: 0; - height: 80px; -} - -h1.heading:hover { - background: #222; -} - -h1.heading a { - background: url(jinjabanner.png) no-repeat center 0; - display: block; - width: 100%; - height: 80px; -} - -h1.heading a:focus { - -moz-outline: none; - outline: none; -} - -h1.heading span { - display: none; -} - -#jinjalogo { - background-image: url(jinjalogo.png); - background-repeat: no-repeat; - width: 400px; - height: 160px; -} - -#contentwrapper { - max-width: 680px; - padding: 0 18px 20px 18px; - margin: 0 auto 0 auto; - border-right: 1px solid #eee; - border-left: 1px solid #eee; - background: url(watermark_blur.png) center -114px; -} - -#contentwrapper h2, -#contentwrapper h2 a { - color: #222; - font-size: 24px; - margin: 20px 0 0 0; -} - -#contentwrapper h3, -#contentwrapper h3 a { - color: #b41717; - font-size: 20px; - margin: 20px 0 0 0; -} - -table.docutils { - border-collapse: collapse; - border: 2px solid #aaa; - margin: 0.5em 1.5em 0.5em 1.5em; -} - -table.docutils td { - padding: 2px; - border: 1px solid #ddd; -} - -p, li, dd, dt, blockquote { - color: #333; -} - -blockquote { - margin: 10px 0 10px 20px; -} - -p { - line-height: 20px; - margin-bottom: 0; - margin-top: 10px; -} - -hr { - border-top: 1px solid #ccc; - border-bottom: 0; - border-right: 0; - border-left: 0; - margin-bottom: 10px; - margin-top: 20px; -} - -dl { - margin-left: 10px; -} - -li, dt { - margin-top: 5px; -} - -dt { - font-weight: bold; - color: #000; -} - -dd { - margin-top: 10px; - line-height: 20px; -} - -th { - text-align: left; - padding: 3px; - background-color: #f2f2f2; -} - -a { - color: #b41717; -} - -a:hover { - color: #444; -} - -pre { - background: #ededed url(metal.png); - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; - padding: 5px; - font-size: 13px; - font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace; -} - -tt { - font-size: 13px; - font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace; - color: black; - padding: 1px 2px 1px 2px; - background-color: #fafafa; - border-bottom: 1px solid #eee; -} - -a.reference:hover tt { - border-bottom-color: #aaa; -} - -cite { - /* abusing , it's generated by ReST for `x` */ - font-size: 13px; - font-family: 'Bitstream Vera Sans Mono', 'Monaco', monospace; - font-weight: bold; - font-style: normal; -} - -div.admonition { - margin: 10px 0 10px 0; - padding: 10px 10px 10px 60px; - border: 1px solid #ccc; -} - -div.admonition p.admonition-title { - background-color: #b41717; - color: white; - margin: -10px -10px 10px -60px; - padding: 4px 10px 4px 10px; - font-weight: bold; - font-size: 15px; -} - -div.admonition p.admonition-title a { - color: white!important; -} - -div.admonition-note { - background: url(note.png) no-repeat 10px 40px; -} - -div.admonition-implementation { - background: url(implementation.png) no-repeat 10px 40px; -} - -a.headerlink { - color: #B4B4B4!important; - font-size: 0.8em; - padding: 0 4px 0 4px; - text-decoration: none!important; - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -dt:hover > a.headerlink { - visibility: visible; -} - -a.headerlink:hover { - background-color: #B4B4B4; - color: #F0F0F0!important; -} - -table.indextable { - width: 100%; -} - -table.indextable td { - vertical-align: top; - width: 50%; -} - -table.indextable dl dd { - font-size: 11px; -} - -table.indextable dl dd a { - color: #000; -} - -dl.function dt, -dl.class dt, -dl.exception dt, -dl.method dt, -dl.attribute dt { - font-weight: normal; -} - -dt .descname { - font-weight: bold; - margin-right: 4px; -} - -dt .descname, dt .descclassname { - padding: 0; - background: transparent; - border-bottom: 1px solid #111; -} - -dt .descclassname { - margin-left: 2px; -} - -dl dt big { - font-size: 100%; -} - -ul.search { - margin: 10px 0 0 30px; - padding: 0; -} - -ul.search li { - margin: 10px 0 0 0; - padding: 0; -} - -ul.search div.context { - font-size: 12px; - padding: 4px 0 0 20px; - color: #888; -} - -span.highlight { - background-color: #eee; - border: 1px solid #ccc; -} - -#toc { - margin: 0 -17px 0 -17px; - display: none; -} - -#toc h3 { - float: right; - margin: 5px 5px 0 0; - padding: 0; - font-size: 12px; - color: #777; -} - -#toc h3:hover { - color: #333; - cursor: pointer; -} - -.expandedtoc { - background: #222 url(darkmetal.png); - border-bottom: 1px solid #111; - outline-bottom: 1px solid #000; - padding: 5px; -} - -.expandedtoc h3 { - color: #aaa; - margin: 0!important; -} - -.expandedtoc h3:hover { - color: white!important; -} - -#tod h3:hover { - color: white; -} - -#toc a { - color: #ddd; - text-decoration: none; -} - -#toc a:hover { - color: white; - text-decoration: underline; -} - -#toc ul { - margin: 5px 0 12px 17px; - padding: 0 7px 0 7px; -} - -#toc ul ul { - margin-bottom: 0; -} - -#toc ul li { - margin: 2px 0 0 0; -} diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/watermark.png Binary file bundled/jinja2/docs/_static/watermark.png has changed diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_static/watermark_blur.png Binary file bundled/jinja2/docs/_static/watermark_blur.png has changed diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_templates/.ignore diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_templates/genindex.html --- a/bundled/jinja2/docs/_templates/genindex.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -{% extends "layout.html" %} -{% set title = 'Index' %} -{% block body %} - -

Index

- - {% for key, dummy in genindexentries -%} - {{ key }} {% if not loop.last %}| {% endif %} - {%- endfor %} -
- - {% for key, entries in genindexentries %} -

{{ key }}

- - {%- for column in entries|slice(2) if column %} - - {%- endfor %} -
- {%- for entryname, (links, subitems) in column %} -
{% if links %}{{ entryname|e }} - {% for link in links[1:] %}, [Link]{% endfor %} - {%- else %}{{ entryname|e }}{% endif %}
- {%- if subitems %} -
- {%- for subentryname, subentrylinks in subitems %} -
{{ subentryname|e }} - {%- for link in subentrylinks[1:] %}, [Link]{% endfor -%} -
- {%- endfor %} -
- {%- endif -%} - {%- endfor %} -
- {% endfor %} - -{% endblock %} diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_templates/layout.html --- a/bundled/jinja2/docs/_templates/layout.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ - - - - Jinja2 Documentation - - - - - {%- if builder != 'htmlhelp' %} - - - - - - {%- endif %} - {%- if use_opensearch and builder != 'htmlhelp' %} - - {%- endif %} - {%- if hasdoc('about') %} - - {%- endif %} - - - - {%- if hasdoc('copyright') %} - - {%- endif %} - - {%- if parents %} - - {%- endif %} - {%- if next %} - - {%- endif %} - {%- if prev %} - - {%- endif %} - {% block extrahead %}{% endblock %} - - -
-
-

Jinja

-
-
- {%- if prev %} - « {{ prev.title }} | - {%- endif %} - {{ title }} - {%- if next %} - | {{ next.title }} » - {%- endif %} -
-
- {%- if display_toc %} -
-

Table Of Contents

- {{ toc }} -
- {%- endif %} - {% block body %}{% endblock %} -
-
- - - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_templates/opensearch.xml --- a/bundled/jinja2/docs/_templates/opensearch.xml Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ - - - {{ project }} - Search {{ docstitle }} - utf-8 - - {{ docstitle }} - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_templates/page.html --- a/bundled/jinja2/docs/_templates/page.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -{% extends 'layout.html' %} -{% block body %} - {{ body }} -{% endblock %} diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/_templates/search.html --- a/bundled/jinja2/docs/_templates/search.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -{% extends "layout.html" %} -{% set title = 'Search' %} -{% block extrahead %} - -{% endblock %} -{% block body %} -

Search

-

- From here you can search these documents. Enter your search - words into the box below and click "search". Note that the search - function will automatically search for all of the words. Pages - containing less words won't appear in the result list. -

-

- - -

- {% if search_performed %} -

Search Results

- {% if not search_results %} -

Your search did not match any results.

- {% endif %} - {% endif %} -
- {% if search_results %} -
    - {% for href, caption, context in search_results %} -
  • {{ caption }} -
    {{ context|e }}
    -
  • - {% endfor %} -
- {% endif %} -
-{% endblock %} diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/api.rst --- a/bundled/jinja2/docs/api.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,684 +0,0 @@ -API -=== - -.. module:: jinja2 - :synopsis: public Jinja2 API - -This document describes the API to Jinja2 and not the template language. It -will be most useful as reference to those implementing the template interface -to the application and not those who are creating Jinja2 templates. - -Basics ------- - -Jinja2 uses a central object called the template :class:`Environment`. -Instances of this class are used to store the configuration, global objects -and are used to load templates from the file system or other locations. -Even if you are creating templates from strings by using the constructor of -:class:`Template` class, an environment is created automatically for you, -albeit a shared one. - -Most applications will create one :class:`Environment` object on application -initialization and use that to load templates. In some cases it's however -useful to have multiple environments side by side, if different configurations -are in use. - -The simplest way to configure Jinja2 to load templates for your application -looks roughly like this:: - - from jinja2 import Environment, PackageLoader - env = Environment(loader=PackageLoader('yourapplication', 'templates')) - -This will create a template environment with the default settings and a -loader that looks up the templates in the `templates` folder inside the -`yourapplication` python package. Different loaders are available -and you can also write your own if you want to load templates from a -database or other resources. - -To load a template from this environment you just have to call the -:meth:`get_template` method which then returns the loaded :class:`Template`:: - - template = env.get_template('mytemplate.html') - -To render it with some variables, just call the :meth:`render` method:: - - print template.render(the='variables', go='here') - -Using a template loader rather then passing strings to :class:`Template` -or :meth:`Environment.from_string` has multiple advantages. Besides being -a lot easier to use it also enables template inheritance. - - -Unicode -------- - -Jinja2 is using Unicode internally which means that you have to pass Unicode -objects to the render function or bytestrings that only consist of ASCII -characters. Additionally newlines are normalized to one end of line -sequence which is per default UNIX style (``\n``). - -Python 2.x supports two ways of representing string objects. One is the -`str` type and the other is the `unicode` type, both of which extend a type -called `basestring`. Unfortunately the default is `str` which should not -be used to store text based information unless only ASCII characters are -used. With Python 2.6 it is possible to make `unicode` the default on a per -module level and with Python 3 it will be the default. - -To explicitly use a Unicode string you have to prefix the string literal -with a `u`: ``u'Hänsel und Gretel sagen Hallo'``. That way Python will -store the string as Unicode by decoding the string with the character -encoding from the current Python module. If no encoding is specified this -defaults to 'ASCII' which means that you can't use any non ASCII identifier. - -To set a better module encoding add the following comment to the first or -second line of the Python module using the Unicode literal:: - - # -*- coding: utf-8 -*- - -We recommend utf-8 as Encoding for Python modules and templates as it's -possible to represent every Unicode character in utf-8 and because it's -backwards compatible to ASCII. For Jinja2 the default encoding of templates -is assumed to be utf-8. - -It is not possible to use Jinja2 to process non-Unicode data. The reason -for this is that Jinja2 uses Unicode already on the language level. For -example Jinja2 treats the non-breaking space as valid whitespace inside -expressions which requires knowledge of the encoding or operating on an -Unicode string. - -For more details about Unicode in Python have a look at the excellent -`Unicode documentation`_. - -Another important thing is how Jinja2 is handling string literals in -templates. A naive implementation would be using Unicode strings for -all string literals but it turned out in the past that this is problematic -as some libraries are typechecking against `str` explicitly. For example -`datetime.strftime` does not accept Unicode arguments. To not break it -completely Jinja2 is returning `str` for strings that fit into ASCII and -for everything else `unicode`: - ->>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module ->>> m.a -'foo' ->>> m.b -u'f\xf6\xf6' - - -.. _Unicode documentation: http://docs.python.org/dev/howto/unicode.html - -High Level API --------------- - -The high-level API is the API you will use in the application to load and -render Jinja2 templates. The :ref:`low-level-api` on the other side is only -useful if you want to dig deeper into Jinja2 or :ref:`develop extensions -`. - -.. autoclass:: Environment([options]) - :members: from_string, get_template, select_template, - get_or_select_template, join_path, extend, compile_expression - - .. attribute:: shared - - If a template was created by using the :class:`Template` constructor - an environment is created automatically. These environments are - created as shared environments which means that multiple templates - may have the same anonymous environment. For all shared environments - this attribute is `True`, else `False`. - - .. attribute:: sandboxed - - If the environment is sandboxed this attribute is `True`. For the - sandbox mode have a look at the documentation for the - :class:`~jinja2.sandbox.SandboxedEnvironment`. - - .. attribute:: filters - - A dict of filters for this environment. As long as no template was - loaded it's safe to add new filters or remove old. For custom filters - see :ref:`writing-filters`. For valid filter names have a look at - :ref:`identifier-naming`. - - .. attribute:: tests - - A dict of test functions for this environment. As long as no - template was loaded it's safe to modify this dict. For custom tests - see :ref:`writing-tests`. For valid test names have a look at - :ref:`identifier-naming`. - - .. attribute:: globals - - A dict of global variables. These variables are always available - in a template. As long as no template was loaded it's safe - to modify this dict. For more details see :ref:`global-namespace`. - For valid object names have a look at :ref:`identifier-naming`. - - .. automethod:: overlay([options]) - - .. method:: undefined([hint, obj, name, exc]) - - Creates a new :class:`Undefined` object for `name`. This is useful - for filters or functions that may return undefined objects for - some operations. All parameters except of `hint` should be provided - as keyword parameters for better readability. The `hint` is used as - error message for the exception if provided, otherwise the error - message will be generated from `obj` and `name` automatically. The exception - provided as `exc` is raised if something with the generated undefined - object is done that the undefined object does not allow. The default - exception is :exc:`UndefinedError`. If a `hint` is provided the - `name` may be ommited. - - The most common way to create an undefined object is by providing - a name only:: - - return environment.undefined(name='some_name') - - This means that the name `some_name` is not defined. If the name - was from an attribute of an object it makes sense to tell the - undefined object the holder object to improve the error message:: - - if not hasattr(obj, 'attr'): - return environment.undefined(obj=obj, name='attr') - - For a more complex example you can provide a hint. For example - the :func:`first` filter creates an undefined object that way:: - - return environment.undefined('no first item, sequence was empty') - - If it the `name` or `obj` is known (for example because an attribute - was accessed) it shold be passed to the undefined object, even if - a custom `hint` is provided. This gives undefined objects the - possibility to enhance the error message. - -.. autoclass:: Template - :members: module, make_module - - .. attribute:: globals - - The dict with the globals of that template. It's unsafe to modify - this dict as it may be shared with other templates or the environment - that loaded the template. - - .. attribute:: name - - The loading name of the template. If the template was loaded from a - string this is `None`. - - .. attribute:: filename - - The filename of the template on the file system if it was loaded from - there. Otherwise this is `None`. - - .. automethod:: render([context]) - - .. automethod:: generate([context]) - - .. automethod:: stream([context]) - - -.. autoclass:: jinja2.environment.TemplateStream() - :members: disable_buffering, enable_buffering, dump - - -.. _identifier-naming: - -Notes on Identifiers --------------------- - -Jinja2 uses the regular Python 2.x naming rules. Valid identifiers have to -match ``[a-zA-Z_][a-zA-Z0-9_]*``. As a matter of fact non ASCII characters -are currently not allowed. This limitation will probably go away as soon as -unicode identifiers are fully specified for Python 3. - -Filters and tests are looked up in separate namespaces and have slightly -modified identifier syntax. Filters and tests may contain dots to group -filters and tests by topic. For example it's perfectly valid to add a -function into the filter dict and call it `to.unicode`. The regular -expression for filter and test identifiers is -``[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*```. - - -Undefined Types ---------------- - -These classes can be used as undefined types. The :class:`Environment` -constructor takes an `undefined` parameter that can be one of those classes -or a custom subclass of :class:`Undefined`. Whenever the template engine is -unable to look up a name or access an attribute one of those objects is -created and returned. Some operations on undefined values are then allowed, -others fail. - -The closest to regular Python behavior is the `StrictUndefined` which -disallows all operations beside testing if it's an undefined object. - -.. autoclass:: jinja2.Undefined() - - .. attribute:: _undefined_hint - - Either `None` or an unicode string with the error message for - the undefined object. - - .. attribute:: _undefined_obj - - Either `None` or the owner object that caused the undefined object - to be created (for example because an attribute does not exist). - - .. attribute:: _undefined_name - - The name for the undefined variable / attribute or just `None` - if no such information exists. - - .. attribute:: _undefined_exception - - The exception that the undefined object wants to raise. This - is usually one of :exc:`UndefinedError` or :exc:`SecurityError`. - - .. method:: _fail_with_undefined_error(\*args, \**kwargs) - - When called with any arguments this method raises - :attr:`_undefined_exception` with an error message generated - from the undefined hints stored on the undefined object. - -.. autoclass:: jinja2.DebugUndefined() - -.. autoclass:: jinja2.StrictUndefined() - -Undefined objects are created by calling :attr:`undefined`. - -.. admonition:: Implementation - - :class:`Undefined` objects are implemented by overriding the special - `__underscore__` methods. For example the default :class:`Undefined` - class implements `__unicode__` in a way that it returns an empty - string, however `__int__` and others still fail with an exception. To - allow conversion to int by returning ``0`` you can implement your own:: - - class NullUndefined(Undefined): - def __int__(self): - return 0 - def __float__(self): - return 0.0 - - To disallow a method, just override it and raise - :attr:`~Undefined._undefined_exception`. Because this is a very common - idom in undefined objects there is the helper method - :meth:`~Undefined._fail_with_undefined_error` that does the error raising - automatically. Here a class that works like the regular :class:`Undefined` - but chokes on iteration:: - - class NonIterableUndefined(Undefined): - __iter__ = Undefined._fail_with_undefined_error - - -The Context ------------ - -.. autoclass:: jinja2.runtime.Context() - :members: resolve, get_exported, get_all - - .. attribute:: parent - - A dict of read only, global variables the template looks up. These - can either come from another :class:`Context`, from the - :attr:`Environment.globals` or :attr:`Template.globals` or points - to a dict created by combining the globals with the variables - passed to the render function. It must not be altered. - - .. attribute:: vars - - The template local variables. This list contains environment and - context functions from the :attr:`parent` scope as well as local - modifications and exported variables from the template. The template - will modify this dict during template evaluation but filters and - context functions are not allowed to modify it. - - .. attribute:: environment - - The environment that loaded the template. - - .. attribute:: exported_vars - - This set contains all the names the template exports. The values for - the names are in the :attr:`vars` dict. In order to get a copy of the - exported variables as dict, :meth:`get_exported` can be used. - - .. attribute:: name - - The load name of the template owning this context. - - .. attribute:: blocks - - A dict with the current mapping of blocks in the template. The keys - in this dict are the names of the blocks, and the values a list of - blocks registered. The last item in each list is the current active - block (latest in the inheritance chain). - - .. automethod:: jinja2.runtime.Context.call(callable, \*args, \**kwargs) - - -.. admonition:: Implementation - - Context is immutable for the same reason Python's frame locals are - immutable inside functions. Both Jinja2 and Python are not using the - context / frame locals as data storage for variables but only as primary - data source. - - When a template accesses a variable the template does not define, Jinja2 - looks up the variable in the context, after that the variable is treated - as if it was defined in the template. - - -.. _loaders: - -Loaders -------- - -Loaders are responsible for loading templates from a resource such as the -file system. The environment will keep the compiled modules in memory like -Python's `sys.modules`. Unlike `sys.modules` however this cache is limited in -size by default and templates are automatically reloaded. -All loaders are subclasses of :class:`BaseLoader`. If you want to create your -own loader, subclass :class:`BaseLoader` and override `get_source`. - -.. autoclass:: jinja2.BaseLoader - :members: get_source, load - -Here a list of the builtin loaders Jinja2 provides: - -.. autoclass:: jinja2.FileSystemLoader - -.. autoclass:: jinja2.PackageLoader - -.. autoclass:: jinja2.DictLoader - -.. autoclass:: jinja2.FunctionLoader - -.. autoclass:: jinja2.PrefixLoader - -.. autoclass:: jinja2.ChoiceLoader - - -.. _bytecode-cache: - -Bytecode Cache --------------- - -Jinja 2.1 and higher support external bytecode caching. Bytecode caches make -it possible to store the generated bytecode on the file system or a different -location to avoid parsing the templates on first use. - -This is especially useful if you have a web application that is initialized on -the first request and Jinja compiles many templates at once which slows down -the application. - -To use a bytecode cache, instanciate it and pass it to the :class:`Environment`. - -.. autoclass:: jinja2.BytecodeCache - :members: load_bytecode, dump_bytecode, clear - -.. autoclass:: jinja2.bccache.Bucket - :members: write_bytecode, load_bytecode, bytecode_from_string, - bytecode_to_string, reset - - .. attribute:: environment - - The :class:`Environment` that created the bucket. - - .. attribute:: key - - The unique cache key for this bucket - - .. attribute:: code - - The bytecode if it's loaded, otherwise `None`. - - -Builtin bytecode caches: - -.. autoclass:: jinja2.FileSystemBytecodeCache - -.. autoclass:: jinja2.MemcachedBytecodeCache - - -Utilities ---------- - -These helper functions and classes are useful if you add custom filters or -functions to a Jinja2 environment. - -.. autofunction:: jinja2.environmentfilter - -.. autofunction:: jinja2.contextfilter - -.. autofunction:: jinja2.environmentfunction - -.. autofunction:: jinja2.contextfunction - -.. function:: escape(s) - - Convert the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in string `s` - to HTML-safe sequences. Use this if you need to display text that might - contain such characters in HTML. This function will not escaped objects - that do have an HTML representation such as already escaped data. - - The return value is a :class:`Markup` string. - -.. autofunction:: jinja2.clear_caches - -.. autofunction:: jinja2.is_undefined - -.. autoclass:: jinja2.Markup([string]) - :members: escape, unescape, striptags - -.. admonition:: Note - - The Jinja2 :class:`Markup` class is compatible with at least Pylons and - Genshi. It's expected that more template engines and framework will pick - up the `__html__` concept soon. - - -Exceptions ----------- - -.. autoexception:: jinja2.TemplateError - -.. autoexception:: jinja2.UndefinedError - -.. autoexception:: jinja2.TemplateNotFound - -.. autoexception:: jinja2.TemplatesNotFound - -.. autoexception:: jinja2.TemplateSyntaxError - - .. attribute:: message - - The error message as utf-8 bytestring. - - .. attribute:: lineno - - The line number where the error occurred - - .. attribute:: name - - The load name for the template as unicode string. - - .. attribute:: filename - - The filename that loaded the template as bytestring in the encoding - of the file system (most likely utf-8 or mbcs on Windows systems). - - The reason why the filename and error message are bytestrings and not - unicode strings is that Python 2.x is not using unicode for exceptions - and tracebacks as well as the compiler. This will change with Python 3. - -.. autoexception:: jinja2.TemplateAssertionError - - -.. _writing-filters: - -Custom Filters --------------- - -Custom filters are just regular Python functions that take the left side of -the filter as first argument and the the arguments passed to the filter as -extra arguments or keyword arguments. - -For example in the filter ``{{ 42|myfilter(23) }}`` the function would be -called with ``myfilter(42, 23)``. Here for example a simple filter that can -be applied to datetime objects to format them:: - - def datetimeformat(value, format='%H:%M / %d-%m-%Y'): - return value.strftime(format) - -You can register it on the template environment by updating the -:attr:`~Environment.filters` dict on the environment:: - - environment.filters['datetimeformat'] = datetimeformat - -Inside the template it can then be used as follows: - -.. sourcecode:: jinja - - written on: {{ article.pub_date|datetimeformat }} - publication date: {{ article.pub_date|datetimeformat('%d-%m-%Y') }} - -Filters can also be passed the current template context or environment. This -is useful if a filter wants to return an undefined value or check the current -:attr:`~Environment.autoescape` setting. For this purpose two decorators -exist: :func:`environmentfilter` and :func:`contextfilter`. - -Here a small example filter that breaks a text into HTML line breaks and -paragraphs and marks the return value as safe HTML string if autoescaping is -enabled:: - - import re - from jinja2 import environmentfilter, Markup, escape - - _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}') - - @environmentfilter - def nl2br(environment, value): - result = u'\n\n'.join(u'

%s

' % p.replace('\n', '
\n') - for p in _paragraph_re.split(escape(value))) - if environment.autoescape: - result = Markup(result) - return result - -Context filters work the same just that the first argument is the current -active :class:`Context` rather then the environment. - - -.. _writing-tests: - -Custom Tests ------------- - -Tests work like filters just that there is no way for a test to get access -to the environment or context and that they can't be chained. The return -value of a test should be `True` or `False`. The purpose of a test is to -give the template designers the possibility to perform type and conformability -checks. - -Here a simple test that checks if a variable is a prime number:: - - import math - - def is_prime(n): - if n == 2: - return True - for i in xrange(2, int(math.ceil(math.sqrt(n))) + 1): - if n % i == 0: - return False - return True - - -You can register it on the template environment by updating the -:attr:`~Environment.tests` dict on the environment:: - - environment.tests['prime'] = is_prime - -A template designer can then use the test like this: - -.. sourcecode:: jinja - - {% if 42 is prime %} - 42 is a prime number - {% else %} - 42 is not a prime number - {% endif %} - - -.. _global-namespace: - -The Global Namespace --------------------- - -Variables stored in the :attr:`Environment.globals` dict are special as they -are available for imported templates too, even if they are imported without -context. This is the place where you can put variables and functions -that should be available all the time. Additionally :attr:`Template.globals` -exist that are variables available to a specific template that are available -to all :meth:`~Template.render` calls. - - -.. _low-level-api: - -Low Level API -------------- - -The low level API exposes functionality that can be useful to understand some -implementation details, debugging purposes or advanced :ref:`extension -` techniques. Unless you know exactly what you are doing we -don't recommend using any of those. - -.. automethod:: Environment.lex - -.. automethod:: Environment.parse - -.. automethod:: Environment.preprocess - -.. automethod:: Template.new_context - -.. method:: Template.root_render_func(context) - - This is the low level render function. It's passed a :class:`Context` - that has to be created by :meth:`new_context` of the same template or - a compatible template. This render function is generated by the - compiler from the template code and returns a generator that yields - unicode strings. - - If an exception in the template code happens the template engine will - not rewrite the exception but pass through the original one. As a - matter of fact this function should only be called from within a - :meth:`render` / :meth:`generate` / :meth:`stream` call. - -.. attribute:: Template.blocks - - A dict of block render functions. Each of these functions works exactly - like the :meth:`root_render_func` with the same limitations. - -.. attribute:: Template.is_up_to_date - - This attribute is `False` if there is a newer version of the template - available, otherwise `True`. - -.. admonition:: Note - - The low-level API is fragile. Future Jinja2 versions will try not to - change it in a backwards incompatible way but modifications in the Jinja2 - core may shine through. For example if Jinja2 introduces a new AST node - in later versions that may be returned by :meth:`~Environment.parse`. - -The Meta API ------------- - -.. versionadded:: 2.2 - -The meta API returns some information about abstract syntax trees that -could help applications to implement more advanced template concepts. All -the functions of the meta API operate on an abstract syntax tree as -returned by the :meth:`Environment.parse` method. - -.. autofunction:: jinja2.meta.find_undeclared_variables - -.. autofunction:: jinja2.meta.find_referenced_templates diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/cache_extension.py --- a/bundled/jinja2/docs/cache_extension.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -from jinja2 import nodes -from jinja2.ext import Extension - - -class FragmentCacheExtension(Extension): - # a set of names that trigger the extension. - tags = set(['cache']) - - def __init__(self, environment): - super(FragmentCacheExtension, self).__init__(environment) - - # add the defaults to the environment - environment.extend( - fragment_cache_prefix='', - fragment_cache=None - ) - - def parse(self, parser): - # the first token is the token that started the tag. In our case - # we only listen to ``'cache'`` so this will be a name token with - # `cache` as value. We get the line number so that we can give - # that line number to the nodes we create by hand. - lineno = parser.stream.next().lineno - - # now we parse a single expression that is used as cache key. - args = [parser.parse_expression()] - - # if there is a comma, the user provided a timeout. If not use - # None as second parameter. - if parser.stream.skip_if('comma'): - args.append(parser.parse_expression()) - else: - args.append(nodes.Const(None)) - - # now we parse the body of the cache block up to `endcache` and - # drop the needle (which would always be `endcache` in that case) - body = parser.parse_statements(['name:endcache'], drop_needle=True) - - # now return a `CallBlock` node that calls our _cache_support - # helper method on this extension. - return nodes.CallBlock(self.call_method('_cache_support', args), - [], [], body).set_lineno(lineno) - - def _cache_support(self, name, timeout, caller): - """Helper callback.""" - key = self.environment.fragment_cache_prefix + name - - # try to load the block from the cache - # if there is no fragment in the cache, render it and store - # it in the cache. - rv = self.environment.fragment_cache.get(key) - if rv is not None: - return rv - rv = caller() - self.environment.fragment_cache.add(key, rv, timeout) - return rv diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/changelog.rst --- a/bundled/jinja2/docs/changelog.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -.. module:: jinja2 - -.. include:: ../CHANGES diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/conf.py --- a/bundled/jinja2/docs/conf.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Jinja2 documentation build configuration file, created by -# sphinx-quickstart on Sun Apr 27 21:42:41 2008. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# The contents of this file are pickled, so don't put values in the namespace -# that aren't pickleable (module imports are okay, they're removed automatically). -# -# All configuration values have a default value; values that are commented out -# serve to show the default value. - -import sys, os - -# If your extensions are in another directory, add it here. If the directory -# is relative to the documentation root, use os.path.abspath to make it -# absolute, like shown here. -sys.path.append(os.path.dirname(os.path.abspath(__file__))) - -# General configuration -# --------------------- - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'jinjaext'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General substitutions. -project = 'Jinja2' -copyright = '2008, Armin Ronacher' - -# The default replacements for |version| and |release|, also used in various -# other places throughout the built documents. -# -# The short X.Y version. -version = '2.0' -# The full version, including alpha/beta/rc tags. -release = '2.0' - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'jinjaext.JinjaStyle' - - -# Options for HTML output -# ----------------------- - -# The style sheet to use for HTML and HTML Help pages. A file of that name -# must exist either in Sphinx' static/ path, or in one of the custom paths -# given in html_static_path. -html_style = 'style.css' - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# no modindex -html_use_modindex = False - -# If true, the reST sources are included in the HTML build as _sources/. -#html_copy_source = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. -#html_use_opensearch = False - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Jinja2doc' - - -# Options for LaTeX output -# ------------------------ - -# The paper size ('letter' or 'a4'). -latex_paper_size = 'a4' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, document class [howto/manual]). -latex_documents = [ - ('index', 'Jinja2.tex', 'Jinja2 Documentation', 'Armin Ronacher', 'manual', 'toctree_only'), -] - -# Additional stuff for the LaTeX preamble. -latex_preamble = ''' -\usepackage{palatino} -\definecolor{TitleColor}{rgb}{0.7,0,0} -\definecolor{InnerLinkColor}{rgb}{0.7,0,0} -\definecolor{OuterLinkColor}{rgb}{0.8,0,0} -\definecolor{VerbatimColor}{rgb}{0.985,0.985,0.985} -\definecolor{VerbatimBorderColor}{rgb}{0.8,0.8,0.8} -''' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -latex_use_modindex = False diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/extensions.rst --- a/bundled/jinja2/docs/extensions.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,268 +0,0 @@ -.. _jinja-extensions: - -Extensions -========== - -Jinja2 supports extensions that can add extra filters, tests, globals or even -extend the parser. The main motivation of extensions is it to move often used -code into a reusable class like adding support for internationalization. - - -Adding Extensions ------------------ - -Extensions are added to the Jinja2 environment at creation time. Once the -environment is created additional extensions cannot be added. To add an -extension pass a list of extension classes or import paths to the -`environment` parameter of the :class:`Environment` constructor. The following -example creates a Jinja2 environment with the i18n extension loaded:: - - jinja_env = Environment(extensions=['jinja2.ext.i18n']) - - -.. _i18n-extension: - -i18n Extension --------------- - -**Import name:** `jinja2.ext.i18n` - -Jinja2 currently comes with one extension, the i18n extension. It can be -used in combination with `gettext`_ or `babel`_. If the i18n extension is -enabled Jinja2 provides a `trans` statement that marks the wrapped string as -translatable and calls `gettext`. - -After enabling dummy `_` function that forwards calls to `gettext` is added -to the environment globals. An internationalized application then has to -provide at least an `gettext` and optoinally a `ngettext` function into the -namespace. Either globally or for each rendering. - -After enabling of the extension the environment provides the following -additional methods: - -.. method:: jinja2.Environment.install_gettext_translations(translations) - - Installs a translation globally for that environment. The tranlations - object provided must implement at least `ugettext` and `ungettext`. - The `gettext.NullTranslations` and `gettext.GNUTranslations` classes - as well as `Babel`_\s `Translations` class are supported. - -.. method:: jinja2.Environment.install_null_translations() - - Install dummy gettext functions. This is useful if you want to prepare - the application for internationalization but don't want to implement the - full internationalization system yet. - -.. method:: jinja2.Environment.uninstall_gettext_translations() - - Uninstall the translations again. - -.. method:: jinja2.Environment.extract_translations(source) - - Extract localizable strings from the given template node or source. - - For every string found this function yields a ``(lineno, function, - message)`` tuple, where: - - * `lineno` is the number of the line on which the string was found, - * `function` is the name of the `gettext` function used (if the - string was extracted from embedded Python code), and - * `message` is the string itself (a `unicode` object, or a tuple - of `unicode` objects for functions with multiple string arguments). - - If `Babel`_ is installed :ref:`the babel integration ` - can be used to extract strings for babel. - -For a web application that is available in multiple languages but gives all -the users the same language (for example a multilingual forum software -installed for a French community) may load the translations once and add the -translation methods to the environment at environment generation time:: - - translations = get_gettext_translations() - env = Environment(extensions=['jinja2.ext.i18n']) - env.install_gettext_translations(translations) - -The `get_gettext_translations` function would return the translator for the -current configuration. (For example by using `gettext.find`) - -The usage of the `i18n` extension for template designers is covered as part -:ref:`of the template documentation `. - -.. _gettext: http://docs.python.org/dev/library/gettext -.. _Babel: http://babel.edgewall.org/ - - -Expression Statement --------------------- - -**Import name:** `jinja2.ext.do` - -The "do" aka expression-statement extension adds a simple `do` tag to the -template engine that works like a variable expression but ignores the -return value. - -.. _loopcontrols-extension: - -Loop Controls -------------- - -**Import name:** `jinja2.ext.loopcontrols` - -This extension adds support for `break` and `continue` in loops. After -enabling Jinja2 provides those two keywords which work exactly like in -Python. - -.. _with-extension: - -With Statement --------------- - -**Import name:** `jinja2.ext.with_` - -.. versionadded:: 2.3 - -This extension adds support for the with keyword. Using this keyword it -is possible to enforce a nested scope in a template. Variables can be -declared directly in the opening block of the with statement or using a -standard `set` statement directly within. - - -.. _writing-extensions: - -Writing Extensions ------------------- - -.. module:: jinja2.ext - -By writing extensions you can add custom tags to Jinja2. This is a non trival -task and usually not needed as the default tags and expressions cover all -common use cases. The i18n extension is a good example of why extensions are -useful, another one would be fragment caching. - -When writing extensions you have to keep in mind that you are working with the -Jinja2 template compiler which does not validate the node tree you are possing -to it. If the AST is malformed you will get all kinds of compiler or runtime -errors that are horrible to debug. Always make sure you are using the nodes -you create correctly. The API documentation below shows which nodes exist and -how to use them. - -Example Extension -~~~~~~~~~~~~~~~~~ - -The following example implements a `cache` tag for Jinja2 by using the -`Werkzeug`_ caching contrib module: - -.. literalinclude:: cache_extension.py - :language: python - -And here is how you use it in an environment:: - - from jinja2 import Environment - from werkzeug.contrib.cache import SimpleCache - - env = Environment(extensions=[FragmentCacheExtension]) - env.fragment_cache = SimpleCache() - -Inside the template it's then possible to mark blocks as cacheable. The -following example caches a sidebar for 300 seconds: - -.. sourcecode:: html+jinja - - {% cache 'sidebar', 300 %} - - {% endcache %} - -.. _Werkzeug: http://werkzeug.pocoo.org/ - -Extension API -~~~~~~~~~~~~~ - -Extensions always have to extend the :class:`jinja2.ext.Extension` class: - -.. autoclass:: Extension - :members: preprocess, filter_stream, parse, attr, call_method - - .. attribute:: identifier - - The identifier of the extension. This is always the true import name - of the extension class and must not be changed. - - .. attribute:: tags - - If the extension implements custom tags this is a set of tag names - the extension is listening for. - -Parser API -~~~~~~~~~~ - -The parser passed to :meth:`Extension.parse` provides ways to parse -expressions of different types. The following methods may be used by -extensions: - -.. autoclass:: jinja2.parser.Parser - :members: parse_expression, parse_tuple, parse_assign_target, - parse_statements, free_identifier, fail - - .. attribute:: filename - - The filename of the template the parser processes. This is **not** - the load name of the template. For the load name see :attr:`name`. - For templates that were not loaded form the file system this is - `None`. - - .. attribute:: name - - The load name of the template. - - .. attribute:: stream - - The current :class:`~jinja2.lexer.TokenStream` - -.. autoclass:: jinja2.lexer.TokenStream - :members: push, look, eos, skip, next, next_if, skip_if, expect - - .. attribute:: current - - The current :class:`~jinja2.lexer.Token`. - -.. autoclass:: jinja2.lexer.Token - :members: test, test_any - - .. attribute:: lineno - - The line number of the token - - .. attribute:: type - - The type of the token. This string is interned so you may compare - it with arbitrary strings using the `is` operator. - - .. attribute:: value - - The value of the token. - -There is also a utility function in the lexer module that can count newline -characters in strings: - -.. autofunction:: jinja2.lexer.count_newlines - -AST -~~~ - -The AST (Abstract Syntax Tree) is used to represent a template after parsing. -It's build of nodes that the compiler then converts into executable Python -code objects. Extensions that provide custom statements can return nodes to -execute custom Python code. - -The list below describes all nodes that are currently available. The AST may -change between Jinja2 versions but will stay backwards compatible. - -For more information have a look at the repr of :meth:`jinja2.Environment.parse`. - -.. module:: jinja2.nodes - -.. jinjanodes:: - -.. autoexception:: Impossible diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/faq.rst --- a/bundled/jinja2/docs/faq.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +0,0 @@ -Frequently Asked Questions -========================== - -This page answers some of the often asked questions about Jinja. - -.. highlight:: html+jinja - -Why is it called Jinja? ------------------------ - -The name Jinja was chosen because it's the name of a Japanese temple and -temple and template share a similar pronunciation. It is not named after -the capital city of Uganda. - -How fast is it? ---------------- - -We really hate benchmarks especially since they don't reflect much. The -performance of a template depends on many factors and you would have to -benchmark different engines in different situations. The benchmarks from the -testsuite show that Jinja2 has a similar performance to `Mako`_ and is between -10 and 20 times faster than Django's template engine or Genshi. These numbers -should be taken with tons of salt as the benchmarks that took these numbers -only test a few performance related situations such as looping. Generally -speaking the performance of a template engine doesn't matter much as the -usual bottleneck in a web application is either the database or the application -code. - -.. _Mako: http://www.makotemplates.org/ - -How Compatible is Jinja2 with Django? -------------------------------------- - -The default syntax of Jinja2 matches Django syntax in many ways. However -this similarity doesn't mean that you can use a Django template unmodified -in Jinja2. For example filter arguments use a function call syntax rather -than a colon to separate filter name and arguments. Additionally the -extension interface in Jinja is fundamentally different from the Django one -which means that your custom tags won't work any longer. - -Generally speaking you will use much less custom extensions as the Jinja -template system allows you to use a certain subset of Python expressions -which can replace most Django extensions. For example instead of using -something like this:: - - {% load comments %} - {% get_latest_comments 10 as latest_comments %} - {% for comment in latest_comments %} - ... - {% endfor %} - -You will most likely provide an object with attributes to retrieve -comments from the database:: - - {% for comment in models.comments.latest(10) %} - ... - {% endfor %} - -Or directly provide the model for quick testing:: - - {% for comment in Comment.objects.order_by('-pub_date')[:10] %} - ... - {% endfor %} - -Please keep in mind that even though you may put such things into templates -it still isn't a good idea. Queries should go into the view code and not -the template! - -Isn't it a terrible idea to put Logic into Templates? ------------------------------------------------------ - -Without a doubt you should try to remove as much logic from templates as -possible. But templates without any logic mean that you have to do all -the processing in the code which is boring and stupid. A template engine -that does that is shipped with Python and called `string.Template`. Comes -without loops and if conditions and is by far the fastest template engine -you can get for Python. - -So some amount of logic is required in templates to keep everyone happy. -And Jinja leaves it pretty much to you how much logic you want to put into -templates. There are some restrictions in what you can do and what not. - -Jinja2 neither allows you to put arbitrary Python code into templates nor -does it allow all Python expressions. The operators are limited to the -most common ones and more advanced expressions such as list comprehensions -and generator expressions are not supported. This keeps the template engine -easier to maintain and templates more readable. - -Why is Autoescaping not the Default? ------------------------------------- - -There are multiple reasons why automatic escaping is not the default mode -and also not the recommended one. While automatic escaping of variables -means that you will less likely have an XSS problem it also causes a huge -amount of extra processing in the template engine which can cause serious -performance problems. As Python doesn't provide a way to mark strings as -unsafe Jinja has to hack around that limitation by providing a custom -string class (the :class:`Markup` string) that safely interacts with safe -and unsafe strings. - -With explicit escaping however the template engine doesn't have to perform -any safety checks on variables. Also a human knows not to escape integers -or strings that may never contain characters one has to escape or already -HTML markup. For example when iterating over a list over a table of -integers and floats for a table of statistics the template designer can -omit the escaping because he knows that integers or floats don't contain -any unsafe parameters. - -Additionally Jinja2 is a general purpose template engine and not only used -for HTML/XML generation. For example you may generate LaTeX, emails, -CSS, JavaScript, or configuration files. - -Why is the Context immutable? ------------------------------ - -When writing a :func:`contextfunction` or something similar you may have -noticed that the context tries to stop you from modifying it. If you have -managed to modify the context by using an internal context API you may -have noticed that changes in the context don't seem to be visible in the -template. The reason for this is that Jinja uses the context only as -primary data source for template variables for performance reasons. - -If you want to modify the context write a function that returns a variable -instead that one can assign to a variable by using set:: - - {% set comments = get_latest_comments() %} - -I don't have the _speedups Module. Is Jinja slower now? --------------------------------------------------------- - -To achieve a good performance with automatic escaping enabled, the escaping -function is also implemented in pure C and used if Jinja2 was installed with -the speedups module. This happens automatically if a C compiler is available -on the system during installation. - -My tracebacks look weird. What's happening? --------------------------------------------- - -If the speedups module is not compiled and you are using a Python installation -without ctypes (Python 2.4 without ctypes, Jython or Google's AppEngine) -Jinja2 is unable to provide correct debugging information and the traceback -may be incomplete. There is currently no good workaround for Jython or -the AppEngine as ctypes is unavailable there and it's not possible to use -the speedups extension. - -Why is there no Python 2.3 support? ------------------------------------ - -Python 2.3 is missing a lot of features that are used heavily in Jinja2. This -decision was made as with the upcoming Python 2.6 and 3.0 versions it becomes -harder to maintain the code for older Python versions. If you really need -Python 2.3 support you either have to use `Jinja 1`_ or other templating -engines that still support 2.3. - -My Macros are overriden by something ------------------------------------- - -In some situations the Jinja scoping appears arbitrary: - -layout.tmpl: - -.. sourcecode:: jinja - - {% macro foo() %}LAYOUT{% endmacro %} - {% block body %}{% endblock %} - -child.tmpl: - -.. sourcecode:: jinja - - {% extends 'layout.tmpl' %} - {% macro foo() %}CHILD{% endmacro %} - {% block body %}{{ foo() }}{% endblock %} - -This will print ``LAYOUT`` in Jinja2. This is a side effect of having -the parent template evaluated after the child one. This allows child -templates passing information to the parent template. To avoid this -issue rename the macro or variable in the parent template to have an -uncommon prefix. - -.. _Jinja 1: http://jinja.pocoo.org/1/ diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/index.rst --- a/bundled/jinja2/docs/index.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -Jinja2 Documentation -==================== - -This is the documentation for the Jinja2 general purpose templating language. -Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible, -fast and secure. - -.. toctree:: - :maxdepth: 2 - - intro - api - sandbox - templates - extensions - integration - switching - tricks - - faq - changelog - -If you can't find the information you're looking for, have a look at the -index of try to find it using the search function: - -* :ref:`genindex` -* :ref:`search` diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/integration.rst --- a/bundled/jinja2/docs/integration.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -Integration -=========== - -Jinja2 provides some code for integration into other tools such as frameworks, -the `Babel`_ library or your favourite editor for fancy code highlighting. -This is a brief description of whats included. - -.. _babel-integration: - -Babel Integration ------------------ - -Jinja provides support for extracting gettext messages from templates via a -`Babel`_ extractor entry point called `jinja2.ext.babel_extract`. The Babel -support is implemented as part of the :ref:`i18n-extension` extension. - -Gettext messages extracted from both `trans` tags and code expressions. - -To extract gettext messages from templates, the project needs a Jinja2 section -in its Babel extraction method `mapping file`_: - -.. sourcecode:: ini - - [jinja2: **/templates/**.html] - encoding = utf-8 - -The syntax related options of the :class:`Environment` are also available as -configuration values in the mapping file. For example to tell the extraction -that templates use ``%`` as `line_statement_prefix` you can use this code: - -.. sourcecode:: ini - - [jinja2: **/templates/**.html] - encoding = utf-8 - line_statement_prefix = % - -:ref:`jinja-extensions` may also be defined by passing a comma separated list -of import paths as `extensions` value. The i18n extension is added -automatically. - -.. _mapping file: http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration - -Pylons ------- - -With `Pylons`_ 0.9.7 onwards it's incredible easy to integrate Jinja into a -Pylons powered application. - -The template engine is configured in `config/environment.py`. The configuration -for Jinja2 looks something like that:: - - from jinja2 import Environment, PackageLoader - config['pylons.app_globals'].jinja_env = Environment( - loader=PackageLoader('yourapplication', 'templates') - ) - -After that you can render Jinja templates by using the `render_jinja` function -from the `pylons.templating` module. - -Additionally it's a good idea to set the Pylons' `c` object into strict mode. -Per default any attribute to not existing attributes on the `c` object return -an empty string and not an undefined object. To change this just use this -snippet and add it into your `config/environment.py`:: - - config['pylons.strict_c'] = True - -.. _Pylons: http://www.pylonshq.com/ - -TextMate --------- - -Inside the `ext` folder of Jinja2 there is a bundle for TextMate that supports -syntax highlighting for Jinja1 and Jinja2 for text based templates as well as -HTML. It also contains a few often used snippets. - -Vim ---- - -A syntax plugin for `Vim`_ exists in the Vim-scripts directory as well as the -ext folder of Jinja2. `The script `_ -supports Jinja1 and Jinja2. Once installed two file types are available `jinja` -and `htmljinja`. The first one for text based templates, the latter for HTML -templates. - -Copy the files into your `syntax` folder. - -.. _Babel: http://babel.edgewall.org/ -.. _Vim: http://www.vim.org/ diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/intro.rst --- a/bundled/jinja2/docs/intro.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -Introduction -============ - -This is the documentation for the Jinja2 general purpose templating language. -Jinja2 is a library for Python 2.4 and onwards that is designed to be flexible, -fast and secure. - -If you have any exposure to other text-based template languages, such as Smarty or -Django, you should feel right at home with Jinja2. It's both designer and -developer friendly by sticking to Python's principles and adding functionality -useful for templating environments. - -The key-features are... - -- ... **configurable syntax**. If you are generating LaTeX or other formats - with Jinja2 you can change the delimiters to something that integrates better - into the LaTeX markup. - -- ... **fast**. While performance is not the primarily target of Jinja2 it's - surprisingly fast. The overhead compared to regular Python code was reduced - to the very minimum. - -- ... **easy to debug**. Jinja2 integrates directly into the python traceback - system which allows you to debug Jinja2 templates with regular python - debugging helpers. - -- ... **secure**. It's possible to evaluate untrusted template code if the - optional sandbox is enabled. This allows Jinja2 to be used as templating - language for applications where users may modify the template design. - - -Prerequisites -------------- - -Jinja2 needs at least **Python 2.4** to run. Additionally a working C-compiler -that can create python extensions should be installed for the debugger. If no -C-compiler is available and you are using Python 2.4 the `ctypes`_ module -should be installed. - -If you don't have a working C-compiler and you are trying to install the source -release with the speedups you will get a compiler error. This however can be -circumvented by passing the ``--without-speedups`` command line argument to the -setup script:: - - $ python setup.py --with-speedups install - -(As of Jinja 2.2, the speedups are disabled by default and can be enabled -with ``--with-speedups``. See :ref:`enable-speedups`) - -.. _ctypes: http://python.net/crew/theller/ctypes/ - - -Installation ------------- - -You have multiple ways to install Jinja2. If you are unsure what to do, go -with the Python egg or tarball. - -As a Python egg (via easy_install) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can install the most recent Jinja2 version using `easy_install`_ or `pip`_:: - - easy_install Jinja2 - pip install Jinja2 - -This will install a Jinja2 egg in your Python installation's site-packages -directory. - -(If you are installing from the windows command line omit the `sudo` and make -sure to run the command as user with administrator rights) - -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 you either have to have setuptools or `distribute`_ installed, -the latter is preferred. - -This will install Jinja2 into your Python installation's site-packages directory. - -.. _distribute: http://pypi.python.org/pypi/distribute - -Installing the development version -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -1. Install `mercurial`_ -2. ``hg clone http://dev.pocoo.org/hg/jinja2-main jinja2`` -3. ``cd jinja2`` -4. ``ln -s jinja2 /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 distribute in development mode. This also -has the advantage that the C extensions are compiled. - -Alternative you can use `pip`_ to install the current development -snapshot:: - - sudo pip install Jinja2==dev - -Or the `easy_install`_ command:: - - sudo easy_install Jinja2==dev - -.. _download page: http://pypi.python.org/pypi/Jinja2 -.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools -.. _easy_install: http://peak.telecommunity.com/DevCenter/EasyInstall -.. _pip: http://pypi.python.org/pypi/pip -.. _mercurial: http://www.selenic.com/mercurial/ - -.. _enable-speedups: - -Enable the speedups Module -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default Jinja2 will not compile the speedups module. Enabling this -will fail if you don't have the Python headers or a working compiler. This -is often the case if you are installing Jinja2 from a windows machine. - -You can enable the speedups extension when installing using the -``--with-speedups`` flag:: - - sudo python setup.py --with-speedups install - - - -Basic API Usage ---------------- - -This section gives you a brief introduction to the Python API for Jinja2 -templates. - -The most basic way to create a template and render it is through -:class:`~jinja2.Template`. This however is not the recommended way to -work with it if your templates are not loaded from strings but the file -system or another data source: - ->>> from jinja2 import Template ->>> template = Template('Hello {{ name }}!') ->>> template.render(name='John Doe') -u'Hello John Doe!' - -By creating an instance of :class:`~jinja2.Template` you get back a new template -object that provides a method called :meth:`~jinja2.Template.render` which when -called with a dict or keyword arguments expands the template. The dict -or keywords arguments passed to the template are the so-called "context" -of the template. - -What you can see here is that Jinja2 is using unicode internally and the -return value is an unicode string. So make sure that your application is -indeed using unicode internally. - - -Experimental Python 3 Support ------------------------------ - -Jinja 2.3 brings experimental support for Python 3. It means that all -unittests pass on the new version, but there might still be small bugs in -there and behavior might be inconsistent. If you notice any bugs, please -provide feedback in the `Jinja bug tracker`_. - -Also please keep in mind that the documentation is written with Python 2 -in mind, you will have to adapt the shown code examples to Python 3 syntax -for yourself. - - -.. _Jinja bug tracker: http://dev.pocoo.org/projects/jinja/ diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/jinjaext.py --- a/bundled/jinja2/docs/jinjaext.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -# -*- coding: utf-8 -*- -""" - Jinja Documentation Extensions - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Support for automatically documenting filters and tests. - - :copyright: Copyright 2008 by Armin Ronacher. - :license: BSD. -""" -import os -import re -import inspect -import jinja2 -from itertools import islice -from types import BuiltinFunctionType -from docutils import nodes -from docutils.statemachine import ViewList -from sphinx.ext.autodoc import prepare_docstring -from sphinx.application import TemplateBridge -from pygments.style import Style -from pygments.token import Keyword, Name, Comment, String, Error, \ - Number, Operator, Generic -from jinja2 import Environment, FileSystemLoader - - -def parse_rst(state, content_offset, doc): - node = nodes.section() - # hack around title style bookkeeping - surrounding_title_styles = state.memo.title_styles - surrounding_section_level = state.memo.section_level - state.memo.title_styles = [] - state.memo.section_level = 0 - state.nested_parse(doc, content_offset, node, match_titles=1) - state.memo.title_styles = surrounding_title_styles - state.memo.section_level = surrounding_section_level - return node.children - - -class JinjaStyle(Style): - title = 'Jinja Style' - default_style = "" - styles = { - Comment: 'italic #aaaaaa', - Comment.Preproc: 'noitalic #B11414', - Comment.Special: 'italic #505050', - - Keyword: 'bold #B80000', - Keyword.Type: '#808080', - - Operator.Word: 'bold #B80000', - - Name.Builtin: '#333333', - Name.Function: '#333333', - Name.Class: 'bold #333333', - Name.Namespace: 'bold #333333', - Name.Entity: 'bold #363636', - Name.Attribute: '#686868', - Name.Tag: 'bold #686868', - Name.Decorator: '#686868', - - String: '#AA891C', - Number: '#444444', - - Generic.Heading: 'bold #000080', - Generic.Subheading: 'bold #800080', - Generic.Deleted: '#aa0000', - Generic.Inserted: '#00aa00', - Generic.Error: '#aa0000', - Generic.Emph: 'italic', - Generic.Strong: 'bold', - Generic.Prompt: '#555555', - Generic.Output: '#888888', - Generic.Traceback: '#aa0000', - - Error: '#F00 bg:#FAA' - } - - -_sig_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*(\(.*?\))') - - -def format_function(name, aliases, func): - lines = inspect.getdoc(func).splitlines() - signature = '()' - if isinstance(func, BuiltinFunctionType): - match = _sig_re.match(lines[0]) - if match is not None: - del lines[:1 + bool(lines and not lines[0])] - signature = match.group(1) - else: - try: - argspec = inspect.getargspec(func) - if getattr(func, 'environmentfilter', False) or \ - getattr(func, 'contextfilter', False): - del argspec[0][0] - signature = inspect.formatargspec(*argspec) - except: - pass - result = ['.. function:: %s%s' % (name, signature), ''] - result.extend(' ' + line for line in lines) - if aliases: - result.extend(('', ' :aliases: %s' % ', '.join( - '``%s``' % x for x in sorted(aliases)))) - return result - - -def dump_functions(mapping): - def directive(dirname, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - reverse_mapping = {} - for name, func in mapping.iteritems(): - reverse_mapping.setdefault(func, []).append(name) - filters = [] - for func, names in reverse_mapping.iteritems(): - aliases = sorted(names, key=lambda x: len(x)) - name = aliases.pop() - filters.append((name, aliases, func)) - filters.sort() - - result = ViewList() - for name, aliases, func in filters: - for item in format_function(name, aliases, func): - result.append(item, '') - - node = nodes.paragraph() - state.nested_parse(result, content_offset, node) - return node.children - return directive - - -from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS -jinja_filters = dump_functions(DEFAULT_FILTERS) -jinja_tests = dump_functions(DEFAULT_TESTS) - - -def jinja_nodes(dirname, arguments, options, content, lineno, - content_offset, block_text, state, state_machine): - from jinja2.nodes import Node - doc = ViewList() - def walk(node, indent): - p = ' ' * indent - sig = ', '.join(node.fields) - doc.append(p + '.. autoclass:: %s(%s)' % (node.__name__, sig), '') - if node.abstract: - members = [] - for key, name in node.__dict__.iteritems(): - if not key.startswith('_') and \ - not hasattr(node.__base__, key) and callable(name): - members.append(key) - if members: - members.sort() - doc.append('%s :members: %s' % (p, ', '.join(members)), '') - if node.__base__ != object: - doc.append('', '') - doc.append('%s :Node type: :class:`%s`' % - (p, node.__base__.__name__), '') - doc.append('', '') - children = node.__subclasses__() - children.sort(key=lambda x: x.__name__.lower()) - for child in children: - walk(child, indent) - walk(Node, 0) - return parse_rst(state, content_offset, doc) - - -def inject_toc(app, doctree, docname): - titleiter = iter(doctree.traverse(nodes.title)) - try: - # skip first title, we are not interested in that one - titleiter.next() - title = titleiter.next() - # and check if there is at least another title - titleiter.next() - except StopIteration: - return - tocnode = nodes.section('') - tocnode['classes'].append('toc') - toctitle = nodes.section('') - toctitle['classes'].append('toctitle') - toctitle.append(nodes.title(text='Table Of Contents')) - tocnode.append(toctitle) - tocnode += doctree.document.settings.env.get_toc_for(docname)[0][1] - title.parent.insert(title.parent.children.index(title), tocnode) - - -def setup(app): - app.add_directive('jinjafilters', jinja_filters, 0, (0, 0, 0)) - app.add_directive('jinjatests', jinja_tests, 0, (0, 0, 0)) - app.add_directive('jinjanodes', jinja_nodes, 0, (0, 0, 0)) - # uncomment for inline toc. links are broken unfortunately - ##app.connect('doctree-resolved', inject_toc) diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/sandbox.rst --- a/bundled/jinja2/docs/sandbox.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -Sandbox -======= - -The Jinja2 sandbox can be used to evaluate untrusted code. Access to unsafe -attributes and methods is prohibited. - -Assuming `env` is a :class:`SandboxedEnvironment` in the default configuration -the following piece of code shows how it works: - ->>> env.from_string("{{ func.func_code }}").render(func=lambda:None) -u'' ->>> env.from_string("{{ func.func_code.do_something }}").render(func=lambda:None) -Traceback (most recent call last): - ... -SecurityError: access to attribute 'func_code' of 'function' object is unsafe. - - -.. module:: jinja2.sandbox - -.. autoclass:: SandboxedEnvironment([options]) - :members: is_safe_attribute, is_safe_callable - -.. autoclass:: ImmutableSandboxedEnvironment([options]) - -.. autoexception:: SecurityError - -.. autofunction:: unsafe - -.. autofunction:: is_internal_attribute - -.. autofunction:: modifies_known_mutable - -.. admonition:: Note - - The Jinja2 sandbox alone is no solution for perfect security. Especially - for web applications you have to keep in mind that users may create - templates with arbitrary HTML in so it's crucial to ensure that (if you - are running multiple users on the same server) they can't harm each other - via JavaScript insertions and much more. - - Also the sandbox is only as good as the configuration. We stronly - recommend only passing non-shared resources to the template and use - some sort of whitelisting for attributes. - - Also keep in mind that templates may raise runtime or compile time errors, - so make sure to catch them. diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/switching.rst --- a/bundled/jinja2/docs/switching.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,242 +0,0 @@ -Switching from other Template Engines -===================================== - -.. highlight:: html+jinja - -If you have used a different template engine in the past and want to swtich -to Jinja2 here is a small guide that shows the basic syntatic and semantic -changes between some common, similar text template engines for Python. - -Jinja1 ------- - -Jinja2 is mostly compatible with Jinja1 in terms of API usage and template -syntax. The differences between Jinja1 and 2 are explained in the following -list. - -API -~~~ - -Loaders - Jinja2 uses a different loader API. Because the internal representation - of templates changed there is no longer support for external caching - systems such as memcached. The memory consumed by templates is comparable - with regular Python modules now and external caching doesn't give any - advantage. If you have used a custom loader in the past have a look at - the new :ref:`loader API `. - -Loading templates from strings - In the past it was possible to generate templates from a string with the - default environment configuration by using `jinja.from_string`. Jinja2 - provides a :class:`Template` class that can be used to do the same, but - with optional additional configuration. - -Automatic unicode conversion - Jinja1 performed automatic conversion of bytestrings in a given encoding - into unicode objects. This conversion is no longer implemented as it - was inconsistent as most libraries are using the regular Python ASCII - bytestring to Unicode conversion. An application powered by Jinja2 - *has to* use unicode internally everywhere or make sure that Jinja2 only - gets unicode strings passed. - -i18n - Jinja1 used custom translators for internationalization. i18n is now - available as Jinja2 extension and uses a simpler, more gettext friendly - interface and has support for babel. For more details see - :ref:`i18n-extension`. - -Internal methods - Jinja1 exposed a few internal methods on the environment object such - as `call_function`, `get_attribute` and others. While they were marked - as being an internal method it was possible to override them. Jinja2 - doesn't have equivalent methods. - -Sandbox - Jinja1 was running sandbox mode by default. Few applications actually - used that feature so it became optional in Jinja2. For more details - about the sandboxed execution see :class:`SandboxedEnvironment`. - -Context - Jinja1 had a stacked context as storage for variables passed to the - environment. In Jinja2 a similar object exists but it doesn't allow - modifications nor is it a singleton. As inheritance is dynamic now - multiple context objects may exist during template evaluation. - -Filters and Tests - Filters and tests are regular functions now. It's no longer necessary - and allowed to use factory functions. - - -Templates -~~~~~~~~~ - -Jinja2 has mostly the same syntax as Jinja1. What's different is that -macros require parentheses around the argument list now. - -Additionally Jinja2 allows dynamic inheritance now and dynamic includes. -The old helper function `rendertemplate` is gone now, `include` can be used -instead. Includes no longer import macros and variable assignments, for -that the new `import` tag is used. This concept is explained in the -:ref:`import` documentation. - -Another small change happened in the `for`-tag. The special loop variable -doesn't have a `parent` attribute, instead you have to alias the loop -yourself. See :ref:`accessing-the-parent-loop` for more details. - - -Django ------- - -If you have previously worked with Django templates, you should find -Jinja2 very familiar. In fact, most of the syntax elements look and -work the same. - -However, Jinja2 provides some more syntax elements covered in the -documentation and some work a bit different. - -This section covers the template changes. As the API is fundamentally -different we won't cover it here. - -Method Calls -~~~~~~~~~~~~ - -In Django method calls work implicitly. With Jinja2 you have to specify that -you want to call an object. Thus this Django code:: - - {% for page in user.get_created_pages %} - ... - {% endfor %} - -will look like this in Jinja:: - - {% for page in user.get_created_pages() %} - ... - {% endfor %} - -This allows you to pass variables to the function which is also used for macros -which is not possible in Django. - -Conditions -~~~~~~~~~~ - -In Django you can use the following constructs to check for equality:: - - {% ifequal foo "bar" %} - ... - {% else %} - ... - {% endifequal %} - -In Jinja2 you can use the normal if statement in combination with operators:: - - {% if foo == 'bar' %} - ... - {% else %} - ... - {% endif %} - -You can also have multiple elif branches in your template:: - - {% if something %} - ... - {% elif otherthing %} - ... - {% elif foothing %} - ... - {% else %} - ... - {% endif %} - -Filter Arguments -~~~~~~~~~~~~~~~~ - -Jinja2 provides more than one argument for filters. Also the syntax for -argument passing is different. A template that looks like this in Django:: - - {{ items|join:", " }} - -looks like this in Jinja2:: - - {{ items|join(', ') }} - -In fact it's a bit more verbose but it allows different types of arguments - -including variables - and more than one of them. - -Tests -~~~~~ - -In addition to filters there also are tests you can perform using the is -operator. Here are some examples:: - - {% if user.user_id is odd %} - {{ user.username|e }} is odd - {% else %} - hmm. {{ user.username|e }} looks pretty normal - {% endif %} - -Loops -~~~~~ - -For loops work very similar to Django, the only incompatibility is that in -Jinja2 the special variable for the loop context is called `loop` and not -`forloop` like in Django. - -Cycle -~~~~~ - -The ``{% cycle %}`` tag does not exist in Jinja because of it's implicit -nature. However you can achieve mostly the same by using the `cycle` -method on a loop object. - -The following Django template:: - - {% for user in users %} -
  • {{ user }}
  • - {% endfor %} - -Would look like this in Jinja:: - - {% for user in users %} -
  • {{ user }}
  • - {% endfor %} - -There is no equivalent of ``{% cycle ... as variable %}``. - - -Mako ----- - -.. highlight:: html+mako - -If you have used Mako so far and want to switch to Jinja2 you can configure -Jinja2 to look more like Mako: - -.. sourcecode:: python - - env = Environment('<%', '%>', '${', '}', '%') - -Once the environment is configure like that Jinja2 should be able to interpret -a small subset of Mako templates. Jinja2 does not support embedded Python code -so you would have to move that out of the template. The syntax for defs (in -Jinja2 defs are called macros) and template inheritance is different too. The -following Mako template:: - - <%inherit file="layout.html" /> - <%def name="title()">Page Title -
      - % for item in list: -
    • ${item}
    • - % endfor -
    - -Looks like this in Jinja2 with the above configuration:: - - <% extends "layout.html" %> - <% block title %>Page Title<% endblock %> - <% block body %> -
      - % for item in list: -
    • ${item}
    • - % endfor -
    - <% endblock %> diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/templates.rst --- a/bundled/jinja2/docs/templates.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1310 +0,0 @@ -Template Designer Documentation -=============================== - -.. highlight:: html+jinja - -This document describes the syntax and semantics of the template engine and -will be most useful as reference to those creating Jinja templates. As the -template engine is very flexible the configuration from the application might -be slightly different from here in terms of delimiters and behavior of -undefined values. - - -Synopsis --------- - -A template is simply a text file. It can generate any text-based format -(HTML, XML, CSV, LaTeX, etc.). It doesn't have a specific extension, -``.html`` or ``.xml`` are just fine. - -A template contains **variables** or **expressions**, which get replaced with -values when the template is evaluated, and tags, which control the logic of -the template. The template syntax is heavily inspired by Django and Python. - -Below is a minimal template that illustrates a few basics. We will cover -the details later in that document:: - - - - - My Webpage - - - - -

    My Webpage

    - {{ a_variable }} - - - -This covers the default settings. The application developer might have -changed the syntax from ``{% foo %}`` to ``<% foo %>`` or something similar. - -There are two kinds of delimiers. ``{% ... %}`` and ``{{ ... }}``. The first -one is used to execute statements such as for-loops or assign values, the -latter prints the result of the expression to the template. - -.. _variables: - -Variables ---------- - -The application passes variables to the templates you can mess around in the -template. Variables may have attributes or elements on them you can access -too. How a variable looks like, heavily depends on the application providing -those. - -You can use a dot (``.``) to access attributes of a variable, alternative the -so-called "subscript" syntax (``[]``) can be used. The following lines do -the same:: - - {{ foo.bar }} - {{ foo['bar'] }} - -It's important to know that the curly braces are *not* part of the variable -but the print statement. If you access variables inside tags don't put the -braces around. - -If a variable or attribute does not exist you will get back an undefined -value. What you can do with that kind of value depends on the application -configuration, the default behavior is that it evaluates to an empty string -if printed and that you can iterate over it, but every other operation fails. - -.. _notes-on-subscriptions: - -.. admonition:: Implementation - - For convenience sake ``foo.bar`` in Jinja2 does the following things on - the Python layer: - - - check if there is an attribute called `bar` on `foo`. - - if there is not, check if there is an item ``'bar'`` in `foo`. - - if there is not, return an undefined object. - - ``foo['bar']`` on the other hand works mostly the same with the a small - difference in the order: - - - check if there is an item ``'bar'`` in `foo`. - - if there is not, check if there is an attribute called `bar` on `foo`. - - if there is not, return an undefined object. - - This is important if an object has an item or attribute with the same - name. Additionally there is the :func:`attr` filter that just looks up - attributes. - -.. _filters: - -Filters -------- - -Variables can by modified by **filters**. Filters are separated from the -variable by a pipe symbol (``|``) and may have optional arguments in -parentheses. Multiple filters can be chained. The output of one filter is -applied to the next. - -``{{ name|striptags|title }}`` for example will remove all HTML Tags from the -`name` and title-cases it. Filters that accept arguments have parentheses -around the arguments, like a function call. This example will join a list -by commas: ``{{ list|join(', ') }}``. - -The :ref:`builtin-filters` below describes all the builtin filters. - -.. _tests: - -Tests ------ - -Beside filters there are also so called "tests" available. Tests can be used -to test a variable against a common expression. To test a variable or -expression you add `is` plus the name of the test after the variable. For -example to find out if a variable is defined you can do ``name is defined`` -which will then return true or false depending on if `name` is defined. - -Tests can accept arguments too. If the test only takes one argument you can -leave out the parentheses to group them. For example the following two -expressions do the same:: - - {% if loop.index is divisibleby 3 %} - {% if loop.index is divisibleby(3) %} - -The :ref:`builtin-tests` below describes all the builtin tests. - - -Comments --------- - -To comment-out part of a line in a template, use the comment syntax which is -by default set to ``{# ... #}``. This is useful to comment out parts of the -template for debugging or to add information for other template designers or -yourself:: - - {# note: disabled template because we no longer use this - {% for user in users %} - ... - {% endfor %} - #} - - -Whitespace Control ------------------- - -In the default configuration whitespace is not further modified by the -template engine, so each whitespace (spaces, tabs, newlines etc.) is returned -unchanged. If the application configures Jinja to `trim_blocks` the first -newline after a a template tag is removed automatically (like in PHP). - -But you can also strip whitespace in templates by hand. If you put an minus -sign (``-``) to the start or end of an block (for example a for tag), a -comment or variable expression you can remove the whitespaces after or before -that block:: - - {% for item in seq -%} - {{ item }} - {%- endfor %} - -This will yield all elements without whitespace between them. If `seq` was -a list of numbers from ``1`` to ``9`` the output would be ``123456789``. - -If :ref:`line-statements` are enabled they strip leading whitespace -automatically up to the beginning of the line. - -.. admonition:: Note - - You must not use a whitespace between the tag and the minus sign. - - **valid**:: - - {%- if foo -%}...{% endif %} - - **invalid**:: - - {% - if foo - %}...{% endif %} - - -Escaping --------- - -It is sometimes desirable or even necessary to have Jinja ignore parts it -would otherwise handle as variables or blocks. For example if the default -syntax is used and you want to use ``{{`` as raw string in the template and -not start a variable you have to use a trick. - -The easiest way is to output the variable delimiter (``{{``) by using a -variable expression:: - - {{ '{{' }} - -For bigger sections it makes sense to mark a block `raw`. For example to -put Jinja syntax as example into a template you can use this snippet:: - - {% raw %} -
      - {% for item in seq %} -
    • {{ item }}
    • - {% endfor %} -
    - {% endraw %} - - -.. _line-statements: - -Line Statements ---------------- - -If line statements are enabled by the application it's possible to mark a -line as a statement. For example if the line statement prefix is configured -to ``#`` the following two examples are equivalent:: - -
      - # for item in seq -
    • {{ item }}
    • - # endfor -
    - -
      - {% for item in seq %} -
    • {{ item }}
    • - {% endfor %} -
    - -The line statement prefix can appear anywhere on the line as long as no text -precedes it. For better readability statements that start a block (such as -`for`, `if`, `elif` etc.) may end with a colon:: - - # for item in seq: - ... - # endfor - - -.. admonition:: Note - - Line statements can span multiple lines if there are open parentheses, - braces or brackets:: - -
      - # for href, caption in [('index.html', 'Index'), - ('about.html', 'About')]: -
    • {{ caption }}
    • - # endfor -
    - -Since Jinja 2.2 line-based comments are available as well. For example if -the line-comment prefix is configured to be ``##`` everything from ``##`` to -the end of the line is ignored (excluding the newline sign):: - - # for item in seq: -
  • {{ item }}
  • ## this comment is ignored - # endfor - - -.. _template-inheritance: - -Template Inheritance --------------------- - -The most powerful part of Jinja is template inheritance. Template inheritance -allows you to build a base "skeleton" template that contains all the common -elements of your site and defines **blocks** that child templates can override. - -Sounds complicated but is very basic. It's easiest to understand it by starting -with an example. - - -Base Template -~~~~~~~~~~~~~ - -This template, which we'll call ``base.html``, defines a simple HTML skeleton -document that you might use for a simple two-column page. It's the job of -"child" templates to fill the empty blocks with content:: - - - - - - {% block head %} - - {% block title %}{% endblock %} - My Webpage - {% endblock %} - - -
    {% block content %}{% endblock %}
    - - - -In this example, the ``{% block %}`` tags define four blocks that child templates -can fill in. All the `block` tag does is to tell the template engine that a -child template may override those portions of the template. - -Child Template -~~~~~~~~~~~~~~ - -A child template might look like this:: - - {% extends "base.html" %} - {% block title %}Index{% endblock %} - {% block head %} - {{ super() }} - - {% endblock %} - {% block content %} -

    Index

    -

    - Welcome on my awesome homepage. -

    - {% endblock %} - -The ``{% extends %}`` tag is the key here. It tells the template engine that -this template "extends" another template. When the template system evaluates -this template, first it locates the parent. The extends tag should be the -first tag in the template. Everything before it is printed out normally and -may cause confusion. For details about this behavior and how to take -advantage of it, see :ref:`null-master-fallback`. - -The filename of the template depends on the template loader. For example the -:class:`FileSystemLoader` allows you to access other templates by giving the -filename. You can access templates in subdirectories with an slash:: - - {% extends "layout/default.html" %} - -But this behavior can depend on the application embedding Jinja. Note that -since the child template doesn't define the ``footer`` block, the value from -the parent template is used instead. - -You can't define multiple ``{% block %}`` tags with the same name in the -same template. This limitation exists because a block tag works in "both" -directions. That is, a block tag doesn't just provide a hole to fill - it -also defines the content that fills the hole in the *parent*. If there -were two similarly-named ``{% block %}`` tags in a template, that template's -parent wouldn't know which one of the blocks' content to use. - -If you want to print a block multiple times you can however use the special -`self` variable and call the block with that name:: - - {% block title %}{% endblock %} -

    {{ self.title() }}

    - {% block body %}{% endblock %} - - -Super Blocks -~~~~~~~~~~~~ - -It's possible to render the contents of the parent block by calling `super`. -This gives back the results of the parent block:: - - {% block sidebar %} -

    Table Of Contents

    - ... - {{ super() }} - {% endblock %} - - -Named Block End-Tags -~~~~~~~~~~~~~~~~~~~~ - -Jinja2 allows you to put the name of the block after the end tag for better -readability:: - - {% block sidebar %} - {% block inner_sidebar %} - ... - {% endblock inner_sidebar %} - {% endblock sidebar %} - -However the name after the `endblock` word must match the block name. - - -Block Nesting and Scope -~~~~~~~~~~~~~~~~~~~~~~~ - -Blocks can be nested for more complex layouts. However per default blocks -may not access variables from outer scopes:: - - {% for item in seq %} -
  • {% block loop_item %}{{ item }}{% endblock %}
  • - {% endfor %} - -This example would output empty ``
  • `` items because `item` is unavailable -inside the block. The reason for this is that if the block is replaced by -a child template a variable would appear that was not defined in the block or -passed to the context. - -Starting with Jinja 2.2 you can explicitly specify that variables are -available in a block by setting the block to "scoped" by adding the `scoped` -modifier to a block declaration:: - - {% for item in seq %} -
  • {% block loop_item scoped %}{{ item }}{% endblock %}
  • - {% endfor %} - -When overriding a block the `scoped` modifier does not have to be provided. - - -Template Objects -~~~~~~~~~~~~~~~~ - -.. versionchanged:: 2.4 - -If a template object was passed to the template context you can -extend from that object as well. Assuming the calling code passes -a layout template as `layout_template` to the environment, this -code works:: - - {% extends layout_template %} - -Previously the `layout_template` variable had to be a string with -the layout template's filename for this to work. - - -HTML Escaping -------------- - -When generating HTML from templates, there's always a risk that a variable will -include characters that affect the resulting HTML. There are two approaches: -manually escaping each variable or automatically escaping everything by default. - -Jinja supports both, but what is used depends on the application configuration. -The default configuaration is no automatic escaping for various reasons: - -- escaping everything except of safe values will also mean that Jinja is - escaping variables known to not include HTML such as numbers which is - a huge performance hit. - -- The information about the safety of a variable is very fragile. It could - happen that by coercing safe and unsafe values the return value is double - escaped HTML. - -Working with Manual Escaping -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If manual escaping is enabled it's **your** responsibility to escape -variables if needed. What to escape? If you have a variable that *may* -include any of the following chars (``>``, ``<``, ``&``, or ``"``) you -**have to** escape it unless the variable contains well-formed and trusted -HTML. Escaping works by piping the variable through the ``|e`` filter: -``{{ user.username|e }}``. - -Working with Automatic Escaping -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When automatic escaping is enabled everything is escaped by default except -for values explicitly marked as safe. Those can either be marked by the -application or in the template by using the `|safe` filter. The main -problem with this approach is that Python itself doesn't have the concept -of tainted values so the information if a value is safe or unsafe can get -lost. If the information is lost escaping will take place which means that -you could end up with double escaped contents. - -Double escaping is easy to avoid however, just rely on the tools Jinja2 -provides and don't use builtin Python constructs such as the string modulo -operator. - -Functions returning template data (macros, `super`, `self.BLOCKNAME`) return -safe markup always. - -String literals in templates with automatic escaping are considered unsafe -too. The reason for this is that the safe string is an extension to Python -and not every library will work properly with it. - - -List of Control Structures --------------------------- - -A control structure refers to all those things that control the flow of a -program - conditionals (i.e. if/elif/else), for-loops, as well as things like -macros and blocks. Control structures appear inside ``{% ... %}`` blocks -in the default syntax. - -For -~~~ - -Loop over each item in a sequence. For example, to display a list of users -provided in a variable called `users`:: - -

    Members

    -
      - {% for user in users %} -
    • {{ user.username|e }}
    • - {% endfor %} -
    - -Inside of a for loop block you can access some special variables: - -+-----------------------+---------------------------------------------------+ -| Variable | Description | -+=======================+===================================================+ -| `loop.index` | The current iteration of the loop. (1 indexed) | -+-----------------------+---------------------------------------------------+ -| `loop.index0` | The current iteration of the loop. (0 indexed) | -+-----------------------+---------------------------------------------------+ -| `loop.revindex` | The number of iterations from the end of the loop | -| | (1 indexed) | -+-----------------------+---------------------------------------------------+ -| `loop.revindex0` | The number of iterations from the end of the loop | -| | (0 indexed) | -+-----------------------+---------------------------------------------------+ -| `loop.first` | True if first iteration. | -+-----------------------+---------------------------------------------------+ -| `loop.last` | True if last iteration. | -+-----------------------+---------------------------------------------------+ -| `loop.length` | The number of items in the sequence. | -+-----------------------+---------------------------------------------------+ -| `loop.cycle` | A helper function to cycle between a list of | -| | sequences. See the explanation below. | -+-----------------------+---------------------------------------------------+ - -Within a for-loop, it's possible to cycle among a list of strings/variables -each time through the loop by using the special `loop.cycle` helper:: - - {% for row in rows %} -
  • {{ 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 -can however filter the sequence during iteration which allows you to skip -items. The following example skips all the users which are hidden:: - - {% for user in users if not user.hidden %} -
  • {{ user.username|e }}
  • - {% endfor %} - -The advantage is that the special `loop` variable will count correctly thus -not counting the users not iterated over. - -If no iteration took place because the sequence was empty or the filtering -removed all the items from the sequence you can render a replacement block -by using `else`:: - -
      - {% for user in users %} -
    • {{ user.username|e }}
    • - {% else %} -
    • no users found
    • - {% endfor %} -
    - -It is also possible to use loops recursively. This is useful if you are -dealing with recursive data such as sitemaps. To use loops recursively you -basically have to add the `recursive` modifier to the loop definition and -call the `loop` variable with the new iterable where you want to recurse. - -The following example implements a sitemap with recursive loops:: - -
      - {%- for item in sitemap recursive %} -
    • {{ item.title }} - {%- if item.children -%} - - {%- endif %}
    • - {%- endfor %} -
    - - -If -~~ - -The `if` statement in Jinja is comparable with the if statements of Python. -In the simplest form you can use it to test if a variable is defined, not -empty or not false:: - - {% if users %} -
      - {% for user in users %} -
    • {{ user.username|e }}
    • - {% endfor %} -
    - {% endif %} - -For multiple branches `elif` and `else` can be used like in Python. You can -use more complex :ref:`expressions` there too:: - - {% if kenny.sick %} - Kenny is sick. - {% elif kenny.dead %} - You killed Kenny! You bastard!!! - {% else %} - Kenny looks okay --- so far - {% endif %} - -If can also be used as :ref:`inline expression ` and for -:ref:`loop filtering `. - - -Macros -~~~~~~ - -Macros are comparable with functions in regular programming languages. They -are useful to put often used idioms into reusable functions to not repeat -yourself. - -Here a small example of a macro that renders a form element:: - - {% macro input(name, value='', type='text', size=20) -%} - - {%- endmacro %} - -The macro can then be called like a function in the namespace:: - -

    {{ input('username') }}

    -

    {{ input('password', type='password') }}

    - -If the macro was defined in a different template you have to -:ref:`import ` it first. - -Inside macros you have access to three special variables: - -`varargs` - If more positional arguments are passed to the macro than accepted by the - macro they end up in the special `varargs` variable as list of values. - -`kwargs` - Like `varargs` but for keyword arguments. All unconsumed keyword - arguments are stored in this special variable. - -`caller` - If the macro was called from a :ref:`call` tag the caller is stored - in this variable as macro which can be called. - -Macros also expose some of their internal details. The following attributes -are available on a macro object: - -`name` - The name of the macro. ``{{ input.name }}`` will print ``input``. - -`arguments` - A tuple of the names of arguments the macro accepts. - -`defaults` - A tuple of default values. - -`catch_kwargs` - This is `true` if the macro accepts extra keyword arguments (ie: accesses - the special `kwargs` variable). - -`catch_varargs` - This is `true` if the macro accepts extra positional arguments (ie: - accesses the special `varargs` variable). - -`caller` - This is `true` if the macro accesses the special `caller` variable and may - be called from a :ref:`call` tag. - -If a macro name starts with an underscore it's not exported and can't -be imported. - - -.. _call: - -Call -~~~~ - -In some cases it can be useful to pass a macro to another macro. For this -purpose you can use the special `call` block. The following example shows -a macro that takes advantage of the call functionality and how it can be -used:: - - {% macro render_dialog(title, class='dialog') -%} -
    -

    {{ title }}

    -
    - {{ caller() }} -
    -
    - {%- endmacro %} - - {% call render_dialog('Hello World') %} - This is a simple dialog rendered by using a macro and - a call block. - {% endcall %} - -It's also possible to pass arguments back to the call block. This makes it -useful as replacement for loops. Generally speaking a call block works -exactly like an macro, just that it doesn't have a name. - -Here an example of how a call block can be used with arguments:: - - {% macro dump_users(users) -%} -
      - {%- for user in users %} -
    • {{ user.username|e }}

      {{ caller(user) }}
    • - {%- endfor %} -
    - {%- endmacro %} - - {% call(user) dump_users(list_of_user) %} -
    -
    Realname
    -
    {{ user.realname|e }}
    -
    Description
    -
    {{ user.description }}
    -
    - {% endcall %} - - -Filters -~~~~~~~ - -Filter sections allow you to apply regular Jinja2 filters on a block of -template data. Just wrap the code in the special `filter` section:: - - {% filter upper %} - This text becomes uppercase - {% endfilter %} - - -Assignments -~~~~~~~~~~~ - -Inside code blocks you can also assign values to variables. Assignments at -top level (outside of blocks, macros or loops) are exported from the template -like top level macros and can be imported by other templates. - -Assignments use the `set` tag and can have multiple targets:: - - {% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %} - {% set key, value = call_something() %} - - -Extends -~~~~~~~ - -The `extends` tag can be used to extend a template from another one. You -can have multiple of them in a file but only one of them may be executed -at the time. See the section about :ref:`template-inheritance` above. - - -Block -~~~~~ - -Blocks are used for inheritance and act as placeholders and replacements -at the same time. They are documented in detail as part of the section -about :ref:`template-inheritance`. - - -Include -~~~~~~~ - -The `include` statement is useful to include a template and return the -rendered contents of that file into the current namespace:: - - {% include 'header.html' %} - Body - {% include 'footer.html' %} - -Included templates have access to the variables of the active context by -default. For more details about context behavior of imports and includes -see :ref:`import-visibility`. - -From Jinja 2.2 onwards you can mark an include with ``ignore missing`` in -which case Jinja will ignore the statement if the template to be ignored -does not exist. When combined with ``with`` or ``without context`` it has -to be placed *before* the context visibility statement. Here some valid -examples:: - - {% include "sidebar.html" ignore missing %} - {% include "sidebar.html" ignore missing with context %} - {% include "sidebar.html" ignore missing without context %} - -.. versionadded:: 2.2 - -You can also provide a list of templates that are checked for existence -before inclusion. The first template that exists will be included. If -`ignore missing` is given, it will fall back to rendering nothing if -none of the templates exist, otherwise it will raise an exception. - -Example:: - - {% include ['page_detailed.html', 'page.html'] %} - {% include ['special_sidebar.html', 'sidebar.html'] ignore missing %} - -.. versionchanged:: 2.4 - If a template object was passed to the template context you can - include that object using `include`. - -.. _import: - -Import -~~~~~~ - -Jinja2 supports putting often used code into macros. These macros can go into -different templates and get imported from there. This works similar to the -import statements in Python. It's important to know that imports are cached -and imported templates don't have access to the current template variables, -just the globals by defualt. For more details about context behavior of -imports and includes see :ref:`import-visibility`. - -There are two ways to import templates. You can import the complete template -into a variable or request specific macros / exported variables from it. - -Imagine we have a helper module that renders forms (called `forms.html`):: - - {% macro input(name, value='', type='text') -%} - - {%- endmacro %} - - {%- macro textarea(name, value='', rows=10, cols=40) -%} - - {%- endmacro %} - -The easiest and most flexible is importing the whole module into a variable. -That way you can access the attributes:: - - {% import 'forms.html' as forms %} -
    -
    Username
    -
    {{ forms.input('username') }}
    -
    Password
    -
    {{ forms.input('password', type='password') }}
    -
    -

    {{ forms.textarea('comment') }}

    - - -Alternatively you can import names from the template into the current -namespace:: - - {% from 'forms.html' import input as input_field, textarea %} -
    -
    Username
    -
    {{ input_field('username') }}
    -
    Password
    -
    {{ input_field('password', type='password') }}
    -
    -

    {{ textarea('comment') }}

    - -Macros and variables starting with one ore more underscores are private and -cannot be imported. - -.. versionchanged:: 2.4 - If a template object was passed to the template context you can - import from that object. - - -.. _import-visibility: - -Import Context Behavior ------------------------ - -Per default included templates are passed the current context and imported -templates not. The reason for this is that imports unlike includes are -cached as imports are often used just as a module that holds macros. - -This however can be changed of course explicitly. By adding `with context` -or `without context` to the import/include directive the current context -can be passed to the template and caching is disabled automatically. - -Here two examples:: - - {% from 'forms.html' import input with context %} - {% include 'header.html' without context %} - -.. admonition:: Note - - In Jinja 2.0 the context that was passed to the included template - did not include variables defined in the template. As a matter of - fact this did not work:: - - {% for box in boxes %} - {% include "render_box.html" %} - {% endfor %} - - The included template ``render_box.html`` is not able to access - `box` in Jinja 2.0, but in Jinja 2.1. - - -.. _expressions: - -Expressions ------------ - -Jinja allows basic expressions everywhere. These work very similar to regular -Python and even if you're not working with Python you should feel comfortable -with it. - -Literals -~~~~~~~~ - -The simplest form of expressions are literals. Literals are representations -for Python objects such as strings and numbers. The following literals exist: - -"Hello World": - Everything between two double or single quotes is a string. They are - useful whenever you need a string in the template (for example as - arguments to function calls, filters or just to extend or include a - template). - -42 / 42.23: - Integers and floating point numbers are created by just writing the - number down. If a dot is present the number is a float, otherwise an - integer. Keep in mind that for Python ``42`` and ``42.0`` is something - different. - -['list', 'of', 'objects']: - Everything between two brackets is a list. Lists are useful to store - sequential data in or to iterate over them. For example you can easily - create a list of links using lists and tuples with a for loop:: - -
      - {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'), - ('downloads.html', 'Downloads')] %} -
    • {{ caption }}
    • - {% endfor %} -
    - -('tuple', 'of', 'values'): - Tuples are like lists, just that you can't modify them. If the tuple - only has one item you have to end it with a comma. Tuples are usually - used to represent items of two or more elements. See the example above - for more details. - -{'dict': 'of', 'key': 'and', 'value': 'pairs'}: - A dict in Python is a structure that combines keys and values. Keys must - be unique and always have exactly one value. Dicts are rarely used in - templates, they are useful in some rare cases such as the :func:`xmlattr` - filter. - -true / false: - true is always true and false is always false. - -.. admonition:: Note - - The special constants `true`, `false` and `none` are indeed lowercase. - Because that caused confusion in the past, when writing `True` expands - to an undefined variable that is considered false, all three of them can - be written in title case too (`True`, `False`, and `None`). However for - consistency (all Jinja identifiers are lowercase) you should use the - lowercase versions. - -Math -~~~~ - -Jinja allows you to calculate with values. This is rarely useful in templates -but exists for completeness' sake. The following operators are supported: - -\+ - Adds two objects together. Usually the objects are numbers but if both are - strings or lists you can concatenate them this way. This however is not - the preferred way to concatenate strings! For string concatenation have - a look at the ``~`` operator. ``{{ 1 + 1 }}`` is ``2``. - -\- - Substract the second number from the first one. ``{{ 3 - 2 }}`` is ``1``. - -/ - Divide two numbers. The return value will be a floating point number. - ``{{ 1 / 2 }}`` is ``{{ 0.5 }}``. - -// - Divide two numbers and return the truncated integer result. - ``{{ 20 / 7 }}`` is ``2``. - -% - Calculate the remainder of an integer division. ``{{ 11 % 7 }}`` is ``4``. - -\* - Multiply the left operand with the right one. ``{{ 2 * 2 }}`` would - return ``4``. This can also be used to repeat a string multiple times. - ``{{ '=' * 80 }}`` would print a bar of 80 equal signs. - -\** - Raise the left operand to the power of the right operand. ``{{ 2**3 }}`` - would return ``8``. - -Logic -~~~~~ - -For `if` statements, `for` filtering or `if` expressions it can be useful to -combine multiple expressions: - -and - Return true if the left and the right operand is true. - -or - Return true if the left or the right operand is true. - -not - negate a statement (see below). - -(expr) - group an expression. - -.. admonition:: Note - - The ``is`` and ``in`` operators support negation using an infix notation - too: ``foo is not bar`` and ``foo not in bar`` instead of ``not foo is bar`` - and ``not foo in bar``. All other expressions require a prefix notation: - ``not (foo and bar).`` - - -Other Operators -~~~~~~~~~~~~~~~ - -The following operators are very useful but don't fit into any of the other -two categories: - -in - Perform sequence / mapping containment test. Returns true if the left - operand is contained in the right. ``{{ 1 in [1, 2, 3] }}`` would for - example return true. - -is - Performs a :ref:`test `. - -\| - Applies a :ref:`filter `. - -~ - Converts all operands into strings and concatenates them. - ``{{ "Hello " ~ name ~ "!" }}`` would return (assuming `name` is - ``'John'``) ``Hello John!``. - -() - Call a callable: ``{{ post.render() }}``. Inside of the parentheses you - can use positional arguments and keyword arguments like in python: - ``{{ post.render(user, full=true) }}``. - -. / [] - Get an attribute of an object. (See :ref:`variables`) - - -.. _if-expression: - -If Expression -~~~~~~~~~~~~~ - -It is also possible to use inline `if` expressions. These are useful in some -situations. For example you can use this to extend from one template if a -variable is defined, otherwise from the default layout template:: - - {% extends layout_template if layout_template is defined else 'master.html' %} - -The general syntax is `` if else ``. - -The `else` part is optional. If not provided the else block implicitly -evaluates into an undefined object:: - - {{ '[%s]' % page.title if page.title }} - - -.. _builtin-filters: - -List of Builtin Filters ------------------------ - -.. jinjafilters:: - - -.. _builtin-tests: - -List of Builtin Tests ---------------------- - -.. jinjatests:: - -.. _builtin-globals: - -List of Global Functions ------------------------- - -The following functions are available in the global scope by default: - -.. function:: range([start,] stop[, step]) - - Return a list containing an arithmetic progression of integers. - range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0. - When step is given, it specifies the increment (or decrement). - For example, range(4) returns [0, 1, 2, 3]. The end point is omitted! - These are exactly the valid indices for a list of 4 elements. - - This is useful to repeat a template block multiple times for example - to fill a list. Imagine you have 7 users in the list but you want to - render three empty items to enforce a height with CSS:: - -
      - {% for user in users %} -
    • {{ user.username }}
    • - {% endfor %} - {% for number in range(10 - users|count) %} -
    • ...
    • - {% endfor %} -
    - -.. function:: lipsum(n=5, html=True, min=20, max=100) - - Generates some lorem ipsum for the template. Per default five paragraphs - with HTML are generated each paragraph between 20 and 100 words. If html - is disabled regular text is returned. This is useful to generate simple - contents for layout testing. - -.. function:: dict(\**items) - - 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 alternating - row colors. - - The following example shows how `cycler` can be used:: - - {% set row_class = cycler('odd', 'even') %} -
      - {% for folder in folders %} -
    • {{ folder|e }}
    • - {% endfor %} - {% for filename in files %} -
    • {{ filename|e }}
    • - {% endfor %} -
    - - 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** - -.. class:: joiner(sep=', ') - - A tiny helper that can be use to "join" multiple sections. A joiner is - passed a string and will return that string every time it's calld, except - the first time in which situation it returns an empty string. You can - use this to join things:: - - {% set pipe = joiner("|") %} - {% if categories %} {{ pipe() }} - Categories: {{ categories|join(", ") }} - {% endif %} - {% if author %} {{ pipe() }} - Author: {{ author() }} - {% endif %} - {% if can_edit %} {{ pipe() }} - Edit - {% endif %} - - **new in Jinja 2.1** - - -Extensions ----------- - -The following sections cover the built-in Jinja2 extensions that may be -enabled by the application. The application could also provide further -extensions not covered by this documentation. In that case there should -be a separate document explaining the extensions. - -.. _i18n-in-templates: - -i18n -~~~~ - -If the i18n extension is enabled it's possible to mark parts in the template -as translatable. To mark a section as translatable you can use `trans`:: - -

    {% trans %}Hello {{ user }}!{% endtrans %}

    - -To translate a template expression --- say, using template filters or just -accessing an attribute of an object --- you need to bind the expression to a -name for use within the translation block:: - -

    {% trans user=user.username %}Hello {{ user }}!{% endtrans %}

    - -If you need to bind more than one expression inside a `trans` tag, separate -the pieces with a comma (``,``):: - - {% trans book_title=book.title, author=author.name %} - This is {{ book_title }} by {{ author }} - {% endtrans %} - -Inside trans tags no statements are allowed, only variable tags are. - -To pluralize, specify both the singular and plural forms with the `pluralize` -tag, which appears between `trans` and `endtrans`:: - - {% trans count=list|length %} - There is {{ count }} {{ name }} object. - {% pluralize %} - There are {{ count }} {{ name }} objects. - {% endtrans %} - -Per default the first variable in a block is used to determine the correct -singular or plural form. If that doesn't work out you can specify the name -which should be used for pluralizing by adding it as parameter to `pluralize`:: - - {% trans ..., user_count=users|length %}... - {% pluralize user_count %}...{% endtrans %} - -It's also possible to translate strings in expressions. For that purpose -three functions exist: - -_ `gettext`: translate a single string -- `ngettext`: translate a pluralizable string -- `_`: alias for `gettext` - -For example you can print a translated string easily this way:: - - {{ _('Hello World!') }} - -To use placeholders you can use the `format` filter:: - - {{ _('Hello %(user)s!')|format(user=user.username) }} - or - {{ _('Hello %s')|format(user.username) }} - -For multiple placeholders always use keyword arguments to `format` as other -languages may not use the words in the same order. - - -Expression Statement -~~~~~~~~~~~~~~~~~~~~ - -If the expression-statement extension is loaded a tag called `do` is available -that works exactly like the regular variable expression (``{{ ... }}``) just -that it doesn't print anything. This can be used to modify lists:: - - {% do navigation.append('a string') %} - - -Loop Controls -~~~~~~~~~~~~~ - -If the application enables the :ref:`loopcontrols-extension` it's possible to -use `break` and `continue` in loops. When `break` is reached, the loop is -terminated, if `continue` is eached the processing is stopped and continues -with the next iteration. - -Here a loop that skips every second item:: - - {% for user in users %} - {%- if loop.index is even %}{% continue %}{% endif %} - ... - {% endfor %} - -Likewise a look that stops processing after the 10th iteration:: - - {% for user in users %} - {%- if loop.index >= 10 %}{% break %}{% endif %} - {%- endfor %} - - -With Statement -~~~~~~~~~~~~~~ - -.. versionadded:: 2.3 - -If the application enables the :ref:`with-extension` it is possible to -use the `with` keyword in templates. This makes it possible to create -a new inner scope. Variables set within this scope are not visible -outside of the scope. - -With in a nutshell:: - - {% with %} - {% set foo = 42 %} - {{ foo }} foo is 42 here - {% endwith %} - foo is not visible here any longer - -Because it is common to set variables at the beginning of the scope -you can do that within the with statement. The following two examples -are equivalent:: - - {% with foo = 42 %} - {{ foo }} - {% endwith %} - - {% with %} - {% set foo = 42 %} - {{ foo }} - {% endwith %} diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/docs/tricks.rst --- a/bundled/jinja2/docs/tricks.rst Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -Tips and Tricks -=============== - -.. highlight:: html+jinja - -This part of the documentation shows some tips and tricks for Jinja2 -templates. - - -.. _null-master-fallback: - -Null-Master Fallback --------------------- - -Jinja2 supports dynamic inheritance and does not distinguish between parent -and child template as long as no `extends` tag is visited. While this leads -to the surprising behavior that everything before the first `extends` tag -including whitespace is printed out instead of being igored, it can be used -for a neat trick. - -Usually child templates extend from one template that adds a basic HTML -skeleton. However it's possible put the `extends` tag into an `if` tag to -only extend from the layout template if the `standalone` variable evaluates -to false which it does per default if it's not defined. Additionally a very -basic skeleton is added to the file so that if it's indeed rendered with -`standalone` set to `True` a very basic HTML skeleton is added:: - - {% if not standalone %}{% extends 'master.html' %}{% endif -%} - - {% block title %}The Page Title{% endblock %} - - {% block body %} -

    This is the page body.

    - {% endblock %} - - -Alternating Rows ----------------- - -If you want to have different styles for each row of a table or -list you can use the `cycle` method on the `loop` object:: - -
      - {% for row in rows %} -
    • {{ row }}
    • - {% endfor %} -
    - -`cycle` can take an unlimited amount of strings. Each time this -tag is encountered the next item from the list is rendered. - - -Highlighting Active Menu Items ------------------------------- - -Often you want to have a navigation bar with an active navigation -item. This is really simple to achieve. Because assignments outside -of `block`\s in child templates are global and executed before the layout -template is evaluated it's possible to define the active menu item in the -child template:: - - {% extends "layout.html" %} - {% set active_page = "index" %} - -The layout template can then access `active_page`. Additionally it makes -sense to defined a default for that variable:: - - {% set navigation_bar = [ - ('/', 'index', 'Index'), - ('/downloads/', 'downloads', 'Downloads'), - ('/about/', 'about', 'About') - ] -%} - {% set active_page = active_page|default('index') -%} - ... - - ... - -.. _accessing-the-parent-loop: - -Accessing the parent Loop -------------------------- - -The special `loop` variable always points to the innermost loop. If it's -desired to have access to an outer loop it's possible to alias it:: - - - {% for row in table %} - - {% set rowloop = loop %} - {% for cell in row %} -
    -# for item in range(10) -
  • ${item}
  • -# endfor -\ -""").render() diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/basic/debugger.py --- a/bundled/jinja2/examples/basic/debugger.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -from jinja2 import Environment -from jinja2.loaders import FileSystemLoader - -env = Environment(loader=FileSystemLoader('templates')) - -tmpl = env.get_template('broken.html') -print tmpl.render(seq=[3, 2, 4, 5, 3, 2, 0, 2, 1]) diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/basic/inheritance.py --- a/bundled/jinja2/examples/basic/inheritance.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -from jinja2 import Environment -from jinja2.loaders import DictLoader - - -env = Environment(loader=DictLoader({ -'a': '''[A[{% block body %}{% endblock %}]]''', -'b': '''{% extends 'a' %}{% block body %}[B]{% endblock %}''', -'c': '''{% extends 'b' %}{% block body %}###{{ super() }}###{% endblock %}''' -})) - - -print env.get_template('c').render() diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/basic/templates/broken.html --- a/bundled/jinja2/examples/basic/templates/broken.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -{% from 'subbroken.html' import may_break %} -
      -{% for item in seq %} -
    • {{ may_break(item) }}
    • -{% endfor %} -
    diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/basic/templates/subbroken.html --- a/bundled/jinja2/examples/basic/templates/subbroken.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -{% macro may_break(item) -%} - [{{ item / 0 }}] -{%- endmacro %} diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/basic/test.py --- a/bundled/jinja2/examples/basic/test.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -from jinja2 import Environment -from jinja2.loaders import DictLoader - -env = Environment(loader=DictLoader({ -'child.html': u'''\ -{% extends master_layout or 'master.html' %} -{% include helpers = 'helpers.html' %} -{% macro get_the_answer() %}42{% endmacro %} -{% title = 'Hello World' %} -{% block body %} - {{ get_the_answer() }} - {{ helpers.conspirate() }} -{% endblock %} -''', -'master.html': u'''\ - -{{ title }} -{% block body %}{% endblock %} -''', -'helpers.html': u'''\ -{% macro conspirate() %}23{% endmacro %} -''' -})) - - -tmpl = env.get_template("child.html") -print tmpl.render() diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/basic/test_filter_and_linestatements.py --- a/bundled/jinja2/examples/basic/test_filter_and_linestatements.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -from jinja2 import Environment - - -env = Environment(line_statement_prefix='%', variable_start_string="${", variable_end_string="}") -tmpl = env.from_string("""\ -% macro foo() - ${caller(42)} -% endmacro -
      -% for item in seq -
    • ${item}
    • -% endfor -
    -% call(var) foo() - [${var}] -% endcall -% filter escape - - % for item in [1, 2, 3] - - ${item} - % endfor -% endfilter -""") - -print tmpl.render(seq=range(10)) diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/basic/test_loop_filter.py --- a/bundled/jinja2/examples/basic/test_loop_filter.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -from jinja2 import Environment - -tmpl = Environment().from_string("""\ -
      -{%- for item in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] if item % 2 == 0 %} -
    • {{ loop.index }} / {{ loop.length }}: {{ item }}
    • -{%- endfor %} -
    -if condition: {{ 1 if foo else 0 }} -""") - -print tmpl.render(foo=True) diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/basic/translate.py --- a/bundled/jinja2/examples/basic/translate.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -from jinja2 import Environment - -print Environment(extensions=['jinja2.i18n.TransExtension']).from_string("""\ -{% trans %}Hello {{ user }}!{% endtrans %} -{% trans count=users|count %}{{ count }} user{% pluralize %}{{ count }} users{% endtrans %} -""").render(user="someone") diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/bench.py --- a/bundled/jinja2/examples/bench.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,361 +0,0 @@ -"""\ - This benchmark compares some python templating engines with Jinja 2 so - that we get a picture of how fast Jinja 2 is for a semi real world - template. If a template engine is not installed the test is skipped.\ -""" -import sys -import cgi -from timeit import Timer -from jinja2 import Environment as JinjaEnvironment - -context = { - 'page_title': 'mitsuhiko\'s benchmark', - 'table': [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) for x in range(1000)] -} - -jinja_template = JinjaEnvironment( - line_statement_prefix='%', - variable_start_string="${", - variable_end_string="}" -).from_string("""\ - - - - ${page_title|e} - - -
    -

    ${page_title|e}

    -
    - -
    - - % for row in table - - % for cell in row - - % endfor - - % endfor -
    ${cell}
    -
    - -\ -""") - -def test_jinja(): - jinja_template.render(context) - -try: - from tornado.template import Template -except ImportError: - test_tornado = None -else: - tornado_template = Template("""\ - - - - {{ page_title }} - - -
    -

    {{ page_title }}

    -
    - -
    - - {% for row in table %} - - {% for cell in row %} - - {% end %} - - {% end %} -
    {{ cell }}
    -
    - -\ -""") - - def test_tornado(): - tornado_template.generate(**context) - -try: - from django.conf import settings - settings.configure() - from django.template import Template as DjangoTemplate, Context as DjangoContext -except ImportError: - test_django = None -else: - django_template = """\ - - - - {{ page_title }} - - -
    -

    {{ page_title }}

    -
    - -
    - - {% for row in table %} - - {% for cell in row %} - - {% endfor %} - - {% endfor %} -
    {{ cell }}
    -
    - -\ -""" - - def test_django(): - c = DjangoContext(context) - c['navigation'] = [('index.html', 'Index'), ('downloads.html', 'Downloads'), - ('products.html', 'Products')] - # recompile template each rendering because that's what django - # is doing in normal situations too. Django is not thread safe - # so we can't cache it in regular apps either. - DjangoTemplate(django_template).render(c) - -try: - from mako.template import Template as MakoTemplate -except ImportError: - test_mako = None -else: - mako_template = MakoTemplate("""\ - - - - ${page_title|h} - - -
    -

    ${page_title|h}

    -
    - -
    - - % for row in table: - - % for cell in row: - - % endfor - - % endfor -
    ${cell}
    -
    - -\ -""") - - def test_mako(): - mako_template.render(**context) - -try: - from genshi.template import MarkupTemplate as GenshiTemplate -except ImportError: - test_genshi = None -else: - genshi_template = GenshiTemplate("""\ - - - ${page_title} - - -
    -

    ${page_title}

    -
    - -
    - - - - -
    ${cell}
    -
    - -\ -""") - - def test_genshi(): - genshi_template.generate(**context).render('html', strip_whitespace=False) - -try: - from Cheetah.Template import Template as CheetahTemplate -except ImportError: - test_cheetah = None -else: - cheetah_template = CheetahTemplate("""\ -#import cgi - - - - $cgi.escape($page_title) - - -
    -

    $cgi.escape($page_title)

    -
    - -
    - - #for $row in $table: - - #for $cell in $row: - - #end for - - #end for -
    $cell
    -
    - -\ -""", searchList=[dict(context)]) - - def test_cheetah(): - unicode(cheetah_template) - -try: - import tenjin -except ImportError: - test_tenjin = None -else: - tenjin_template = tenjin.Template() - tenjin_template.convert("""\ - - - - ${page_title} - - -
    -

    ${page_title}

    -
    - -
    - - - - - - - - -
    #{cell}
    -
    - -\ -""") - - def test_tenjin(): - from tenjin.helpers import escape, to_str - tenjin_template.render(context, locals()) - -try: - from spitfire.compiler import util as SpitfireTemplate - from spitfire.compiler.analyzer import o2_options as spitfire_optimizer -except ImportError: - test_spitfire = None -else: - spitfire_template = SpitfireTemplate.load_template("""\ - - - - $cgi.escape($page_title) - - -
    -

    $cgi.escape($page_title)

    -
    - -
    - - #for $row in $table - - #for $cell in $row - - #end for - - #end for -
    $cell
    -
    - -\ -""", 'spitfire_tmpl', spitfire_optimizer, {'enable_filters': False}) - spitfire_context = dict(context, **{'cgi': cgi}) - - def test_spitfire(): - spitfire_template(search_list=[spitfire_context]).main() - -sys.stdout.write('\r' + '\n'.join(( - '=' * 80, - 'Template Engine BigTable Benchmark'.center(80), - '=' * 80, - __doc__, - '-' * 80 -)) + '\n') - - -for test in 'jinja', 'mako', 'tornado', 'tenjin', 'spitfire', 'django', 'genshi', 'cheetah': - if locals()['test_' + test] is None: - sys.stdout.write(' %-20s*not installed*\n' % test) - continue - t = Timer(setup='from __main__ import test_%s as bench' % test, - stmt='bench()') - sys.stdout.write(' >> %-20s' % test) - sys.stdout.flush() - sys.stdout.write('\r %-20s%.4f seconds\n' % (test, t.timeit(number=50) / 50)) -sys.stdout.write('-' * 80 + '\n') -sys.stdout.write('''\ - WARNING: The results of this benchmark are useless to compare the - performance of template engines and should not be taken seriously in any - way. It's testing the performance of simple loops and has no real-world - usefulnes. It only used to check if changes on the Jinja code affect - performance in a good or bad way and how it roughly compares to others. -''' + '=' * 80 + '\n') diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/profile.py --- a/bundled/jinja2/examples/profile.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -try: - from cProfile import Profile -except ImportError: - from profile import Profile -from pstats import Stats -from jinja2 import Environment as JinjaEnvironment - -context = { - 'page_title': 'mitsuhiko\'s benchmark', - 'table': [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) for x in range(1000)] -} - -source = """\ - - - - ${page_title|e} - - -
    -

    ${page_title|e}

    -
    -
    - - % for row in table - - % for cell in row - - % endfor - - % endfor -
    ${cell}
    -
    - -\ -""" -jinja_template = JinjaEnvironment( - line_statement_prefix='%', - variable_start_string="${", - variable_end_string="}" -).from_string(source) -print jinja_template.environment.compile(source, raw=True) - - -p = Profile() -p.runcall(lambda: jinja_template.render(context)) -stats = Stats(p) -stats.sort_stats('time', 'calls') -stats.print_stats() diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/django/_form.html --- a/bundled/jinja2/examples/rwbench/django/_form.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -
    {{ body }}
    diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/django/_input_field.html --- a/bundled/jinja2/examples/rwbench/django/_input_field.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/django/_textarea.html --- a/bundled/jinja2/examples/rwbench/django/_textarea.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/django/index.html --- a/bundled/jinja2/examples/rwbench/django/index.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -{% extends "layout.html" %} -{% block page_title %}Index Page{% endblock %} -{% block body %} - {% for article in articles %} - {% if article.published %} -
    -

    {{ article.title }}

    -

    written by {{ article.user.username }} on {{ article.pub_date|dateformat }}

    -
    {{ article.body|safe }}
    -
    - {% endif %} - {% endfor %} - {% form %} -
    -
    Name
    -
    {% input_field 'name' %}
    -
    E-Mail
    -
    {% input_field 'email' %}
    -
    URL
    -
    {% input_field 'url' %}
    -
    Comment
    -
    {% textarea 'comment' %}
    -
    Captcha
    -
    {% input_field 'captcha' %}
    -
    - {% input_field '' 'submit' 'Submit' %} - {% input_field 'cancel' 'submit' 'Cancel' %} - {% endform %} -{% endblock %} diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/django/layout.html --- a/bundled/jinja2/examples/rwbench/django/layout.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ - - - - {% block page_title %}{% endblock %} | RealWorld Benchmark - - - -
    -
    -

    RealWorld Benchmark

    -

    - A less stupid benchmark for Mako and Jinja2 to get an impression how - code changes affect runtime performance. -

    -
    - -
    - {% block body %}{% endblock %} -
    - -
    - - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/djangoext.py --- a/bundled/jinja2/examples/rwbench/djangoext.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -# -*- coding: utf-8 -*- -from rwbench import ROOT -from os.path import join -from django.conf import settings -settings.configure(TEMPLATE_DIRS=(join(ROOT, 'django'),)) -from django.template import loader as django_loader, Context as DjangoContext, \ - Node, NodeList, Variable, TokenParser -from django import template as django_template_module -from django.template import Library - - -# for django extensions. We monkey patch our extensions in so that -# we don't have to initialize a more complex django setup. -django_extensions = django_template_module.Library() -django_template_module.builtins.append(django_extensions) - - -from rwbench import dateformat -django_extensions.filter(dateformat) - - -def var_or_none(x): - if x is not None: - return Variable(x) - - -# and more django extensions -@django_extensions.tag -def input_field(parser, token): - p = TokenParser(token.contents) - args = [p.value()] - while p.more(): - args.append(p.value()) - return InputFieldNode(*args) - - -@django_extensions.tag -def textarea(parser, token): - p = TokenParser(token.contents) - args = [p.value()] - while p.more(): - args.append(p.value()) - return TextareaNode(*args) - - -@django_extensions.tag -def form(parser, token): - p = TokenParser(token.contents) - args = [] - while p.more(): - args.append(p.value()) - body = parser.parse(('endform',)) - parser.delete_first_token() - return FormNode(body, *args) - - -class InputFieldNode(Node): - - def __init__(self, name, type=None, value=None): - self.name = var_or_none(name) - self.type = var_or_none(type) - self.value = var_or_none(value) - - def render(self, context): - name = self.name.resolve(context) - type = 'text' - value = '' - if self.type is not None: - type = self.type.resolve(context) - if self.value is not None: - value = self.value.resolve(context) - tmpl = django_loader.get_template('_input_field.html') - return tmpl.render(DjangoContext({ - 'name': name, - 'type': type, - 'value': value - })) - - -class TextareaNode(Node): - - def __init__(self, name, rows=None, cols=None, value=None): - self.name = var_or_none(name) - self.rows = var_or_none(rows) - self.cols = var_or_none(cols) - self.value = var_or_none(value) - - def render(self, context): - name = self.name.resolve(context) - rows = 10 - cols = 40 - value = '' - if self.rows is not None: - rows = int(self.rows.resolve(context)) - if self.cols is not None: - cols = int(self.cols.resolve(context)) - if self.value is not None: - value = self.value.resolve(context) - tmpl = django_loader.get_template('_textarea.html') - return tmpl.render(DjangoContext({ - 'name': name, - 'rows': rows, - 'cols': cols, - 'value': value - })) - - -class FormNode(Node): - - def __init__(self, body, action=None, method=None): - self.body = body - self.action = action - self.method = method - - def render(self, context): - body = self.body.render(context) - action = '' - method = 'post' - if self.action is not None: - action = self.action.resolve(context) - if self.method is not None: - method = self.method.resolve(context) - tmpl = django_loader.get_template('_form.html') - return tmpl.render(DjangoContext({ - 'body': body, - 'action': action, - 'method': method - })) diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/genshi/helpers.html --- a/bundled/jinja2/examples/rwbench/genshi/helpers.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -
    - - - - - - - - - -
    diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/genshi/index.html --- a/bundled/jinja2/examples/rwbench/genshi/index.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ - - - - - Index Page - -
    - -

    ${article.title}

    -

    written by ${article.user.username} on ${dateformat(article.pub_date)}

    -
    ${Markup(article.body)}
    -
    -
    - -
    -
    -
    Name
    -
    ${input_field('name')}
    -
    E-Mail
    -
    ${input_field('email')}
    -
    URL
    -
    ${input_field('url')}
    -
    Comment
    -
    ${textarea('comment')}
    -
    Captcha
    -
    ${input_field('captcha')}
    -
    - ${input_field(type='submit', value='Submit')} - ${input_field(name='cancel', type='submit', value='Cancel')} -
    - - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/genshi/layout.html --- a/bundled/jinja2/examples/rwbench/genshi/layout.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - ${select('title/text()')} | RealWorld Benchmark - - - - - -
    -
    -

    RealWorld Benchmark

    -

    - A less stupid benchmark for Mako and Jinja2 to get an impression how - code changes affect runtime performance. -

    -
    - -
    - ${select('*|text()')} -
    - -
    - -
    - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/jinja/helpers.html --- a/bundled/jinja2/examples/rwbench/jinja/helpers.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -{% macro input_field(name, value='', type='text') -%} - -{%- endmacro %} - -{% macro textarea(name, value='', rows=10, cols=40) -%} - -{%- endmacro %} - -{% macro form(action='', method='post') -%} -
    {{ caller() }}
    -{%- endmacro %} diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/jinja/index.html --- a/bundled/jinja2/examples/rwbench/jinja/index.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -{% extends "layout.html" %} -{% from "helpers.html" import input_field, textarea, form %} -{% block page_title %}Index Page{% endblock %} -{% block body %} - {%- for article in articles if article.published %} -
    -

    {{ article.title|e }}

    -

    written by {{ article.user.username|e }} on {{ article.pub_date|dateformat }}

    -
    {{ article.body }}
    -
    - {%- endfor %} - {%- call form() %} -
    -
    Name
    -
    {{ input_field('name') }}
    -
    E-Mail
    -
    {{ input_field('email') }}
    -
    URL
    -
    {{ input_field('url') }}
    -
    Comment
    -
    {{ textarea('comment') }}
    -
    Captcha
    -
    {{ input_field('captcha') }}
    -
    - {{ input_field(type='submit', value='Submit') }} - {{ input_field('cancel', type='submit', value='Cancel') }} - {%- endcall %} -{% endblock %} diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/jinja/layout.html --- a/bundled/jinja2/examples/rwbench/jinja/layout.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ - - - - {% block page_title %}{% endblock %} | RealWorld Benchmark - - - -
    -
    -

    RealWorld Benchmark

    -

    - A less stupid benchmark for Mako and Jinja2 to get an impression how - code changes affect runtime performance. -

    -
    - -
    - {% block body %}{% endblock %} -
    - -
    - - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/mako/helpers.html --- a/bundled/jinja2/examples/rwbench/mako/helpers.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -<%def name="input_field(name='', value='', type='text')"> - - - -<%def name="textarea(name, value='', rows=10, cols=40)"> - - - -<%def name="form(action='', method='post')"> -
    ${caller.body()}
    - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/mako/index.html --- a/bundled/jinja2/examples/rwbench/mako/index.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -<%! - from rwbench import dateformat -%> -<%inherit file="layout.html" /> -<%namespace file="helpers.html" import="input_field, textarea, form" /> -<%def name="page_title()">Index Page -% for article in articles: - <% if not article.published: continue %> -
    -

    ${article.title|h}

    -

    written by ${article.user.username|h} on ${dateformat(article.pub_date)}

    -
    ${article.body}
    -
    -% endfor -<%call expr="form()"> -
    -
    Name
    -
    ${input_field('name')}
    -
    E-Mail
    -
    ${input_field('email')}
    -
    URL
    -
    ${input_field('url')}
    -
    Comment
    -
    ${textarea('comment')}
    -
    Captcha
    -
    ${input_field('captcha')}
    -
    - ${input_field(type='submit', value='Submit')} - ${input_field(name='cancel', type='submit', value='Cancel')} - diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/mako/layout.html --- a/bundled/jinja2/examples/rwbench/mako/layout.html Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - ${self.page_title()} | RealWorld Benchmark - - - -
    -
    -

    RealWorld Benchmark

    -

    - A less stupid benchmark for Mako and Jinja2 to get an impression how - code changes affect runtime performance. -

    -
    - -
    - ${self.body()} -
    - -
    - - -<%def name="page_title()"> diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/examples/rwbench/rwbench.py --- a/bundled/jinja2/examples/rwbench/rwbench.py Fri Jun 11 20:14:01 2010 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -""" - RealWorldish Benchmark - ~~~~~~~~~~~~~~~~~~~~~~ - - A more real-world benchmark of Jinja2. Like the other benchmark in the - Jinja2 repository this has no real-world usefulnes (despite the name). - Just go away and ignore it. NOW! - - :copyright: (c) 2009 by the Jinja Team. - :license: BSD. -""" -import sys -from os.path import join, dirname, abspath -ROOT = abspath(dirname(__file__)) - -from random import choice, randrange -from datetime import datetime -from timeit import Timer -from jinja2 import Environment, FileSystemLoader -from jinja2.utils import generate_lorem_ipsum -from mako.lookup import TemplateLookup -from genshi.template import TemplateLoader as GenshiTemplateLoader - - -def dateformat(x): - return x.strftime('%Y-%m-%d') - - -jinja_env = Environment(loader=FileSystemLoader(join(ROOT, 'jinja'))) -jinja_env.filters['dateformat'] = dateformat -mako_lookup = TemplateLookup(directories=[join(ROOT, 'mako')]) -genshi_loader = GenshiTemplateLoader([join(ROOT, 'genshi')]) - -class Article(object): - - def __init__(self, id): - self.id = id - self.href = '/article/%d' % self.id - self.title = generate_lorem_ipsum(1, False, 5, 10) - self.user = choice(users) - self.body = generate_lorem_ipsum() - self.pub_date = datetime.utcfromtimestamp(randrange(10 ** 9, 2 * 10 ** 9)) - self.published = True - - -class User(object): - - def __init__(self, username): - self.href = '/user/%s' % username - self.username = username - - -users = map(User, [u'John Doe', u'Jane Doe', u'Peter Somewhat']) -articles = map(Article, range(20)) -navigation = [ - ('index', 'Index'), - ('about', 'About'), - ('foo?bar=1', 'Foo with Bar'), - ('foo?bar=2&s=x', 'Foo with X'), - ('blah', 'Blub Blah'), - ('hehe', 'Haha'), -] * 5 - -context = dict(users=users, articles=articles, page_navigation=navigation) - - -jinja_template = jinja_env.get_template('index.html') -mako_template = mako_lookup.get_template('index.html') -genshi_template = genshi_loader.load('index.html') - - -def test_jinja(): - jinja_template.render(context) - -def test_mako(): - mako_template.render_unicode(**context) - - -from djangoext import django_loader, DjangoContext -def test_django(): - # not cached because django is not thread safe and does - # not cache by itself so it would be unfair to cache it here. - django_template = django_loader.get_template('index.html') - django_template.render(DjangoContext(context)) - - -def test_genshi(): - genshi_template.generate(**context).render('html', doctype='html') - - -if __name__ == '__main__': - sys.stdout.write('Realworldish Benchmark:\n') - for test in 'jinja', 'mako', 'django', 'genshi': - t = Timer(setup='from __main__ import test_%s as bench' % test, - stmt='bench()') - sys.stdout.write(' >> %-20s' % test) - sys.stdout.flush() - sys.stdout.write('\r %-20s%.4f seconds\n' % (test, t.timeit(number=200) / 200)) diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/jinja2/__init__.py --- a/bundled/jinja2/jinja2/__init__.py Fri Jun 11 20:14:01 2010 -0400 +++ b/bundled/jinja2/jinja2/__init__.py Fri Jun 11 20:32:12 2010 -0400 @@ -38,7 +38,8 @@ # loaders from jinja2.loaders import BaseLoader, FileSystemLoader, PackageLoader, \ - DictLoader, FunctionLoader, PrefixLoader, ChoiceLoader + DictLoader, FunctionLoader, PrefixLoader, ChoiceLoader, \ + ModuleLoader # bytecode caches from jinja2.bccache import BytecodeCache, FileSystemBytecodeCache, \ @@ -53,9 +54,11 @@ TemplateAssertionError # decorators and public utilities -from jinja2.filters import environmentfilter, contextfilter +from jinja2.filters import environmentfilter, contextfilter, \ + evalcontextfilter from jinja2.utils import Markup, escape, clear_caches, \ - environmentfunction, contextfunction, is_undefined + environmentfunction, evalcontextfunction, contextfunction, \ + is_undefined __all__ = [ 'Environment', 'Template', 'BaseLoader', 'FileSystemLoader', @@ -64,6 +67,7 @@ 'MemcachedBytecodeCache', 'Undefined', 'DebugUndefined', 'StrictUndefined', 'TemplateError', 'UndefinedError', 'TemplateNotFound', 'TemplatesNotFound', 'TemplateSyntaxError', 'TemplateAssertionError', - 'environmentfilter', 'contextfilter', 'Markup', 'escape', - 'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined' + 'ModuleLoader', 'environmentfilter', 'contextfilter', 'Markup', 'escape', + 'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined', + 'evalcontextfilter', 'evalcontextfunction' ] diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/jinja2/compiler.py --- a/bundled/jinja2/jinja2/compiler.py Fri Jun 11 20:14:01 2010 -0400 +++ b/bundled/jinja2/jinja2/compiler.py Fri Jun 11 20:32:12 2010 -0400 @@ -12,6 +12,7 @@ from itertools import chain from copy import deepcopy from jinja2 import nodes +from jinja2.nodes import EvalContext from jinja2.visitor import NodeVisitor, NodeTransformer from jinja2.exceptions import TemplateAssertionError from jinja2.utils import Markup, concat, escape, is_python_keyword, next @@ -53,11 +54,12 @@ unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure) -def generate(node, environment, name, filename, stream=None): +def generate(node, environment, name, filename, stream=None, + defer_init=False): """Generate the python source for a node tree.""" if not isinstance(node, nodes.Template): raise TypeError('Can\'t compile non template nodes') - generator = CodeGenerator(environment, name, filename, stream) + generator = CodeGenerator(environment, name, filename, stream, defer_init) generator.visit(node) if stream is None: return generator.stream.getvalue() @@ -140,7 +142,8 @@ class Frame(object): """Holds compile time information for us.""" - def __init__(self, parent=None): + def __init__(self, eval_ctx, parent=None): + self.eval_ctx = eval_ctx self.identifiers = Identifiers() # a toplevel frame is the root + soft frames such as if conditions. @@ -210,7 +213,7 @@ def inner(self): """Return an inner frame.""" - return Frame(self) + return Frame(self.eval_ctx, self) def soft(self): """Return a soft frame. A soft frame may not be modified as @@ -290,8 +293,7 @@ self.visit(node.test) real_identifiers = self.identifiers - old_names = real_identifiers.declared | \ - real_identifiers.declared_locally | \ + old_names = real_identifiers.declared_locally | \ real_identifiers.declared_parameter def inner_visit(nodes): @@ -312,7 +314,8 @@ # the differences between the two branches are also pulled as # undeclared variables - real_identifiers.undeclared.update(body.symmetric_difference(else_)) + real_identifiers.undeclared.update(body.symmetric_difference(else_) - + real_identifiers.declared) # remember those that are declared. real_identifiers.declared_locally.update(body | else_) @@ -365,7 +368,8 @@ class CodeGenerator(NodeVisitor): - def __init__(self, environment, name, filename, stream=None): + def __init__(self, environment, name, filename, stream=None, + defer_init=False): if stream is None: stream = StringIO() self.environment = environment @@ -373,6 +377,7 @@ self.filename = filename self.stream = stream self.created_block_context = False + self.defer_init = defer_init # aliases for imports self.import_aliases = {} @@ -419,7 +424,7 @@ # -- Various compilation helpers def fail(self, msg, lineno): - """Fail with a `TemplateAssertionError`.""" + """Fail with a :exc:`TemplateAssertionError`.""" raise TemplateAssertionError(msg, lineno, self.name, self.filename) def temporary_identifier(self): @@ -434,7 +439,16 @@ def return_buffer_contents(self, frame): """Return the buffer contents of the frame.""" - if self.environment.autoescape: + if frame.eval_ctx.volatile: + self.writeline('if context.eval_ctx.autoescape:') + self.indent() + self.writeline('return Markup(concat(%s))' % frame.buffer) + self.outdent() + self.writeline('else:') + self.indent() + self.writeline('return concat(%s)' % frame.buffer) + self.outdent() + elif frame.eval_ctx.autoescape: self.writeline('return Markup(concat(%s))' % frame.buffer) else: self.writeline('return concat(%s)' % frame.buffer) @@ -747,12 +761,18 @@ def visit_Template(self, node, frame=None): assert frame is None, 'no root frame allowed' + eval_ctx = EvalContext(self.environment, self.name) + from jinja2.runtime import __all__ as exported self.writeline('from __future__ import division') self.writeline('from jinja2.runtime import ' + ', '.join(exported)) if not unoptimize_before_dead_code: self.writeline('dummy = lambda *x: None') + # if we want a deferred initialization we cannot move the + # environment into a local name + envenv = not self.defer_init and ', environment=environment' or '' + # do we have an extends tag at all? If not, we can save some # overhead by just not processing any inheritance code. have_extends = node.find(nodes.Extends) is not None @@ -779,10 +799,10 @@ self.writeline('name = %r' % self.name) # generate the root render function. - self.writeline('def root(context, environment=environment):', extra=1) + self.writeline('def root(context%s):' % envenv, extra=1) # process the root - frame = Frame() + frame = Frame(eval_ctx) frame.inspect(node.body) frame.toplevel = frame.rootlevel = True frame.require_output_check = have_extends and not self.has_known_extends @@ -811,11 +831,11 @@ # at this point we now have the blocks collected and can visit them too. for name, block in self.blocks.iteritems(): - block_frame = Frame() + block_frame = Frame(eval_ctx) block_frame.inspect(block.body) block_frame.block = name - self.writeline('def block_%s(context, environment=environment):' - % name, block, 1) + self.writeline('def block_%s(context%s):' % (name, envenv), + block, 1) self.indent() undeclared = find_undeclared(block.body, ('self', 'super')) if 'self' in undeclared: @@ -1217,12 +1237,15 @@ body = [] for child in node.nodes: try: - const = child.as_const() + const = child.as_const(frame.eval_ctx) except nodes.Impossible: body.append(child) continue + # the frame can't be volatile here, becaus otherwise the + # as_const() function would raise an Impossible exception + # at that point. try: - if self.environment.autoescape: + if frame.eval_ctx.autoescape: if hasattr(const, '__html__'): const = const.__html__() else: @@ -1260,7 +1283,10 @@ else: self.newline(item) close = 1 - if self.environment.autoescape: + if frame.eval_ctx.volatile: + self.write('(context.eval_ctx.autoescape and' + ' escape or to_string)(') + elif frame.eval_ctx.autoescape: self.write('escape(') else: self.write('to_string(') @@ -1293,7 +1319,11 @@ for argument in arguments: self.newline(argument) close = 0 - if self.environment.autoescape: + if frame.eval_ctx.volatile: + self.write('(context.eval_ctx.autoescape and' + ' escape or to_string)(') + close += 1 + elif frame.eval_ctx.autoescape: self.write('escape(') close += 1 if self.environment.finalize is not None: @@ -1360,7 +1390,11 @@ self.write(repr(val)) def visit_TemplateData(self, node, frame): - self.write(repr(node.as_const())) + try: + self.write(repr(node.as_const(frame.eval_ctx))) + except nodes.Impossible: + self.write('(context.eval_ctx.autoescape and Markup or identity)(%r)' + % node.data) def visit_Tuple(self, node, frame): self.write('(') @@ -1420,8 +1454,14 @@ del binop, uaop def visit_Concat(self, node, frame): - self.write('%s((' % (self.environment.autoescape and - 'markup_join' or 'unicode_join')) + if frame.eval_ctx.volatile: + func_name = '(context.eval_ctx.volatile and' \ + ' markup_join or unicode_join)' + elif frame.eval_ctx.autoescape: + func_name = 'markup_join' + else: + func_name = 'unicode_join' + self.write('%s((' % func_name) for arg in node.nodes: self.visit(arg, frame) self.write(', ') @@ -1472,6 +1512,8 @@ self.fail('no filter named %r' % node.name, node.lineno) if getattr(func, 'contextfilter', False): self.write('context, ') + elif getattr(func, 'evalcontextfilter', False): + self.write('context.eval_ctx, ') elif getattr(func, 'environmentfilter', False): self.write('environment, ') @@ -1479,7 +1521,11 @@ # and want to write to the current buffer if node.node is not None: self.visit(node.node, frame) - elif self.environment.autoescape: + elif frame.eval_ctx.volatile: + self.write('(context.eval_ctx.autoescape and' + ' Markup(concat(%s)) or concat(%s))' % + (frame.buffer, frame.buffer)) + elif frame.eval_ctx.autoescape: self.write('Markup(concat(%s))' % frame.buffer) else: self.write('concat(%s)' % frame.buffer) @@ -1540,6 +1586,11 @@ self.visit(node.expr, frame) self.write(')') + def visit_MarkSafeIfAutoescape(self, node, frame): + self.write('(context.eval_ctx.autoescape and Markup or identity)(') + self.visit(node.expr, frame) + self.write(')') + def visit_EnvironmentAttribute(self, node, frame): self.write('environment.' + node.name) @@ -1568,3 +1619,24 @@ self.pull_locals(scope_frame) self.blockvisit(node.body, scope_frame) self.pop_scope(aliases, scope_frame) + + def visit_EvalContextModifier(self, node, frame): + for keyword in node.options: + self.writeline('context.eval_ctx.%s = ' % keyword.key) + self.visit(keyword.value, frame) + try: + val = keyword.value.as_const(frame.eval_ctx) + except nodes.Impossible: + frame.eval_ctx.volatile = True + else: + setattr(frame.eval_ctx, keyword.key, val) + + def visit_ScopedEvalContextModifier(self, node, frame): + old_ctx_name = self.temporary_identifier() + safed_ctx = frame.eval_ctx.save() + self.writeline('%s = context.eval_ctx.save()' % old_ctx_name) + self.visit_EvalContextModifier(node, frame) + for child in node.body: + self.visit(child, frame) + frame.eval_ctx.revert(safed_ctx) + self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name) diff -r b2bd9c232faa -r 9a463602589d bundled/jinja2/jinja2/environment.py --- a/bundled/jinja2/jinja2/environment.py Fri Jun 11 20:14:01 2010 -0400 +++ b/bundled/jinja2/jinja2/environment.py Fri Jun 11 20:32:12 2010 -0400 @@ -8,6 +8,7 @@ :copyright: (c) 2010 by the Jinja Team. :license: BSD, see LICENSE for more details. """ +import os import sys from jinja2 import nodes from jinja2.defaults import * @@ -157,9 +158,15 @@ `None` implicitly into an empty string here. `autoescape` - If set to true the XML/HTML autoescaping feature is enabled. - For more details about auto escaping see - :class:`~jinja2.utils.Markup`. + If set to true the XML/HTML autoescaping feature is enabled by + default. For more details about auto escaping see + :class:`~jinja2.utils.Markup`. As of Jinja 2.4 this can also + be a callable that is passed the template name and has to + return `True` or `False` depending on autoescape should be + enabled by default. + + .. versionchanged:: 2.4 + `autoescape` can now be a function `loader` The template loader for this environment. @@ -272,6 +279,13 @@ _environment_sanity_check(self) + def add_extension(self, extension): + """Adds an extension after the environment was created. + + .. versionadded:: 2.5 + """ + self.extensions.update(load_extensions(self, [extension])) + def extend(self, **attributes): """Add the items to the instance of the environment if they do not exist yet. This is used by :ref:`extensions ` to register @@ -327,6 +341,11 @@ lexer = property(get_lexer, doc="The lexer for this environment.") + def iter_extensions(self): + """Iterates over the extensions by priority.""" + return iter(sorted(self.extensions.values(), + key=lambda x: x.priority)) + def getitem(self, obj, argument): """Get an item or attribute of an object but prefer the item.""" try: @@ -400,7 +419,7 @@ because there you usually only want the actual source tokenized. """ return reduce(lambda s, e: e.preprocess(s, name, filename), - self.extensions.itervalues(), unicode(source)) + self.iter_extensions(), unicode(source)) def _tokenize(self, source, name, filename=None, state=None): """Called by the parser to do the preprocessing and filtering @@ -408,14 +427,31 @@ """ source = self.preprocess(source, name, filename) stream = self.lexer.tokenize(source, name, filename, state) - for ext in self.extensions.itervalues(): + for ext in self.iter_extensions(): stream = ext.filter_stream(stream) if not isinstance(stream, TokenStream): stream = TokenStream(stream, name, filename) return stream + def _generate(self, source, name, filename, defer_init=False): + """Internal hook that can be overriden to hook a different generate + method in. + + .. versionadded:: 2.5 + """ + return generate(source, self, name, filename, defer_init=defer_init) + + def _compile(self, source, filename): + """Internal hook that can be overriden to hook a different compile + method in. + + .. versionadded:: 2.5 + """ + return compile(source, filename, 'exec') + @internalcode - def compile(self, source, name=None, filename=None, raw=False): + def compile(self, source, name=None, filename=None, raw=False, + defer_init=False): """Compile a node or template source code. The `name` parameter is the load name of the template after it was joined using :meth:`join_path` if necessary, not the filename on the file system. @@ -427,6 +463,13 @@ parameter is `True` the return value will be a string with python code equivalent to the bytecode returned otherwise. This method is mainly used internally. + + `defer_init` is use internally to aid the module code generator. This + causes the generated code to be able to import without the global + environment variable to be set. + + .. versionadded:: 2.4 + `defer_init` parameter added. """ source_hint = None try: @@ -435,14 +478,15 @@ source = self._parse(source, name, filename) if self.optimized: source = optimize(source, self) - source = generate(source, self, name, filename) + source = self._generate(source, name, filename, + defer_init=defer_init) if raw: return source if filename is None: filename = '