Metadata-Version: 1.0
Name: grokcore.chameleon
Version: 1.0
Summary: Chameleon page template support for Grok
Home-page: http://pypi.python.org/pypi/grokcore.chameleon
Author: Uli Fouquet
Author-email: grok-dev@zope.org
License: ZPL
Description: ==================
        grokcore.chameleon
        ==================
        
        `grokcore.chameleon` makes it possible to use Chameleon page templates in Grok.
        For more information on Grok and Chameleon page templates see:
        
        - http://pagetemplates.org/
        - http://pagetemplates.org/docs/latest/
        - http://pypi.python.org/pypi/Chameleon
        - http://grok.zope.org/
        
        .. contents::
        
        Installation
        ============
        
        Note that future versions of grok will depend itself on grokcore.chameleon
        and configure it. In other words, chameleon-based templates will be available
        by default from that version on!
        
        To use Chameleon page templates with Grok all you need is to install
        grokcore.chameleon as an egg and include its ZCML. The best place to do
        this is to make `grokcore.chameleon` a dependency of your application by
        adding it to your ``install_requires`` list in ``setup.cfg``. If you
        used grokproject to create your application ``setup.py`` is located in the
        project root. It should look something like this::
        
           install_requires=['setuptools',
                             'grokcore.chameleon',
                             # Add extra requirements here
                             ],
        
        Note that if you use the ``allow-picked-versions = false`` directive in your
        project's ``buildout.cfg``, you will have to add version number specifications
        for several packages to your ``[versions]`` section.
        
        Then include ``grokcore.chameleon`` in your ``configure.zcml``. If you used
        grokproject to create your application it's at
        ``src/<projectname>/configure.zcml``. Add the include line after the include
        line for grok, but before the grokking of the current package. It should look
        something like this::
        
              <include package="grok" />
              <include package="grokcore.chameleon" />
              <grok:grok package="." />
        
        If you use ``autoInclude`` in your ``configure.zcml``, you should not
        have to do this latter step.
        
        Then run ``bin/buildout`` again. You should now see buildout saying
        something like (where version numbers can vary)::
        
           Getting distribution for 'grokcore.chameleon'.
           Got grokcore.chameleon 0.5.
        
        That's all. You can now start using Chameleon page templates in your
        Grok application.
        
        Usage
        =====
        
        ``grokcore.chameleon`` supports the Grok standard of placing templates in a
        templates directory, for example ``app_templates``, so you can use Chameleon
        page templates by simply placing the Chameleon page templates in the templates
        directory, just as you would with regular ZPT templates.
        
        Although chameleon templates themselves do not have a standard for the file
        extensions for templates, Grok needs to have an association between an filename
        extension and a template language implementation so it knows which
        implementation to use.
        
        `grokcore.chameleon` declares to use the extension ``*.cpt`` (``Chameleon page
        template``) for Chameleon page templates.
        
        You can also use Chameleon page templates inline. The syntax for this
        is::
        
           from grokcore.chameleon.components import ChameleonPageTemplate
           index = ChameleonPageTemplate('<html>the html code</html>')
        
        Or if you use files::
        
           from grokcore.chameleon.components import ChameleonPageTemplateFile
           index = ChameleonPageTemplateFile(filename='thefilename.html')
        
        
        ====================
        Detailed Description
        ====================
        
        Grok-support for using chameleon driven templates.
        
        With `grokcore.chameleon` you can use templates parsed and rendered by
        `Chameleon`_ using the Zope Page Template templating language.
        
        Chameleon Zope page templates
        =============================
        
        Chameleon provides support for Zope page templates which can be used
        from grok writing templates with the ``.cpt`` (=Chameleon Page
        Template) filename extension.
        
        Chameleon page templates differ from standard Zope page templates in a
        few aspects, most notably:
        
        * Expressions are parsed in ``Python-mode`` by default. This means,
          instead of ``tal:content="view/value"`` you must use
          ``tal:content="view.value"``. Every occurence of TAL-expressions
          starting with ``python:`` now can be shortened by skipping this
          marker.
        
        * Also Genshi-like variable substitutions are supported. For example
          you can write ``${myvar}`` instead of ``tal:content="myvar"``.
        
        Beside this, most rules for regular Zope page templates apply also to
        chameleon page templates.
        
        See the `Chameleon`_ page for more information.
        
        .. _Chameleon: http://chameleon.repoze.org/docs/latest/zpt.html
        
        Prerequisites
        =============
        
        Before we can see the templates in action, we care for correct
        registration and set some used variables:
        
            >>> import os
            >>> testdir = os.path.join(os.path.dirname(__file__), 'tests')
            >>> cpt_fixture = os.path.join(testdir, 'cpt_fixture')
            >>> template_dir = os.path.join(cpt_fixture, 'app_templates')
        
        We register everything. Before we can grok our fixture, we have to
        grok the `grokcore.chameleon` package. This way the new template types
        are registered with the framework:
        
            >>> import grokcore.view
            >>> grokcore.view.testing.grok('grokcore.chameleon')
            >>> grokcore.view.testing.grok('grokcore.chameleon.tests.cpt_fixture')
        
        We create a mammoth, which should provide us a bunch of chameleon page
        template driven views and put it in the database to setup location
        info::
        
            >>> from grokcore.chameleon.tests.cpt_fixture.app import Mammoth
            >>> manfred = Mammoth()
            >>> getRootFolder()['manfred'] = manfred
        
        Furthermore we prepare for getting the different views on manfred:
        
            >>> from zope.publisher.browser import TestRequest
            >>> from zope.component import getMultiAdapter
            >>> request = TestRequest()
        
        Simple templates
        ================
        
        We prepared a plain cavepainting view. The template looks like this:
        
            >>> cavepainting_cpt = os.path.join(template_dir, 'cavepainting.cpt')
            >>> print open(cavepainting_cpt, 'rb').read()
            <html>
              <body>
                A cave painting.
              </body>
            </html>
        
        The rendered view looks like this:
        
            >>> view = getMultiAdapter((manfred, request),
            ...                         name='cavepainting')
            >>> print view()
            <html>
              <body>
                A cave painting.
              </body>
            </html>
        
        Substituting variables
        ======================
        
        A template can access variables like ``view``, ``context``, ``static``
        and its methods and attributes. The ``food`` view does exactly
        this. The template looks like this:
        
            >>> food_cpt = os.path.join(template_dir, 'food.cpt')
            >>> print open(food_cpt, 'rb').read()
            <html>
            <body>
            <span tal:define="foo 'a FOO'">
            ${view.me_do()}
            <span tal:replace="structure view.me_do()" />
            CSS-URL: ${path:static/test.css}
            My context is: ${view.url(context)}
            ${foo}
            <span tal:replace="foo" />
            </span>
            </body>
            </html>
        
        The rendered view looks like this:
        
            >>> view = getMultiAdapter((manfred, request), name='food')
            >>> print view()
            <html>
            <body>
            <span>
            &lt;ME GROK EAT MAMMOTH!&gt;
            <ME GROK EAT MAMMOTH!>
            CSS-URL: dummy:/test.css
            My context is: http://127.0.0.1/manfred
            a FOO
            a FOO
            </span>
            </body>
            </html>
        
        As we can see, there is a difference between Genshi-like substitution
        and TAL-like substitution: while both expressions::
        
          ${view.me_do()}
        
        and::
        
          <span tal:replace="view.me_do()" />
        
        actually render the same string ``<ME GROK EAT MAMMOTH!>``, the former
        does this straight and plain, while the latter performs additionally
        HTML-encoding of the string. Therefore the output of both expressions
        differ. It's::
        
          <ME GROK EAT MAMMOTH!>
        
        for the former expression and::
        
          &lt;ME GROK EAT MAMMOTH!&gt;
        
        for the latter.
        
        
        Supported variables
        ===================
        
        Each template provides at least the following vars:
        
        * ``template``
            the template instance
        
        * ``view``
            the associated view
        
        * ``context``
            the context of the view
        
        * ``request``
            the current request
        
        as we can see, when we look at the ``vars.cpt`` from our fixture:
        
            >>> cpt_file = os.path.join(template_dir, 'vars.cpt')
            >>> print open(cpt_file, 'rb').read()
            <html>
            <body>
            This template knows about the following vars:
            <BLANKLINE>
              template (the template instance):
               ${template}
            <BLANKLINE>
              view (the associated view):
               ${view}
            <BLANKLINE>
              context (the context of the view):
               ${context}
            <BLANKLINE>
              request (the current request):
               ${request}
            </body>
            </html>
        
        and render it:
        
            >>> view = getMultiAdapter((manfred, request), name='vars')
            >>> print view()
            <html>
            <body>
            This template knows about the following vars:
            <BLANKLINE>
              template (the template instance):
               &lt;PageTemplateFile ...vars.cpt&gt;
            <BLANKLINE>
              view (the associated view):
               &lt;grokcore.chameleon.tests.cpt_fixture.app.Vars object at 0x...&gt;
            <BLANKLINE>
              context (the context of the view):
               &lt;grokcore.chameleon.tests.cpt_fixture.app.Mammoth object at 0x...&gt;
            <BLANKLINE>
              request (the current request):
               CONTENT_LENGTH:	0
            GATEWAY_INTERFACE:	TestFooInterface/1.0
            HTTP_HOST:	127.0.0.1
            SERVER_URL:	http://127.0.0.1
            </body>
            </html>
        
        Custom template namespace names are supported:
        
            >>> view = getMultiAdapter((manfred, request), name='namespace')
            >>> print view()
            <html>
            <body>
            This template knows about the following custom namespace name:
            <BLANKLINE>
              myname:
               Henk
            <BLANKLINE>
            </body>
            </html>
        
        Inline Templates
        ================
        
        We can also define inline templates. In our ``app.py`` we defined an
        inline template like this::
        
          from grokcore.chameleon import components
        
          ...
        
          class Inline(grokcore.view.View):
            sometext = 'Some Text'
        
          inline = components.ChameleonPageTemplate(
              "<html><body>ME GROK HAS INLINES! ${view.sometext}</body></html>")
        
        If we render this view we get:
        
            >>> view = getMultiAdapter((manfred, request), name='inline')
            >>> print view()
            <html><body>ME GROK HAS INLINES! Some Text</body></html>
        
        TAL expressions
        ===============
        
        Starting with ``grokcore.chameleon`` 0.5 we deploy the all-in-one
        `Chameleon`_ package.
        
        What TAL/TALES expressions in templates are supported depends mainly
        from the installed version of `Chameleon`, while we support some
        additional, Zope-related TALES expressions.
        
        A list of all supported expressions and statements can be found at the
        `chameleon.zpt documentation
        <http://chameleon.repoze.org/docs/latest/zpt.html>`_. The additional
        TALES expressions provided by ``grokcore.chameleon`` are:
        
        * ``exists``
             Tell whether a name exists in the templates' namespace.
        
        * ``not``
             Evaluate the expression to a boolean value and invert it.
        
        * ``path``
             Handle the expression as a path and not as a Python expression.
        
        * ``provider``
             Support for viewlet providers.
        
        .. note:: Starting with ``grokcore.chameleon`` 0.5 support for the
                  Python expression ``exists()`` has been dropped. The TALES
                  expression ``exists: path/to/something`` is still available.
        
        In our ``app.py`` we defined a special view for showing some special
        expressions. This also includes a viewlet::
        
           import grok
           from grokcore.chameleon import components
        
           class Mammoth(grok.Application, grok.Container):
               pass
        
           ...
        
           class Expressions(grok.View):
               pass
        
           class MainArea(grok.ViewletManager):
               grok.name('main')
        
           class MainContent(grok.Viewlet):
               grok.view(Expressions)
               grok.viewletmanager(MainArea)
               def render(self):
                   return 'Hello from viewlet'
        
        Now we can make use of the TALES expressions ``not:``, ``path:``,
        ``exists:`` and ``provider:`` in the ``expressions.cpt`` template of
        our fixture:
        
            >>> cpt_file = os.path.join(template_dir, 'expressions.cpt')
            >>> print open(cpt_file, 'rb').read()
            <html>
            <body>
              <div tal:define="food 'Yummy Dinoburger'"
                   tal:omit-tag="">
                <!-- We support `exists` -->
                <div tal:condition="exists: food">
                  ${food}
                </div>
            <BLANKLINE>
                <!-- We support `not` -->
                <div tal:content="not: food" />
                <div tal:content="not('food')" />
                <div tal:content="not: 1 in [2,3]" />
                <div tal:content="not: not: food" />
            <BLANKLINE>
                <!-- We support `path` -->
                <div tal:content="path: food/upper" />
            <BLANKLINE>
                <!-- We support `provider` -->
                <tal:main content="structure provider:main" />
            <BLANKLINE>
              </div>
            </body>
            </html>
        
        and render it:
        
            >>> view = getMultiAdapter((manfred, request), name='expressions')
            >>> print view()
            <html>
            <body>
            <BLANKLINE>
                <!-- We support `exists` -->
                <div>
                  Yummy Dinoburger
                </div>
            <BLANKLINE>
                <!-- We support `not` -->
                <div>False</div>
                <div>False</div>
                <div>True</div>
                <div>True</div>
            <BLANKLINE>
                <!-- We support `path` -->
                <div>YUMMY DINOBURGER</div>
            <BLANKLINE>
                <!-- We support `provider` -->
                Hello from viewlet
            <BLANKLINE>
            <BLANKLINE>
            </body>
            </html>
        
        Translation
        ===========
        
            >>> # Monkeypatch zope.i18n.negotiate
            >>> import zope.i18n
            >>> import zope.i18n.config
            >>> print getMultiAdapter((manfred, request), name='menu')()
            <html>
            <body>
              <h1>Menu</h1>
              <ol>
                <li>Deepfried breaded veal cutlets</li>
              </ol>
            </body>
            </html>
        
            >>> # What's for food today in Germany?
            >>> # We need to monkey patch the language settings for this test.
            >>> old_1, old_2 = zope.i18n.negotiate, zope.i18n.config.ALLOWED_LANGUAGES
            >>> zope.i18n.negotiate = lambda context: 'de'
            >>> zope.i18n.config.ALLOWED_LANGUAGES = ['de']
            >>> print getMultiAdapter((manfred, request), name='menu')()
            <html>
            <body>
              <h1>Menu</h1>
              <ol>
                <li>Schnitzel</li>
              </ol>
            </body>
            </html>
        
            >>> # Restore the monkey patch.
            >>> zope.i18n.negotiate, zope.i18n.config.ALLOWED_LANGUAGES = old_1, old_2
        
        Macros
        ======
        
        With ``grokcore.chameleon`` we can also use macros, although it is a bit
        different from regular Zope page templates.
        
        We can define macros like this:
        
            >>> cpt_file = os.path.join(template_dir, 'macromaster.cpt')
            >>> print open(cpt_file, 'rb').read()
            <p xmlns:metal="http://xml.zope.org/namespaces/metal"
               metal:define-macro="hello">
              Hello from <b metal:define-slot="name">macro master</b>
            </p>
        
        The defined macro ``hello`` can be rendered in another Chameleon
        template with the METAL attribute ``use-macro``.
        
        To refer to a local macro, i.e. a macros defined in the same template,
        you can use something like::
        
          <div metal:use-macro="template.macros['<macro-name>']">
            Replaced by macro
          </div>
        
        where ``<macro-name>`` must be an existing macro name.
        
        To refer to macros in external templates, you must use the ``path:`` expression
        like this::
        
          <div metal:use-macro="path:
            context/@@<viewname>/template/macros/<macro-name>">
             Replaced by external macro
          </div>
        
        where ``<viewname>`` refers to an existing view on ``context`` and ``macro-
        name`` again refers to an existing macro in the specified template.
        
        Note, that this is different from how you refer to macros in standard Zope page
        templates. The short notation ``view/macros/<macro-name>`` works only with
        regular Zope page templates.
        
        The following template makes use of both methods:
        
            >>> cpt_file = os.path.join(template_dir, 'macrouser.cpt')
            >>> print open(cpt_file, 'rb').read()
            <html xmlns:metal="http://xml.zope.org/namespaces/metal">
            <body>
              <p metal:define-macro="hello">
                Hi there from macro user!
              </p>
              <div metal:use-macro="template.macros['hello']">
                Fill this
              </div>
            <BLANKLINE>
              <div metal:use-macro="path: context/@@macromaster/template/macros/hello">
                <b metal:fill-slot="name">user slot</b>
                Fill this too
              </div>
            </body>
            </html>
        
        When rendered also the slot defined in the master template is filled by macro
        user content:
        
            >>> cpt_file = os.path.join(template_dir, 'macrouser.cpt')
            >>> view = getMultiAdapter((manfred, request), name='macrouser')
            >>> print view()
            <html>
            <body>
              <p>
                Hi there from macro user!
              </p>
              <p>
                Hi there from macro user!
              </p>
            <BLANKLINE>
            <BLANKLINE>
              <p>
              Hello from <b>user slot</b>
            <BLANKLINE>
            </p>
            </body>
            </html>
        
        
        Clean up:
        
            >>> del getRootFolder()['manfred']
        
        Differences from regular Zope page templates
        ============================================
        
        * Macros are referenced differently. See appropriate section above.
        
        * Expressions are parsed in ``Python-mode`` by default. This means, instead
          of ``tal:content="view/value"`` you must use ``tal:content="view.value"``.
          Every occurence of TAL-expressions starting with ``python:`` now can be
          shortened by skipping this marker.
        
        
        CHANGES
        *******
        
        1.0 (2012-05-01)
        ================
        
        - The ``target_language`` mangling was lost in version 1.0rc4. Copied from z3c.pt.
        
        1.0rc4 (2012-01-03)
        ===================
        
        - Update to newes Chameleon 2.7.1
        - Using some Components/Expressions directly from Chameleon instead of z3c.pt
        
        
        1.0rc3 (2011-07-14)
        ===================
        
        - Rename megrok.chameleon into grokcore.chameleon to make it an official part
          of Grok.
        
        1.0rc2 (2011-07-13)
        ===================
        
        * Removed the zope.app.zcmlfiles test dependency.
        
        1.0rc1 (2011-05-19)
        ===================
        
        * Depend on the Chameleon 2.0 line.
        
        * Depend on z3c.pt again, as it contains necessary components for the types
          of expressions we expect to be able to use in page templates in a Zope/Grok
          context. The maintainer for z3c.pt is the same as for Chameleon itself.
        
        * Removal of the Genshi-template components, as they are not available in the
          Chameleon-2.0 line anymore.
        
        * Grok's view namespaces are injected as "top-level" template namespaces
          instead of part of the `options` namespace.
        
        0.5.2 (2010-07-19)
        ==================
        
        * Remove dependency on chameleon.genshi as this is now included
          into Chameleon itself.
        
        0.5.1 (2010-05-20)
        ==================
        
        * Made registering of ITranslatorExpressions conditional: if
          ``z3c.pt`` is installed as well, we don't register our own
          ones. Should fix DuplicationError when using grokcore.chameleon
          together with other packages that require z3c.pt like ``z3c.form``
          and dependent packages from grok-ecosphere.
        
        * Get rid of zope.testing, zope.app.testing and z3c.testsetup for
          tests.
        
        0.5 (2010-03-03)
        ================
        
        * Added tests to show usage of macros with ``grokcore.chameleon``.
        
        * Removed dependency from ``z3c.pt`` by copying the relevant bits over
          and registering them locally.
        
          Drop support for ``exists('varname')`` expressions. The regular
          TALES expression ``exists: varname/path`` can still be used.
        
        * Switch to use ``Chameleon`` instead of ``chameleon.*`` packages.
        
        0.4 (2010-02-23)
        ================
        
        * Declared ``megrok`` as namespace package.
        
        * Fixed order of includes in ftesting.zcml.
        
        * Moved pure test-requirements into own setup-section in order to reduce
          dependencies in regular (non-testing) mode.
        
        0.3 (2010-02-14)
        ================
        
        * Added license file.
        
        0.2 (2009-09-18)
        ================
        
        * Provide macro access from templates.
        
        * Don't depend anymore on grok, but only grokcore.view.
        
        * Added support for `path()` and `exists()` in page templates. This
          was introduced from `z3c.pt`.
        
        * Fix ZCML includes.
        
        0.1 (2009-02-22)
        ================
        
        * Initial release
        
Keywords: grok chameleon template
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Zope Public License
Classifier: Programming Language :: Python :: 2.5
Classifier: Operating System :: OS Independent
Classifier: Topic :: Internet :: WWW/HTTP
