Writing your own recipes
Writing recipes
The recipe API
install
__init__
handoutThe initializer is responsible for computing a part's options. After the initializer call, the options directory must reflect the full configuration of the part. In particular, if a recipe reads any data from other sections, it must be reflected in the options. The options data after the initializer is called is used to determine if a configuration has changed when deciding if a part has to be reinstalled. When a part is reinstalled, it is uninstalled and then installed.
install
handoutThe install method installs the part. It is used when a part is added to a buildout, or when a part is reinstalled.
The install recipe must return a sequence of paths that that should be removed when the part is uninstalled. Most recipes just create files or directories and removing these is sufficient for uninstalling the part.
update
handoutThe update method is used when a part is already installed and it's configuration hasn't changed from previous buildouts. It can return None or a sequence of paths. If paths are returned, they are added to the set of installed paths.
uninstall
handoutMost recipes simply create files or directories and the built-in buildout uninstall support is sufficient. If a recipe does more than simply create files, then an uninstall recipe will likely be needed.
Install Recipes
mkdirrecipe.py:
import logging, os, zc.buildout
class Mkdir:
def __init__(self, buildout, name, options):
self.name, self.options = name, options
options['path'] = os.path.join(
buildout['buildout']['directory'],
options['path'],
)
if not os.path.isdir(os.path.dirname(options['path'])):
logging.getLogger(self.name).error(
'Cannot create %s. %s is not a directory.',
options['path'], os.path.dirname(options['path']))
raise zc.buildout.UserError('Invalid Path')
- The path option in our recipe is interpreted relative to the buildout. We reflect this by saving the adjusted path in the options.
- If there is a user error, we:
- Log error details using the Python logger module.
- Raise a zc.buildout.UserError exception.
mkdirrecipe.py continued
def install(self): path = self.options['path'] logging.getLogger(self.name).info( 'Creating directory %s', os.path.basename(path)) os.mkdir(path) return path def update(self): pass
A well-written recipe will log what it's doing.
Often the update method is empty, as in this case.
Uninstall recipes
servicerecipe.py:
import os
class Service:
def __init__(self, buildout, name, options):
self.options = options
def install(self):
os.system("chkconfig --add %s" % self.options['script'])
return ()
def update(self):
pass
def uninstall_service(name, options):
os.system("chkconfig --del %s" % options['script'])
Buildout entry points
setup.py:
from setuptools import setup
entry_points = """
[zc.buildout]
mkdir = mkdirrecipe:Mkdir
service = servicerecipe:Service
default = mkdirrecipe:Mkdir
[zc.buildout.uninstall]
service = servicerecipe:uninstall_service
"""
setup(name='recipes', entry_points=entry_points)

