    Zope Page Templates (ZPT)
    =========================

    This test demonstrates the compilation of TAL and METAL attribute
    languages.

      >>> from chameleon.zpt.language import Parser
      >>> from chameleon.core.testing import compile_template

      >>> def render(body, **kwargs):
      ...     parser = Parser()
      ...     func = compile_template(parser, parser, body, **kwargs)
      ...     return func(**kwargs)

    TAL
    ---

    :: Namespace elements

      >>> print render("""\
      ...
... Hello, world! ... """) Hello, world! tal:define, tal:attributes, tal:content, tal:replace >>> print render("""\ ...
... ... ... ... ... ...
""")
abc def
>>> print render("""\ ...
... ... Hello Universe! ... Hello Universe! ...
""")
abcghi Hello World! Hello World!
tal:attributes default >>> print render("""\ ...
... 0 ... 2 ... 3 ... 4 ... 5 ...
""")
1 2 3 4 5
tal:attributes 'checked' and 'selected' toggles >>> print render("""\ ...
... ... ... ... ...
""")
tal:attributes keeps original attributes ordering >>> print render("""\ ...
... ...
""")
tal:attributes on a TAL-namespace element fails >>> print render("""\ ...
      ... """)
      Traceback (most recent call last):
       ...
      TypeError: Dynamic attributes not allowed on elements with TAL-namespace.

    tal:repeat

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

...
...

...
""")

- Item 0)
- Item 1)
- Item 2)
- Item 3)
- Item 4)

tal:repeat using builtin name as repeat var >>> print render("""\ ...
...

...
...

...
""")

- 0
- 1

    tal:repeat (tuples)

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

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

""")

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

    tal:repeat (repeat-variable)

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

...
...

...

...
...

...

...
...

...
""")

- 0
- 1
- 2

- 0
- 1
- 2

- even
- odd
- even

    tal:repeat (nested, with same variable)

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

...
- ...
... ...

... ...
""")

- 0
- 0
- 1

5
    tal:repeat (omited tag doesn't generate too many blank lines)

      >>> print render("""\
      ...
... ... ... , ... ... . ...
""")
1, 2, 3, 4, 5, 6, 7, 8, 9.
tal:condition >>> print render("""\ ...
...
... Show me! ...
...
... Do not show me! ...
...
... Do not show me! ...
... ...
""")
Show me!
:: TAL elements with namespace prefix >>> print render("""\ ...
... ... ... ... ... True ...
""")
Hello World! Hello World! Hello World! 0 1 2 True
tal:omit-tag >>> print render("""\ ...
...

No paragraph here.

...

No paragraph here either.

...

A paragraph here.

...
""")
No paragraph here. No paragraph here either.

A paragraph here.

:: Whitespace >>> print render("""\ ...
... one - two ... one - two ... - one - two ... one - two - three ... one - two - three ... one two ...
""")
one - two one - two - one - two one - two - three one - two - three one two
:: Unicode with dynamic attributes and content >>> print render("""\ ...
... ... ... ... ...
""")
<br /> La Peña
:: Using the "string:" expression >>> print render("""\ ...
... ... ...
""", request=object(), greeting=u'Hello')
Hello, world!
:: Using the "import:" expression >>> print render("""\ ...
... ...
""")
<InterfaceClass chameleon.zpt.interfaces.IExpressionTranslator>
    :: Using different expressions with try-except operator (|)

      >>> print render("""\
      ...
... ... ...
""")
1 2
:: Using the "structure" TAL pragma. >>> print render("""\ ...
... ...
""")
Using 'default' means whatever the the literal HTML contains will be output if the condition is not met. Printing default attribute value: >>> print render("""\ ...
... i'm blue ...
""")
i'm blue
Print default tag contents: >>> print render("""\ ...
... default content ...
""")
default content
Use default with 'tal:define': >>> print render("""\ ...
... i'm blue ...
""")
i'm blue
METAL ----- metal:define-macro, metal:use-macro >>> body = """\ ...
...
... Hello, ! ...
...
...
... Hello, ! ...
...
    """

      >>> from chameleon.core.testing import MockTemplate
      >>> from chameleon.zpt.language import Parser

      >>> template = MockTemplate(body, Parser())
      >>> print render(body, template=template)
Hello, earth!
Hello, world!
Hello, earth!
metal:define-slot, metal:fill-slot >>> body = """\ ...
...
... Hey, ... a stranger! ...
...
... This will be omitted ... earth! ...
...
... This will be omitted ... ...
...
... ...
...
...
... earth! ...
...
...
... ...
...
... dummy! ...
...
    """

      >>> template = MockTemplate(body, Parser())
      >>> print render(body, template=template)
Hey, a stranger!
Hey, earth!
Hey,
Hey,
Hey, earth!
Hey, a stranger!
Hey, a stranger!
List Comprehension ------------------ An issue was observed where list comprehension notation resulted in a NameError unless the iterator was already defined. >>> print render("""\ ...
... ... ... ...
""")
0-1-2-3-4-5 0-1-2-3-4-5 0-1-2-3-4-5
Expression interpolation ------------------------ The ``chameleon.zpt`` parser supports Genshi interpolation expressions. Outside tags: >>> print render("""\ ...
... Interpolation ${'expressions'} are ${'convenient'}. ...
""")
Interpolation expressions are convenient.
Inside tags: >>> print render("""\ ...
... ...
""")
Spaces: >>> print render("""\ ...
... ${x},${y} ${x},${y} ...
""", x='x', y='y')
x,y x,y
Inside foreign-namespace tags: >>> print render("""\ ...
... ...
""")
We can disable this feature using ``meta:interpolation``:: >>> print render("""\ ...
...
... ${'foo'} ... ...
...
""")
${'foo'}
The ``tail`` of an element does get intepolated depending oon it's parent:: >>> print render("""\ ...
...
... ${nope} ...
... ${'interpolation'} ...
... ${'interpolation'} ... ... ${nope} ... ... ${'interpolation'} ... ... ${'nope'} ... ...
...
""")
${nope}
interpolation
interpolation ${nope} interpolation ${'nope'}
Escaping inserted data ---------------------- By default all inserted data is escaped. Content that's already encoded using numeric character representation should be left alone:: >>> print render("""\ ...
... ${welcome} ...
""", welcome="“Karibuni”".decode('utf-8'))
“Karibuni”
>>> print render("""\ ...
...
... Data ... Data ... ${data} ... “three” — can’t… ... ... Data ... Data ... ${another} ...
...
""", data="one & two", another='a "quote" b')
one & two one & two one & two “three” — can’t… “three” — can’t… a "quote" b a "quote" b a "quote" b
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