    Genshi templates
    ================

    This test demonstrates the compilation of the Genshi language.

      >>> import chameleon.genshi.language
      >>> import chameleon.core.testing
      >>> def render(body, encoding=None, **kwargs):
      ...     parser = chameleon.genshi.language.Parser()
      ...     mt = kwargs['match_templates'] = chameleon.genshi.language.MatchTemplates()
      ...     func = chameleon.core.testing.compile_template(
      ...         parser, parser, body, encoding=encoding, **kwargs)
      ...     result = func(**kwargs)
      ...     return mt.process(result)

    py:if

      >>> print render("""\
      ...
...
...

Bar

...
...
...

Foo

...
... ... Bar ... ... ... Foo ... ...
""")

Foo

Foo
py:if can be used to make an XInclude optional: >>> print render("""\ ...
... ...
""")
py:if with a lambda: >>> print render("""\ ...
...

... All numbers are odd. ...

...
""")

All numbers are odd.

py:choose, py:when, py:otherwise >>> print render("""\ ...
...
... 0 ... 1 ...
... 2 ... 3 ...
... 3 ... 4 ...
...
... 3 ...
... 1 ... 1 ...
...
... 1 ... 2 ...
...
...
""")
1
2
3
1
2
py:for >>> print render("""\ ...

...
- ${item}
... ...
- ${item}
... ...

""")

- 0
- 1
- 2
- 3
- 4

py:for with tuples >>> print render("""\ ...

...
- ${key}=$value
...

""")

- one=1
- two=2
- three=3

py:def >>> print render("""\ ...
...

... Hello, ${name}! ...

      ...  ${greeting('world')}
      ...  ${greeting('everyone else')}
      ...
...

Goodbye, ${name}!

...
      ...  ${goodbye('world')}
      ...  ${goodbye('everyone')}
      ...
""")

Hello, world!

Hello, everyone else!

Goodbye, world!

Goodbye, everyone!

    py:with

      >>> def quote():
      ...     return dict(author=u"Some name", quote=u"Some random quote")

      >>> print render("""\
      ...
... ${x} ${y} ${z} ... ${x} ${y} ${z} ...

> ... "${q["quote"]} ${q["author"]} ...

...
""", quote=quote)
2 7 12 4 3 9

> "Some random quote Some name

py:with in functions >>> print render("""\ ...
... ... ... ...
      ...     ${func()}
      ...     ${xxx}
      ...
...
""")
False
py:attrs >>> print render("""\ ...

...
- Bar
...
- Bar
...

""", d=dict({'class': u'\u1234'}))

- Bar
- Bar

py:content, py:replace >>> print render("""\ ...
... ... ...
""")
Hello, world! Goodbye, world!
py:strip >>> print render("""\ ...
... foo ...
""")
foo
py:match >>> print render("""\ ...
... ... Hello, ${select('@name')[0]}! ... ... ... goodbye, ${select('@name')[0]}! ... ... and ... ... ...
""")
Hello, dude! and goodbye, dude!
:: Genshi variable interpolation (${
    } notation)

      >>> print render("""\
      ...
... inter${'pol' + 'ati'}onis ${'convenient'}! ... ${'a'}${'b'}${'c'} ${'d'} ... ... ... ${ltr.letter} ... ...
""", ltr={'letter': 'A', 'href': '?title=A', 'iscurrent': 'current'})
interpolationis convenient! abc d A
>>> print render("""\ ...
... ${'$'}{22*2-2} = ${22*2-2} ...
""")
${22*2-2} = 42
    :: Simple variable names do not need { .. }. From `py:with specs`_.

      >>> print render("""\
      ...
... $x $y $z ...
""", x=42)
42 7 52
:: Genshi variable interpolation and unicode values >>> print render("""\ ...
... ... ... ... ${unicode('La Pe\xc3\xb1a', 'utf-8').encode('utf-8')} ... ... ...
""", encoding='utf-8')
La Peña
:: Unicode combined with attribute expansion >>> print render("""\ ...
... ... ...
""", alt=unicode("La Pe\xc3\xb1a", 'utf-8'))
:: Variables containing quotes >>> print render("""\ ...
... "${quote}" ...
""", quote="Hello, World!")
"Hello, World!"
:: Variables containing markup >>> print render("""\ ...
... ${message} ...
""", message="Hello, World!")
Hello, <em>World</em>!
:: Unless we are in a CDATA block >>> print render("""\ ...
... /* */ ...
""", message="Hello, World!")
/* */
:: HTML comments >>> print render("""\ ...
... ... ... ...
""")
:: Chameleon used to forget to output the ]; after the for loop >>> print render("""\ ...
""")
    :: Strange looping behaviour

      >>> brands=[dict(id=1, title="One"),
      ...         dict(id=2, title="Two"),
      ...         dict(id=3, title="Three")]
      >>> print render("""\
      ...
...
...
""", brands=brands)
:: Very basic recursing >>> print render("""\ ...
...

... ${rendermenu([])} ...

...
""")
:: Slightly more complex recursive function calls >>> print render("""\ ...
...

...
- ... Merken ... ${rendermenu(entry.get('children', []))} ...
...

... ${rendermenu(menu)} ...
""", menu=[dict(title=u"Menu entry", url="/test", current=True)])

- Menu entry

:: You can use a loop variable with py:choose >>> print render("""\ ...
...
...
... ... Pending ... New ... ...
...
...
""")
New
Pending
:: Text is not interpolated unless necessary >>> print render("""\ ...
...
... ${form_errors['name']} ...
...
""")
:: By default all inserted data is escaped >>> print render("""\ ...
...
... Data ... Data ... ${data} ...
...
""", data="one & two")
one & two one & two one & two
If inserted data has a __html__ method it is called and the result is inserted without further escaping: >>> class Markup(unicode): ... def __html__(self): ... return self >>> print render("""\ ...
...
... Data ... Data ... ${data} ...
...
""", data=Markup("correct"))
correct correct correct
    If validation is enabled, markup inserted using ``__html__`` must
    validate

      >>> from chameleon.core import config
      >>> config.VALIDATION = True

      >>> print render("""\
      ...
...
... ${data} ...
...
""", data=Markup("incorrect")) Traceback (most recent call last): ... ValidationError: Insertion of u'incorrect' is not allowed. >>> config.VALIDATION = False .. _py:with specs: http://genshi.edgewall.org/wiki/Documentation/0.4.x/xml-templates.html#py-with