Package: megrok.chameleon
megrok.chameleonmegrok.chameleonmakes it possible to use chameleon templates in Grok.Currently support for chameleon genshi templates and chameleon zope
page templates is provided.For more information on Grok and Chameleon templates see:http://grok.zope.org/http://chameleon.repoze.org/http://pypi.python.org/pypi/Chameleonhttp://pypi.python.org/pypi/chameleon.genshiContentsmegrok.chameleonRequirementsInstallationUsageDetailed DescriptionChameleon Zope page templatesPrerequisitesSimple templatesSubstituting variablesSupported variablesInline TemplatesTAL expressionsMacrosDifferences from regular Zope page templatesChameleon Genshi templatesPrerequisitesSimple templatesSubstituting variablesIncluding other templatesText templatesCHANGES0.5.2 (2010-07-19)0.5.1 (2010-05-20)0.5 (2010-03-03)0.4 (2010-02-23)0.3 (2010-02-14)0.2 (2009-09-18)0.1 (2009-02-22)RequirementsChameleon templates (Chameleon).Chameleon genshi templates (chameleon.genshi).Grok v1.0a1 or later, or five.grok 1.0 or later.InstallationTo use Chameleon page templates with Grok all you need is to install
megrok.chameleon as an egg and include its ZCML. The best place to do
this is to makemegrok.chameleona dependency of your application by
adding it to yourinstall_requireslist insetup.cfg. If you
used grokproject to create your applicationsetup.pyis located in the
project root. It should look something like this:install_requires=['setuptools',
                  'megrok.chameleon',
                  # Add extra requirements here
                  ],Then includemegrok.chameleonin yourconfigure.zcml. If you
used grokproject to create your application it’s atsrc/<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="megrok.chameleon" />
<grok:grok package="." />If you useautoIncludein yourconfigure.zcml, you should not
have to do this latter step.Then runbin/buildoutagain. You should now see buildout saying
something like:Getting distribution for 'megrok.chameleon'.
Got megrok.chameleon 0.5.That’s all. You can now start using Chameleon page templates in your
Grok application.Usagemegrok.chameleonsupports the Grok standard of placing templates
in a templates directory, for exampleapp_templates, so you can
use Chameleon page templates by simply placing the Chameleon genshi
templates or Chameleon Zope 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
extension and a type so it knows which type of template each template
is.megrok.chameleondefines the following extensions:.cpt(Chameleon page template) for Chameleon page templates.cg(Chameleon genshi template) for chameleon driven genshi
templates.cgt(Chameleon genshi text template) for chameleon driven
genshi text templatesYou can also use Chameleon page templates inline.  The syntax for this
is:from megrok.chameleon.components import ChameleonPageTemplate
index = ChameleonPageTemplate('<html>the html code</html>')Or if you use files:from megrok.genshi.components import ChameleonPageTemplateFile
index = ChameleonPageTemplateFile(filename='thefilename.html')Detailed DescriptionGrok-support for using chameleon driven templates.Withmegrok.chameleonyou can use templates parsed and rendered byChameleon. Currently Zope page templates and Genshi templates are
supported.Chameleon Zope page templatesChameleon 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 inPython-modeby default. This means,
instead oftal:content="view/value"you must usetal:content="view.value". Every occurence of TAL-expressions
starting withpython:now can be shortened by skipping this
marker.Also genshi-like variable substitutions are supported. For example
you can write${myvar}instead oftal:content="myvar".Beside this, most rules for regular Zope page templates apply also to
chameleon page templates.See theChameleonpage for more information.PrerequisitesBefore 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 themegrok.chameleonpackage. This way the new template types
are registered with the framework:>>> import grokcore.view
>>> grokcore.view.testing.grok('megrok.chameleon')
>>> grokcore.view.testing.grok('megrok.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 megrok.chameleon.tests.cpt_fixture.app import Mammoth
>>> manfred = Mammoth()
>>> getRootFolder()['manfred'] = manfredFurthermore we prepare for getting the different views on manfred:>>> from zope.publisher.browser import TestRequest
>>> from zope.component import getMultiAdapter
>>> request = TestRequest()Simple templatesWe 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 variablesA template can access variables likeview,contextand its
methods and attributes. Thefoodview 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: ${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: http://127.0.0.1/@@/megrok.chameleon.tests.cpt_fixture/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 variablesEach template provides at least the following vars:templatethe template instanceviewthe associated viewcontextthe context of the viewrequestthe current requeststaticthe static dir of the applicationas we can see, when we look at thevars.cptfrom 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}
<BLANKLINE>
  static (the static dir of the application):
   ${static}
</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;vars template in ...vars.cpt&gt;
<BLANKLINE>
  view (the associated view):
   &lt;megrok.chameleon.tests.cpt_fixture.app.Vars object at 0x...&gt;
<BLANKLINE>
  context (the context of the view):
   &lt;megrok.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
<BLANKLINE>
  static (the static dir of the application):
   &lt;grokcore.view.components.DirectoryResource object at 0x...&gt;
</body>
</html>Inline TemplatesWe can also define inline templates. In ourapp.pywe defined an
inline template like this:from megrok.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 expressionsStarting withmegrok.chameleon0.5 we deploy the all-in-oneChameleonpackage.What TAL/TALES expressions in templates are supported depends mainly
from the installed version ofChameleon, while we support some
additional, Zope-related TALES expressions.A list of all supported expressions and statements can be found at thechameleon.zpt documentation. The additional
TALES expressions provided bymegrok.chameleonare:existsTell whether a name exists in the templates’ namespace.notEvaluate the trailing expression to a boolean value and invert it.pathHandle the trailing expression as a path and not as a
Python expression.providerSupport for viewlet providers.Warningz3c.ptsupport has been dropped withmegrok.chameleon0.5.NoteStarting withmegrok.chameleon0.5 support for the
Python expressionexists()has been dropped. The TALES
expressionexists: path/to/somethingis still available.In ourapp.pywe defined a special view for showing some special
expressions. This also includes a viewlet:import grok
from megrok.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 expressionsnot:,path:,exists:andprovider:in theexpressions.cpttemplate 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>MacrosWithmegrok.chameleonwe 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 macrohellocan be rendered in another Chameleon
template with the METAL attributeuse-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 thepath: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 oncontextandmacro-nameagain 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 notationview/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 templatesMacros are referenced differently. See appropriate section above.Expressions are parsed inPython-modeby default. This means,
instead oftal:content="view/value"you must usetal:content="view.value". Every occurence of TAL-expressions
starting withpython:now can be shortened by skipping this
marker.Chameleon Genshi templatesChameleon provides support for Genshi templates which can be used from
grok writing templates with the.cgfilename extension.Genshi text templates can be used with the.cgtfilename
extension.Note, that chameleon genshi templates might not cover the full range
of functionality offered by native genshi parsers. Usemegrok.genshiif you want native genshi support.See thechameleon.genshipage for more information.PrerequisitesBefore 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')
>>> genshi_fixture = os.path.join(testdir, 'genshi_fixture')
>>> template_dir = os.path.join(genshi_fixture, 'app_templates')We register everything. Before we can grok our fixture, we have to
grok themegrok.chameleonpackage. This way the new template types
are registered with the framework:>>> grokcore.view.testing.grok('megrok.chameleon')
>>> grokcore.view.testing.grok('megrok.chameleon.tests.genshi_fixture')We create a mammoth, which should provide us a bunch of Genshi driven
views and put it in the database to setup location info:>>> from megrok.chameleon.tests.genshi_fixture.app import Mammoth
>>> manfred = Mammoth()
>>> getRootFolder()['manfred'] = manfredFurthermore we prepare for getting the different views on manfred:>>> from zope.publisher.browser import TestRequest
>>> from zope.component import getMultiAdapter
>>> request = TestRequest()Simple templatesWe prepared a plain cavepainting view. The template looks like this:>>> cavepainting_cg = os.path.join(template_dir, 'cavepainting.cg')
>>> print open(cavepainting_cg, '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 variablesA template can access variables likeview,contextand its
methods and attributes. Thefoodview does exactly this. The
template looks like this:>>> food_cg = os.path.join(template_dir, 'food.cg')
>>> print open(food_cg, 'rb').read()
<html>
<body>
${view.me_do()}
CSS-URL: ${static['test.css']()}
My context is: ${view.url(context)}
</body>
</html>The rendered view looks like this:>>> view = getMultiAdapter((manfred, request), name='food')
>>> print view()
<html>
<body>
ME GROK EAT MAMMOTH!
CSS-URL: http://127.0.0.1/@@/megrok.chameleon.tests.genshi_fixture/test.css
My context is: http://127.0.0.1/manfred
</body>
</html>Including other templatesWith genshi support we can also include other templates. Thegathererview looks like this:>>> gatherer_cg = os.path.join(template_dir, 'gatherer.cg')
>>> print open(gatherer_cg, 'rb').read()
<html xmlns:xi="http://www.w3.org/2001/XInclude">
<body>
ME GROK GATHER BERRIES!
<xi:include href="berries.cg"/>
</body>
</html>Apparently here we include a template calledberries.cg. It looks
like this:>>> berries_cg = os.path.join(template_dir, 'berries.cg')
>>> print open(berries_cg, 'rb').read()
<strong>Lovely blueberries!</strong>When we render the former template, we get:>>> view = getMultiAdapter((manfred, request), name='gatherer')
>>> print view()
<html>
<body>
ME GROK GATHER BERRIES!
<strong>Lovely blueberries!</strong>
</body>
</html>Text templatesAlso genshi text templates are supported. We have a template that
looks like so:>>> hunter_cgt = os.path.join(template_dir, 'hunter.cgt')
>>> print open(hunter_cgt, 'rb').read()
ME GROK HUNT ${view.game}!Note, that this template has the.cgt(=cameleongenshitext template) file extension.If we render it, all expressions are substituted:>>> view = getMultiAdapter((manfred, request), name='hunter')
>>> print view()
ME GROK HUNT MAMMOTH!!CHANGES0.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: ifz3c.ptis installed as well, we don’t register our own
ones. Should fix DuplicationError when using megrok.chameleon
together with other packages that require z3c.pt likez3c.formand 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 withmegrok.chameleon.Removed dependency fromz3c.ptby copying the relevant bits over
and registering them locally.Drop support forexists('varname')expressions. The regular
TALES expressionexists: varname/pathcan still be used.Switch to useChameleoninstead ofchameleon.*packages.0.4 (2010-02-23)Declaredmegrokas 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 forpath()andexists()in page templates. This
was introduced fromz3c.pt.Fix ZCML includes.0.1 (2009-02-22)Initial release