Description
How to create Paster code skeleton templates to easily add your own add-on product types or code inside your add-on porduct.
Plone CMS and Python extensively use paster code templating system to aid add-on product development.
Paster allows you to create code from code skeleton templates, automatically filling in your company name etc.
Default Plone templates are in ZopeSkel package.
More information
First you need to create a Python egg where your templates will be contained. We use ZopeSkel's plone template, but generic Python template should do as well.
paster create -t plone gomobile.templates
Note
You do not need tests.py or configure.zcml files in the template package itself.
Then we edit setup.py and add paster template entry points:
install_requires=[
'setuptools',
'PasteScript',
'ZopeSkel',
# -*- Extra requirements: -*-
],
entry_points="""
# These will declare what templates paster create command can find
# -*- Entry points: -*-
[paste.paster_create_template]
dexterity = gomobile.templates.theme:Theme
""",
You could also have "subtemplates" with local paster commands which add more code into existing code skeletons:
[zopeskel.zopeskel_sub_template]
dexterity_content = collective.dexteritypaste.localcommands.dexterity:DexterityContent
dexterity_behavior = collective.dexteritypaste.localcommands.dexterity:DexterityBehavior
dexterity_view = collective.dexteritypaste.localcommands.dexterity:DexterityView
Entrypoints allow different plug-in systems through using the standard Python eggs and setup.py file. Plone 3.3+ picks Plone add-ons through this way and paster command pick available templates from all available eggs this way.
More information
Paster template is defined with a class referred from the entry point. Here is an example how we extend the existing Plone template class
ZopeSkel contains facilities how to ask template input from the user who is running Paster. It provides some sane way to give defaults and validate the input.
Examples
Note
ZopeSkel input definitions should work both on command line and on the web based generator.
If you want to run special code before the templates are run and after they have succesfully complete, ZopeSkel provides some logic for this.
More information
All templates should go to templates folder in your ZopeSkel extension namespace.
Filenames and folder names can contain variable substitues as:
templates/yourtemplatename/+namespace_package+/
will be mapped to:
yourcompany.package/yourcompany/
Files having special _tmpl extension will have string substitution performed on then. Paster supports Cheetah templates (default) and Python string templates
Example:
The best way to get the initial template files and folders for your add-on template is to checkout some existing ZopeSkel package, like collective.dexteritypaste and export its templates folder to your own add-on template.
Note
As writing of this I am not aware of any meta-template to create paster templates. But should thing would be greatly beneficial.
Simple string variable substitution is like:
from ${dotted_name} import ${portlet_filename}
from ${dotted_name}.tests.base_${portlet_filename} import TestCase
More information
Defaulte template variables are inherited from various base classes of ZopeSkel templates. One good place to look them is basic_namespace.py template declaration.
Useful snippets:
${namespace_package}.${package}
More information
You can also prepare template variables in Python code in your Paster template class's pre() method:
class Portlet(PloneSubTemplate):
"""
A plone 3 portlet skeleton
"""
_template_dir = 'templates/plone/portlet'
summary = "A Plone 3 portlet"
vars = [
var('portlet_name', 'Portlet name (human readable)', default="Example portlet"),
var('portlet_type_name', 'Portlet type name (should not contain spaces)', default="ExamplePortlet"),
var('description', 'Portlet description', default=""),
]
def pre(self, command, output_dir, vars):
"""
you can use package_namespace, package_namespace2, package
and package_dotted_name of the parent package here. you get them
for free in the vars argument
"""
vars['portlet_filename'] = vars['portlet_type_name'].lower()
More information
If you have any page template (*.pt) files you need to templatetize you will encounter problem that both Cheetah and Zope Page Templates use the similiar string expansion syntax causing a conflict.
You can use (backslash) before dollar sign to escape it.
Example:
<script tal:attributes="src string:\${viewlet/portal_url}/++resource++${namespace_package}.${package}/theme.js" type="text/javascript"></script>
If you need to have if, for and buddies in the templates see Cheetah manual.
Example
Local commands define insert snippets which will be injected to the existing files.
The marker for snippet injects is:
-*- extra stuff goes here -*-
You need to put it to the comment format of the file type. Example for XML would be (configure.zcml_tmpl):
<!-- -*- extra stuff goes here -*- -->
Local command injection templates have _insert in their filename extension. Then the local command injection snippet configure.zcml_insert look like:
<plone:behavior
title="${behavior_name}"
description="${behavior_description}"
provides="${behavior_short_dottedinterface}"
factory="${behavior_short_dottedadapter}"
for="plone.dexterity.interfaces.IDexterityContent"
/>
More information
Some examples
ZopeSkel provides some doctest based testing facilities to hook your templates to automatic testing facilities, mainly for the regression testing.
Examples
The preferred method to run paster with Plone is to have it automatically pulled in and configured for you by buildout.
You need to specially mention to buildout which Python eggs are in source code form.
Then you need to declare [paster] part and section in buildout.cfg:
parts =
...
paster
develop-eggs =
src/yourcompany.templates
[paster]
recipe = zc.recipe.egg
# Include your own template egg here.
# Note that ${instance} section name should be the section name
# for plone.recipe.zope2instance from your buildout.cfg
eggs =
PasteScript
ZopeSkel
yourcompany.templates
${instance:eggs}
Rerun buildout.
Now when you run paster command it should show your custom template:
bin/paster create --list-templates
...
Available templates:
archetype: A Plone project that uses Archetypes content types
basic_namespace: A basic Python project with a namespace package
basic_package: A basic setuptools-enabled package
basic_zope: A Zope project
gomobile_theme: A theme for Go Mobile for Plone <---- you should see yours somewhere here
kss_plugin: A project for a KSS plugin
This checks that your template generates viable code. We use package called gomobiletheme.yourcompany in this examples.
Steps
Generate a product skeleton using paster in non-interactive mode
rm -rf src/gomobiletheme.yourcompany ; bin/paster create --no-interactive -v -f -o src -t gomobile_theme gomobiletheme.yourcompany
Note
Use -f switch or you might encounter problems with template inheritance.
See paster bug regarding template inheritance and -f switch.
Put the newly created add-on skeleton to buildout.cfg in develop eggs and eggs:
eggs =
gomobiletheme.yourcompany
develop-eggs =
src/gomobiletheme.yourcompany
Run buildout
bin/buildout
Run testrunner for the created add-on
bin/test -s gomobiletheme.yourcompany
See bin/paste create --help for other useful debug switches.
The source code of this file is hosted on GitHub. Everyone can update and fix errors in this document with few clicks - no downloads needed.
For basic information about updating this manual and Sphinx format please see Writing and updating the manual guide.