Edgewall Software

Version 1 (modified by cmlenz, 18 years ago) (diff)

API documentation for 0.3.x branch

Title(genshi.template)?

genshi.template

Implementation of the template engine.

TemplateError

Base exception class for errors related to template processing.

TemplateSyntaxError

Exception raised when an expression in a template causes a Python syntax error.

BadDirectiveError

Exception raised when an unknown directive is encountered when parsing a template.

An unknown directive is any attribute using the namespace for directives, with a local name that doesn't match any registered directive.

TemplateRuntimeError

Exception raised when an the evualation of a Python expression in a template causes an error.

TemplateNotFound

Exception raised when a specific template file could not be found.

Context

Container for template input data.

A context provides a stack of scopes (represented by dictionaries).

Template directives such as loops can push a new scope on the stack with data that should only be available inside the loop. When the loop terminates, that scope can get popped off the stack again.

>>> ctxt = Context(one='foo', other=1)
>>> ctxt.get('one')
'foo'
>>> ctxt.get('other')
1
>>> ctxt.push(dict(one='frost'))
>>> ctxt.get('one')
'frost'
>>> ctxt.get('other')
1
>>> ctxt.pop()
{'one': 'frost'}
>>> ctxt.get('one')
'foo'

get(self, key, default=None)

Get a variable's value, starting at the current scope and going upward.

push(self, data)

Push a new scope on the stack.

pop(self)

Pop the top-most scope from the stack.

Directive

Abstract base class for template directives.

A directive is basically a callable that takes three positional arguments: ctxt is the template data context, stream is an iterable over the events that the directive applies to, and directives is is a list of other directives on the same stream that need to be applied.

Directives can be "anonymous" or "registered". Registered directives can be applied by the template author using an XML attribute with the corresponding name in the template. Such directives should be subclasses of this base class that can be instantiated with the value of the directive attribute as parameter.

Anonymous directives are simply functions conforming to the protocol described above, and can only be applied programmatically (for example by template filters).

tagname(self)

Return the local tag name of the directive as it is used in templates.

AttrsDirective

Implementation of the py:attrs template directive.

The value of the py:attrs attribute should be a dictionary or a sequence of (name, value) tuples. The items in that dictionary or sequence are added as attributes to the element:

>>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/">
...   <li py:attrs="foo">Bar</li>
... </ul>''')
>>> print tmpl.generate(foo={'class': 'collapse'})
<ul>
  <li class="collapse">Bar</li>
</ul>
>>> print tmpl.generate(foo=[('class', 'collapse')])
<ul>
  <li class="collapse">Bar</li>
</ul>

If the value evaluates to None (or any other non-truth value), no attributes are added:

>>> print tmpl.generate(foo=None)
<ul>
  <li>Bar</li>
</ul>

ContentDirective

Implementation of the py:content template directive.

This directive replaces the content of the element with the result of evaluating the value of the py:content attribute:

>>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/">
...   <li py:content="bar">Hello</li>
... </ul>''')
>>> print tmpl.generate(bar='Bye')
<ul>
  <li>Bye</li>
</ul>

DefDirective

Implementation of the py:def template directive.

This directive can be used to create "Named Template Functions", which are template snippets that are not actually output during normal processing, but rather can be expanded from expressions in other places in the template.

A named template function can be used just like a normal Python function from template expressions:

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
...   <p py:def="echo(greeting, name='world')" class="message">
...     ${greeting}, ${name}!
...   </p>
...   ${echo('Hi', name='you')}
... </div>''')
>>> print tmpl.generate(bar='Bye')
<div>
  <p class="message">
    Hi, you!
  </p>
</div>

If a function does not require parameters, the parenthesis can be omitted both when defining and when calling it:

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
...   <p py:def="helloworld" class="message">
...     Hello, world!
...   </p>
...   ${helloworld}
... </div>''')
>>> print tmpl.generate(bar='Bye')
<div>
  <p class="message">
    Hello, world!
  </p>
</div>

ForDirective

Implementation of the py:for template directive for repeating an element based on an iterable in the context data.

>>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/">
...   <li py:for="item in items">${item}</li>
... </ul>''')
>>> print tmpl.generate(items=[1, 2, 3])
<ul>
  <li>1</li><li>2</li><li>3</li>
</ul>

IfDirective

Implementation of the py:if template directive for conditionally excluding elements from being output.

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
...   <b py:if="foo">${bar}</b>
... </div>''')
>>> print tmpl.generate(foo=True, bar='Hello')
<div>
  <b>Hello</b>
</div>

MatchDirective

Implementation of the py:match template directive.

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
...   <span py:match="greeting">
...     Hello ${select('@name')}
...   </span>
...   <greeting name="Dude" />
... </div>''')
>>> print tmpl.generate()
<div>
  <span>
    Hello Dude
  </span>
</div>

ReplaceDirective

Implementation of the py:replace template directive.

This directive replaces the element with the result of evaluating the value of the py:replace attribute:

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
...   <span py:replace="bar">Hello</span>
... </div>''')
>>> print tmpl.generate(bar='Bye')
<div>
  Bye
</div>

This directive is equivalent to py:content combined with py:strip, providing a less verbose way to achieve the same effect:

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
...   <span py:content="bar" py:strip="">Hello</span>
... </div>''')
>>> print tmpl.generate(bar='Bye')
<div>
  Bye
</div>

StripDirective

Implementation of the py:strip template directive.

When the value of the py:strip attribute evaluates to True, the element is stripped from the output

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
...   <div py:strip="True"><b>foo</b></div>
... </div>''')
>>> print tmpl.generate()
<div>
  <b>foo</b>
</div>

Leaving the attribute value empty is equivalent to a truth value.

This directive is particulary interesting for named template functions or match templates that do not generate a top-level element:

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
...   <div py:def="echo(what)" py:strip="">
...     <b>${what}</b>
...   </div>
...   ${echo('foo')}
... </div>''')
>>> print tmpl.generate()
<div>
    <b>foo</b>
</div>

ChooseDirective

Implementation of the py:choose directive for conditionally selecting one of several body elements to display.

If the py:choose expression is empty the expressions of nested py:when directives are tested for truth. The first true py:when body is output. If no py:when directive is matched then the fallback directive py:otherwise will be used.

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/"
...   py:choose="">
...   <span py:when="0 == 1">0</span>
...   <span py:when="1 == 1">1</span>
...   <span py:otherwise="">2</span>
... </div>''')
>>> print tmpl.generate()
<div>
  <span>1</span>
</div>

If the py:choose directive contains an expression, the nested py:when directives are tested for equality to the py:choose expression:

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/"
...   py:choose="2">
...   <span py:when="1">1</span>
...   <span py:when="2">2</span>
... </div>''')
>>> print tmpl.generate()
<div>
  <span>2</span>
</div>

Behavior is undefined if a py:choose block contains content outside a py:when or py:otherwise block. Behavior is also undefined if a py:otherwise occurs before py:when blocks.

WhenDirective

Implementation of the py:when directive for nesting in a parent with the py:choose directive.

See the documentation of py:choose for usage.

OtherwiseDirective

Implementation of the py:otherwise directive for nesting in a parent with the py:choose directive.

See the documentation of py:choose for usage.

WithDirective

Implementation of the py:with template directive, which allows shorthand access to variables and expressions.

>>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
...   <span py:with="y=7; z=x+10">$x $y $z</span>
... </div>''')
>>> print tmpl.generate(x=42)
<div>
  <span>42 7 52</span>
</div>

TemplateMeta

Meta class for templates.

Template

Abstract template base class.

This class implements most of the template processing model, but does not specify the syntax of templates.

generate(self, **args, *kwargs)

Apply the template to the given context data.

Any keyword arguments are made available to the template as context data.

Only one positional argument is accepted: if it is provided, it must be an instance of the Context class, and keyword arguments are ignored. This calling style is used for internal processing.

@return: a markup event stream representing the result of applying
the template to the context data.

MarkupTemplate

Implementation of the template language for XML-based templates.

>>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/">
...   <li py:for="item in items">${item}</li>
... </ul>''')
>>> print tmpl.generate(items=[1, 2, 3])
<ul>
  <li>1</li><li>2</li><li>3</li>
</ul>

TextTemplate

Implementation of a simple text-based template engine.

>>> tmpl = TextTemplate('''Dear $name,
...
... We have the following items for you:
... #for item in items
...  * $item
... #end
...
... All the best,
... Foobar''')
>>> print tmpl.generate(name='Joe', items=[1, 2, 3]).render('text')
Dear Joe,
<BLANKLINE>
We have the following items for you:
 * 1
 * 2
 * 3
<BLANKLINE>
All the best,
Foobar

TemplateLoader

Responsible for loading templates from files on the specified search path.

>>> import tempfile
>>> fd, path = tempfile.mkstemp(suffix='.html', prefix='template')
>>> os.write(fd, '<p>$var</p>')
11
>>> os.close(fd)

The template loader accepts a list of directory paths that are then used when searching for template files, in the given order:

>>> loader = TemplateLoader([os.path.dirname(path)])

The load() method first checks the template cache whether the requested template has already been loaded. If not, it attempts to locate the template file, and returns the corresponding Template object:

>>> template = loader.load(os.path.basename(path))
>>> isinstance(template, MarkupTemplate)
True

Template instances are cached: requesting a template with the same name results in the same instance being returned:

>>> loader.load(os.path.basename(path)) is template
True
>>> os.remove(path)

load(self, filename, relative_to=None, cls=MarkupTemplate, encoding=None)

Load the template with the given name.

If the filename parameter is relative, this method searches the search path trying to locate a template matching the given name. If the file name is an absolute path, the search path is not bypassed.

If requested template is not found, a TemplateNotFound exception is raised. Otherwise, a Template object is returned that represents the parsed template.

Template instances are cached to avoid having to parse the same template file more than once. Thus, subsequent calls of this method with the same template file name will return the same Template object (unless the auto_reload option is enabled and the file was changed since the last parse.)

If the relative_to parameter is provided, the filename is interpreted as being relative to that path.

@param filename: the relative path of the template file to load @param relative_to: the filename of the template from which the new

System Message: ERROR/3 (<string>, line 22)

Unexpected indentation.
template is being loaded, or None if the template is being loaded directly

System Message: WARNING/2 (<string>, line 24)

Block quote ends without a blank line; unexpected unindent.

@param cls: the class of the template object to instantiate @param encoding: the encoding of the template to load; defaults to the

System Message: ERROR/3 (<string>, line 26)

Unexpected indentation.
default_encoding of the loader instance


See Genshi XML Template Language, Genshi Text Template Language, ApiDocs/0.3.x, Documentation