Create new eggs and packages quickly with paster

by Martin Aspeli last modified Feb 04, 2009 03:03 AM

How to use the paster command to create new packages with proper setuptools- and egg-compliant filesystem layout quickly and easily.

In Zope 2.10 (or Zope 2.9 if you use pythonproducts) you can create Zope two products that install in your $PYTHONPATH in nicely ordered packages, rather than in the flat namespace of the Products/ directory. Better yet, you can create packages that are not Zope 2 products at all, but which your other products can depend on.

Zope and Plone are steadily moving towards greater dependency on python "eggs", self-contained distributions of code and extensions which can manage dependencies automatically and contain useful metadata. To support this in your own code, however, you need to provide some boilerplate.

To make creating this boilerplate easier, you can use ZopeSkel, a set of PasteScript templates for the paster command that generate common Plone boilerplate.

Setting up

To install ZopeSkel, you first need to have easy_install on your system. If you don't, download and run ez_setup.py, e.g.:

  $ wget peak.telecommunity.com/dist/ez_setup.py
  $ python ez_setup.py

Then, to install the ZopeSkel egg and its dependencies (including PasteScript), run:

 $ easy_install -U ZopeSkel

This will install the paster command in the place your python binaries go. Keep an eye on the output of easy_install if you can't find it afterwards. If it's not in your $PATH, you may want to symlink it in there.

Creating new eggs

Now you will be able to create a variety of different types of packages. run:

  $ paster create --list-templates
  Available templates:  basic_namespace:   A project with a namespace package
   basic_package:     A basic setuptools-enabled package
   nested_namespace:  A project with two nested namespaces.
   paste_deploy:      A web application deployed through paste.deploy
   plone:             A Plone project
   plone2_theme:      A Theme for Plone 2.1 & Plone 2.5
   plone3_theme:      A Theme for Plone 3
   plone_app:         A Plone App project

To create a standard "single-level" Plone template, run:

 $ paster create -t plone

Answer its questions and you'll get a new directory with the necessary boilerplate and metadata. Similarly, for a "two-level" package like plone.app.something, (you don't have to use "plone" or "app" of course), you can do:

 $ paster create -t plone_app

Or, if you want a new theme, based on David Convent's DIYPloneStyle product, try:

 $ paster create -t plone3_theme

Adding eggs to an instance

You can use setup.py in the newly created package to install your package, create and upload eggs to the Cheeseshop etc. See the setuptools documentation for much more detail about this.

To learn more about this way of working, see the buildout tutorial.

Letting Zope find your packages

The magic Products/ directory is scanned by Zope on startup for products to register. This is not so with products and packages outside Products/ (scanning the entire $PYTHONPATH would probably not be a good idea in any case).

If you are just creating a plain python package that you wish to use from some other package or product, you don't need to do anything. It should be found at runtime.

If you need a product (i.e. you answered "Yes" when paster asked you "Is this a Zope 2 product?") or you need to load Zope 3 .zcml files at Zope startup, you can do one of the following:

  • Put a slug in $INSTANCE_HOME/etc/package-includes, with a name like my.package-configure.zcml. This file should contain a single line: <include package="my.package" />. This will cause Zope to find the package my.package in the $PYTHONPATH and run its configure.zcml.
  • Put an <include package="my.package" /> statement in a configure.zcml of any product found in Products/. Five ensures that all ZCML for all products in Products/ is run automatically, and thus, by being included, your package will be loaded as well.
  • Put an <include package"my.package" /> statement in etc/site.zcml, which is also read at startup.

For more details on how to manage this with zc.buildout, see the buildout tutorial.