summaryrefslogtreecommitdiff
path: root/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.txt
diff options
context:
space:
mode:
Diffstat (limited to 'eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.txt')
-rw-r--r--eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.txt2831
1 files changed, 2831 insertions, 0 deletions
diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.txt
new file mode 100644
index 0000000..ba3a72f
--- /dev/null
+++ b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.txt
@@ -0,0 +1,2831 @@
+Buildouts
+=========
+
+The word "buildout" refers to a description of a set of parts and the
+software to create and assemble them. It is often used informally to
+refer to an installed system based on a buildout definition. For
+example, if we are creating an application named "Foo", then "the Foo
+buildout" is the collection of configuration and application-specific
+software that allows an instance of the application to be created. We
+may refer to such an instance of the application informally as "a Foo
+buildout".
+
+This document describes how to define buildouts using buildout
+configuration files and recipes. There are three ways to set up the
+buildout software and create a buildout instance:
+
+1. Install the zc.buildout egg with easy_install and use the buildout
+ script installed in a Python scripts area.
+
+2. Use the buildout bootstrap script to create a buildout that
+ includes both the setuptools and zc.buildout eggs. This allows you
+ to use the buildout software without modifying a Python install.
+ The buildout script is installed into your buildout local scripts
+ area.
+
+3. Use a buildout command from an already installed buildout to
+ bootstrap a new buildout. (See the section on bootstraping later
+ in this document.)
+
+Often, a software project will be managed in a software repository,
+such as a subversion repository, that includes some software source
+directories, buildout configuration files, and a copy of the buildout
+bootstrap script. To work on the project, one would check out the
+project from the repository and run the bootstrap script which
+installs setuptools and zc.buildout into the checkout as well as any
+parts defined.
+
+We have a sample buildout that we created using the bootstrap command
+of an existing buildout (method 3 above). It has the absolute minimum
+information. We have bin, develop-eggs, eggs and parts directories,
+and a configuration file:
+
+ >>> ls(sample_buildout)
+ d bin
+ - buildout.cfg
+ d develop-eggs
+ d eggs
+ d parts
+
+The bin directory contains scripts.
+
+ >>> ls(sample_buildout, 'bin')
+ - buildout
+
+ >>> ls(sample_buildout, 'eggs')
+ - setuptools-0.6-py2.4.egg
+ - zc.buildout-1.0-py2.4.egg
+
+The develop-eggs directory is initially empty:
+
+ >>> ls(sample_buildout, 'develop-eggs')
+
+The develop-eggs directory holds egg links for software being
+developed in the buildout. We separate develop-eggs and other eggs to
+allow eggs directories to be shared across multiple buildouts. For
+example, a common developer technique is to define a common eggs
+directory in their home that all non-develop eggs are stored in. This
+allows larger buildouts to be set up much more quickly and saves disk
+space.
+
+The parts directory just contains some helpers for the buildout script
+itself.
+
+ >>> ls(sample_buildout, 'parts')
+ d buildout
+
+The parts directory provides an area where recipes can install
+part data. For example, if we built a custom Python, we would
+install it in the part directory. Part data is stored in a
+sub-directory of the parts directory with the same name as the part.
+
+Buildouts are defined using configuration files. These are in the
+format defined by the Python ConfigParser module, with extensions
+that we'll describe later. By default, when a buildout is run, it
+looks for the file buildout.cfg in the directory where the buildout is
+run.
+
+The minimal configuration file has a buildout section that defines no
+parts:
+
+ >>> cat(sample_buildout, 'buildout.cfg')
+ [buildout]
+ parts =
+
+A part is simply something to be created by a buildout. It can be
+almost anything, such as a Python package, a program, a directory, or
+even a configuration file.
+
+Recipes
+-------
+
+A part is created by a recipe. Recipes are always installed as Python
+eggs. They can be downloaded from a package server, such as the
+Python Package Index, or they can be developed as part of a project
+using a "develop" egg.
+
+A develop egg is a special kind of egg that gets installed as an "egg
+link" that contains the name of a source directory. Develop eggs
+don't have to be packaged for distribution to be used and can be
+modified in place, which is especially useful while they are being
+developed.
+
+Let's create a recipe as part of the sample project. We'll create a
+recipe for creating directories. First, we'll create a recipes source
+directory for our local recipes:
+
+ >>> mkdir(sample_buildout, 'recipes')
+
+and then we'll create a source file for our mkdir recipe:
+
+ >>> write(sample_buildout, 'recipes', 'mkdir.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')
+ ...
+ ...
+ ... 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
+ ... """)
+
+Currently, recipes must define 3 methods [#future_recipe_methods]_:
+
+- a constructor,
+
+- an install method, and
+
+- an update method.
+
+The constructor is responsible for updating a parts options to reflect
+data read from other sections. The buildout system keeps track of
+whether a part specification has changed. A part specification has
+changed if it's options, after adjusting for data read from other
+sections, has changed, or if the recipe has changed. Only the options
+for the part are considered. If data are read from other sections,
+then that information has to be reflected in the parts options. In
+the Mkdir example, the given path is interpreted relative to the
+buildout directory, and data from the buildout directory is read. The
+path option is updated to reflect this. If the directory option was
+changed in the buildout sections, we would know to update parts
+created using the mkdir recipe using relative path names.
+
+When buildout is run, it saves configuration data for installed parts
+in a file named ".installed.cfg". In subsequent runs, it compares
+part-configuration data stored in the .installed.cfg file and the
+part-configuration data loaded from the configuration files as
+modified by recipe constructors to decide if the configuration of a
+part has changed. If the configuration has changed, or if the recipe
+has changed, then the part is uninstalled and reinstalled. The
+buildout only looks at the part's options, so any data used to
+configure the part needs to be reflected in the part's options. It is
+the job of a recipe constructor to make sure that the options include
+all relevant data.
+
+Of course, parts are also uninstalled if they are no-longer used.
+
+The recipe defines a constructor that takes a buildout object, a part
+name, and an options dictionary. It saves them in instance attributes.
+If the path is relative, we'll interpret it as relative to the
+buildout directory. The buildout object passed in is a mapping from
+section name to a mapping of options for that section. The buildout
+directory is available as the directory option of the buildout
+section. We normalize the path and save it back into the options
+directory.
+
+The install method is responsible for creating the part. In this
+case, we need the path of the directory to create. We'll use a path
+option from our options dictionary. The install method logs what it's
+doing using the Python logging call. We return the path that we
+installed. If the part is uninstalled or reinstalled, then the path
+returned will be removed by the buildout machinery. A recipe install
+method is expected to return a string, or an iterable of strings
+containing paths to be removed if a part is uninstalled. For most
+recipes, this is all of the uninstall support needed. For more complex
+uninstallation scenarios use `Uninstall recipes`_.
+
+The update method is responsible for updating an already installed
+part. An empty method is often provided, as in this example, if parts
+can't be updated. An update method can return None, a string, or an
+iterable of strings. If a string or iterable of strings is returned,
+then the saved list of paths to be uninstalled is updated with the new
+information by adding any new files returned by the update method.
+
+We need to provide packaging information so that our recipe can be
+installed as a develop egg. The minimum information we need to specify
+[#packaging_info]_ is a name. For recipes, we also need to define the
+names of the recipe classes as entry points. Packaging information is
+provided via a setup.py script:
+
+ >>> write(sample_buildout, 'recipes', 'setup.py',
+ ... """
+ ... from setuptools import setup
+ ...
+ ... setup(
+ ... name = "recipes",
+ ... entry_points = {'zc.buildout': ['mkdir = mkdir:Mkdir']},
+ ... )
+ ... """)
+
+Our setup script defines an entry point. Entry points provide
+a way for an egg to define the services it provides. Here we've said
+that we define a zc.buildout entry point named mkdir. Recipe
+classes must be exposed as entry points in the zc.buildout group. we
+give entry points names within the group.
+
+We also need a README.txt for our recipes to avoid an annoying warning
+from distutils, on which setuptools and zc.buildout are based:
+
+ >>> write(sample_buildout, 'recipes', 'README.txt', " ")
+
+Now let's update our buildout.cfg:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data-dir
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = mystuff
+ ... """)
+
+Let's go through the changes one by one::
+
+ develop = recipes
+
+This tells the buildout to install a development egg for our recipes.
+Any number of paths can be listed. The paths can be relative or
+absolute. If relative, they are treated as relative to the buildout
+directory. They can be directory or file paths. If a file path is
+given, it should point to a Python setup script. If a directory path
+is given, it should point to a directory containing a setup.py file.
+Development eggs are installed before building any parts, as they may
+provide locally-defined recipes needed by the parts.
+
+::
+
+ parts = data-dir
+
+Here we've named a part to be "built". We can use any name we want
+except that different part names must be unique and recipes will often
+use the part name to decide what to do.
+
+::
+
+ [data-dir]
+ recipe = recipes:mkdir
+ path = mystuff
+
+
+When we name a part, we also create a section of the same
+name that contains part data. In this section, we'll define
+the recipe to be used to install the part. In this case, we also
+specify the path to be created.
+
+Let's run the buildout. We do so by running the build script in the
+buildout:
+
+ >>> import os
+ >>> os.chdir(sample_buildout)
+ >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Installing data-dir.
+ data-dir: Creating directory mystuff
+
+We see that the recipe created the directory, as expected:
+
+ >>> ls(sample_buildout)
+ - .installed.cfg
+ d bin
+ - buildout.cfg
+ d develop-eggs
+ d eggs
+ d mystuff
+ d parts
+ d recipes
+
+In addition, .installed.cfg has been created containing information
+about the part we installed:
+
+ >>> cat(sample_buildout, '.installed.cfg')
+ [buildout]
+ installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link
+ parts = data-dir
+ <BLANKLINE>
+ [data-dir]
+ __buildout_installed__ = /sample-buildout/mystuff
+ __buildout_signature__ = recipes-c7vHV6ekIDUPy/7fjAaYjg==
+ path = /sample-buildout/mystuff
+ recipe = recipes:mkdir
+
+Note that the directory we installed is included in .installed.cfg.
+In addition, the path option includes the actual destination
+directory.
+
+If we change the name of the directory in the configuration file,
+we'll see that the directory gets removed and recreated:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data-dir
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = mydata
+ ... """)
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling data-dir.
+ Installing data-dir.
+ data-dir: Creating directory mydata
+
+ >>> ls(sample_buildout)
+ - .installed.cfg
+ d bin
+ - buildout.cfg
+ d develop-eggs
+ d eggs
+ d mydata
+ d parts
+ d recipes
+
+If any of the files or directories created by a recipe are removed,
+the part will be reinstalled:
+
+ >>> rmdir(sample_buildout, 'mydata')
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling data-dir.
+ Installing data-dir.
+ data-dir: Creating directory mydata
+
+Error reporting
+---------------
+
+If a user makes an error, an error needs to be printed and work needs
+to stop. This is accomplished by logging a detailed error message and
+then raising a (or an instance of a subclass of a)
+zc.buildout.UserError exception. Raising an error other than a
+UserError still displays the error, but labels it as a bug in the
+buildout software or recipe. In the sample above, of someone gives a
+non-existent directory to create the directory in:
+
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data-dir
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = /xxx/mydata
+ ... """)
+
+We'll get a user error, not a traceback.
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ data-dir: Cannot create /xxx/mydata. /xxx is not a directory.
+ While:
+ Installing.
+ Getting section data-dir.
+ Initializing part data-dir.
+ Error: Invalid Path
+
+
+Recipe Error Handling
+---------------------
+
+If an error occurs during installation, it is up to the recipe to
+clean up any system side effects, such as files created. Let's update
+the mkdir recipe to support multiple paths:
+
+ >>> write(sample_buildout, 'recipes', 'mkdir.py',
+ ... """
+ ... import logging, os, zc.buildout
+ ...
+ ... class Mkdir:
+ ...
+ ... def __init__(self, buildout, name, options):
+ ... self.name, self.options = name, options
+ ...
+ ... # Normalize paths and check that their parent
+ ... # directories exist:
+ ... paths = []
+ ... for path in options['path'].split():
+ ... path = os.path.join(buildout['buildout']['directory'], path)
+ ... if not os.path.isdir(os.path.dirname(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')
+ ... paths.append(path)
+ ... options['path'] = ' '.join(paths)
+ ...
+ ... def install(self):
+ ... paths = self.options['path'].split()
+ ... for path in paths:
+ ... logging.getLogger(self.name).info(
+ ... 'Creating directory %s', os.path.basename(path))
+ ... os.mkdir(path)
+ ... return paths
+ ...
+ ... def update(self):
+ ... pass
+ ... """)
+
+If there is an error creating a path, the install method will exit and
+leave previously created paths in place:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data-dir
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = foo bin
+ ... """)
+
+ >>> print system(buildout), # doctest: +ELLIPSIS
+ Develop: '/sample-buildout/recipes'
+ Uninstalling data-dir.
+ Installing data-dir.
+ data-dir: Creating directory foo
+ data-dir: Creating directory bin
+ While:
+ Installing data-dir.
+ <BLANKLINE>
+ An internal error occurred due to a bug in either zc.buildout or in a
+ recipe being used:
+ Traceback (most recent call last):
+ ...
+ OSError: [Errno 17] File exists: '/sample-buildout/bin'
+
+We meant to create a directory bins, but typed bin. Now foo was
+left behind.
+
+ >>> os.path.exists('foo')
+ True
+
+If we fix the typo:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data-dir
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = foo bins
+ ... """)
+
+ >>> print system(buildout), # doctest: +ELLIPSIS
+ Develop: '/sample-buildout/recipes'
+ Installing data-dir.
+ data-dir: Creating directory foo
+ While:
+ Installing data-dir.
+ <BLANKLINE>
+ An internal error occurred due to a bug in either zc.buildout or in a
+ recipe being used:
+ Traceback (most recent call last):
+ ...
+ OSError: [Errno 17] File exists: '/sample-buildout/foo'
+
+Now they fail because foo exists, because it was left behind.
+
+ >>> remove('foo')
+
+Let's fix the recipe:
+
+ >>> write(sample_buildout, 'recipes', 'mkdir.py',
+ ... """
+ ... import logging, os, zc.buildout
+ ...
+ ... class Mkdir:
+ ...
+ ... def __init__(self, buildout, name, options):
+ ... self.name, self.options = name, options
+ ...
+ ... # Normalize paths and check that their parent
+ ... # directories exist:
+ ... paths = []
+ ... for path in options['path'].split():
+ ... path = os.path.join(buildout['buildout']['directory'], path)
+ ... if not os.path.isdir(os.path.dirname(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')
+ ... paths.append(path)
+ ... options['path'] = ' '.join(paths)
+ ...
+ ... def install(self):
+ ... paths = self.options['path'].split()
+ ... created = []
+ ... try:
+ ... for path in paths:
+ ... logging.getLogger(self.name).info(
+ ... 'Creating directory %s', os.path.basename(path))
+ ... os.mkdir(path)
+ ... created.append(path)
+ ... except:
+ ... for d in created:
+ ... os.rmdir(d)
+ ... raise
+ ...
+ ... return paths
+ ...
+ ... def update(self):
+ ... pass
+ ... """)
+
+And put back the typo:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data-dir
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = foo bin
+ ... """)
+
+When we rerun the buildout:
+
+ >>> print system(buildout), # doctest: +ELLIPSIS
+ Develop: '/sample-buildout/recipes'
+ Installing data-dir.
+ data-dir: Creating directory foo
+ data-dir: Creating directory bin
+ While:
+ Installing data-dir.
+ <BLANKLINE>
+ An internal error occurred due to a bug in either zc.buildout or in a
+ recipe being used:
+ Traceback (most recent call last):
+ ...
+ OSError: [Errno 17] File exists: '/sample-buildout/bin'
+
+.. Wait for the file to really disappear. My linux is weird.
+
+ >>> wait_until("foo goes away", lambda : not os.path.exists('foo'),
+ ... timeout=200)
+
+we get the same error, but we don't get the directory left behind:
+
+ >>> os.path.exists('foo')
+ False
+
+It's critical that recipes clean up partial effects when errors
+occur. Because recipes most commonly create files and directories,
+buildout provides a helper API for removing created files when an
+error occurs. Option objects have a created method that can be called
+to record files as they are created. If the install or update method
+returns with an error, then any registered paths are removed
+automatically. The method returns the files registered and can be
+used to return the files created. Let's use this API to simplify the
+recipe:
+
+ >>> write(sample_buildout, 'recipes', 'mkdir.py',
+ ... """
+ ... import logging, os, zc.buildout
+ ...
+ ... class Mkdir:
+ ...
+ ... def __init__(self, buildout, name, options):
+ ... self.name, self.options = name, options
+ ...
+ ... # Normalize paths and check that their parent
+ ... # directories exist:
+ ... paths = []
+ ... for path in options['path'].split():
+ ... path = os.path.join(buildout['buildout']['directory'], path)
+ ... if not os.path.isdir(os.path.dirname(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')
+ ... paths.append(path)
+ ... options['path'] = ' '.join(paths)
+ ...
+ ... def install(self):
+ ... paths = self.options['path'].split()
+ ... for path in paths:
+ ... logging.getLogger(self.name).info(
+ ... 'Creating directory %s', os.path.basename(path))
+ ... os.mkdir(path)
+ ... self.options.created(path)
+ ...
+ ... return self.options.created()
+ ...
+ ... def update(self):
+ ... pass
+ ... """)
+
+..
+
+ >>> remove(sample_buildout, 'recipes', 'mkdir.pyc')
+
+We returned by calling created, taking advantage of the fact that it
+returns the registered paths. We did this for illustrative purposes.
+It would be simpler just to return the paths as before.
+
+If we rerun the buildout, again, we'll get the error and no
+directories will be created:
+
+ >>> print system(buildout), # doctest: +ELLIPSIS
+ Develop: '/sample-buildout/recipes'
+ Installing data-dir.
+ data-dir: Creating directory foo
+ data-dir: Creating directory bin
+ While:
+ Installing data-dir.
+ <BLANKLINE>
+ An internal error occurred due to a bug in either zc.buildout or in a
+ recipe being used:
+ Traceback (most recent call last):
+ ...
+ OSError: [Errno 17] File exists: '/sample-buildout/bin'
+
+ >>> os.path.exists('foo')
+ False
+
+Now, we'll fix the typo again and we'll get the directories we expect:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data-dir
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = foo bins
+ ... """)
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Installing data-dir.
+ data-dir: Creating directory foo
+ data-dir: Creating directory bins
+
+ >>> os.path.exists('foo')
+ True
+ >>> os.path.exists('bins')
+ True
+
+Configuration file syntax
+-------------------------
+
+As mentioned earlier, buildout configuration files use the format
+defined by the Python ConfigParser module with extensions. The
+extensions are:
+
+- option names are case sensitive
+
+- option values can use a substitution syntax, described below, to
+ refer to option values in specific sections.
+
+- option values can be appended or removed using the - and +
+ operators.
+
+The ConfigParser syntax is very flexible. Section names can contain
+any characters other than newlines and right square braces ("]").
+Option names can contain any characters other than newlines, colons,
+and equal signs, can not start with a space, and don't include
+trailing spaces.
+
+It is likely that, in the future, some characters will be given
+special buildout-defined meanings. This is already true of the
+characters ":", "$", "%", "(", and ")". For now, it is a good idea to
+keep section and option names simple, sticking to alphanumeric
+characters, hyphens, and periods.
+
+Annotated sections
+------------------
+
+When used with the `annotate` command, buildout displays annotated sections.
+All sections are displayed, sorted alphabetically. For each section,
+all key-value pairs are displayed, sorted alphabetically, along with
+the origin of the value (file name or COMPUTED_VALUE, DEFAULT_VALUE,
+COMMAND_LINE_VALUE).
+
+ >>> print system(buildout+ ' annotate'),
+ ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+ <BLANKLINE>
+ Annotated sections
+ ==================
+ <BLANKLINE>
+ [buildout]
+ accept-buildout-test-releases= false
+ DEFAULT_VALUE
+ allow-hosts= *
+ DEFAULT_VALUE
+ allow-picked-versions= true
+ DEFAULT_VALUE
+ allowed-eggs-from-site-packages= *
+ DEFAULT_VALUE
+ bin-directory= bin
+ DEFAULT_VALUE
+ develop= recipes
+ /sample-buildout/buildout.cfg
+ develop-eggs-directory= develop-eggs
+ DEFAULT_VALUE
+ directory= /sample-buildout
+ COMPUTED_VALUE
+ eggs-directory= eggs
+ DEFAULT_VALUE
+ exec-sitecustomize= true
+ DEFAULT_VALUE
+ executable= ...
+ DEFAULT_VALUE
+ find-links=
+ DEFAULT_VALUE
+ include-site-packages= true
+ DEFAULT_VALUE
+ install-from-cache= false
+ DEFAULT_VALUE
+ installed= .installed.cfg
+ DEFAULT_VALUE
+ log-format=
+ DEFAULT_VALUE
+ log-level= INFO
+ DEFAULT_VALUE
+ newest= true
+ DEFAULT_VALUE
+ offline= false
+ DEFAULT_VALUE
+ parts= data-dir
+ /sample-buildout/buildout.cfg
+ parts-directory= parts
+ DEFAULT_VALUE
+ prefer-final= false
+ DEFAULT_VALUE
+ python= buildout
+ DEFAULT_VALUE
+ relative-paths= false
+ DEFAULT_VALUE
+ socket-timeout=
+ DEFAULT_VALUE
+ unzip= false
+ DEFAULT_VALUE
+ use-dependency-links= true
+ DEFAULT_VALUE
+ <BLANKLINE>
+ [data-dir]
+ path= foo bins
+ /sample-buildout/buildout.cfg
+ recipe= recipes:mkdir
+ /sample-buildout/buildout.cfg
+ <BLANKLINE>
+
+Variable substitutions
+----------------------
+
+Buildout configuration files support variable substitution.
+To illustrate this, we'll create an debug recipe to
+allow us to see interactions with the buildout:
+
+ >>> write(sample_buildout, 'recipes', 'debug.py',
+ ... """
+ ... class Debug:
+ ...
+ ... def __init__(self, buildout, name, options):
+ ... self.buildout = buildout
+ ... self.name = name
+ ... self.options = options
+ ...
+ ... def install(self):
+ ... items = self.options.items()
+ ... items.sort()
+ ... for option, value in items:
+ ... print option, value
+ ... return ()
+ ...
+ ... update = install
+ ... """)
+
+This recipe doesn't actually create anything. The install method
+doesn't return anything, because it didn't create any files or
+directories.
+
+We also have to update our setup script:
+
+ >>> write(sample_buildout, 'recipes', 'setup.py',
+ ... """
+ ... from setuptools import setup
+ ... entry_points = (
+ ... '''
+ ... [zc.buildout]
+ ... mkdir = mkdir:Mkdir
+ ... debug = debug:Debug
+ ... ''')
+ ... setup(name="recipes", entry_points=entry_points)
+ ... """)
+
+We've rearranged the script a bit to make the entry points easier to
+edit. In particular, entry points are now defined as a configuration
+string, rather than a dictionary.
+
+Let's update our configuration to provide variable substitution
+examples:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data-dir debug
+ ... log-level = INFO
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... File 1 = ${data-dir:path}/file
+ ... File 2 = ${debug:File 1}/log
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = mydata
+ ... """)
+
+We used a string-template substitution for File 1 and File 2. This
+type of substitution uses the string.Template syntax. Names
+substituted are qualified option names, consisting of a section name
+and option name joined by a colon.
+
+Now, if we run the buildout, we'll see the options with the values
+substituted.
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling data-dir.
+ Installing data-dir.
+ data-dir: Creating directory mydata
+ Installing debug.
+ File 1 /sample-buildout/mydata/file
+ File 2 /sample-buildout/mydata/file/log
+ recipe recipes:debug
+
+Note that the substitution of the data-dir path option reflects the
+update to the option performed by the mkdir recipe.
+
+It might seem surprising that mydata was created again. This is
+because we changed our recipes package by adding the debug module.
+The buildout system didn't know if this module could effect the mkdir
+recipe, so it assumed it could and reinstalled mydata. If we rerun
+the buildout:
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Updating data-dir.
+ Updating debug.
+ File 1 /sample-buildout/mydata/file
+ File 2 /sample-buildout/mydata/file/log
+ recipe recipes:debug
+
+We can see that mydata was not recreated.
+
+Note that, in this case, we didn't specify a log level, so
+we didn't get output about what the buildout was doing.
+
+Section and option names in variable substitutions are only allowed to
+contain alphanumeric characters, hyphens, periods and spaces. This
+restriction might be relaxed in future releases.
+
+We can ommit the section name in a variable substitution to refer to
+the current section. We can also use the special option,
+_buildout_section_name_ to get the current section name.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data-dir debug
+ ... log-level = INFO
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... File 1 = ${data-dir:path}/file
+ ... File 2 = ${:File 1}/log
+ ... my_name = ${:_buildout_section_name_}
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = mydata
+ ... """)
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Updating data-dir.
+ Installing debug.
+ File 1 /sample-buildout/mydata/file
+ File 2 /sample-buildout/mydata/file/log
+ my_name debug
+ recipe recipes:debug
+
+Automatic part selection and ordering
+-------------------------------------
+
+When a section with a recipe is referred to, either through variable
+substitution or by an initializing recipe, the section is treated as a
+part and added to the part list before the referencing part. For
+example, we can leave data-dir out of the parts list:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug
+ ... log-level = INFO
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... File 1 = ${data-dir:path}/file
+ ... File 2 = ${debug:File 1}/log
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = mydata
+ ... """)
+
+
+It will still be treated as a part:
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Updating data-dir.
+ Installing debug.
+ File 1 /sample-buildout/mydata/file
+ File 2 /sample-buildout/mydata/file/log
+ recipe recipes:debug
+
+ >>> cat('.installed.cfg') # doctest: +ELLIPSIS
+ [buildout]
+ installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link
+ parts = data-dir debug
+ ...
+
+Note that the data-dir part is included *before* the debug part,
+because the debug part refers to the data-dir part. Even if we list
+the data-dir part after the debug part, it will be included before:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug data-dir
+ ... log-level = INFO
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... File 1 = ${data-dir:path}/file
+ ... File 2 = ${debug:File 1}/log
+ ...
+ ... [data-dir]
+ ... recipe = recipes:mkdir
+ ... path = mydata
+ ... """)
+
+
+It will still be treated as a part:
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Updating data-dir.
+ Updating debug.
+ File 1 /sample-buildout/mydata/file
+ File 2 /sample-buildout/mydata/file/log
+ recipe recipes:debug
+
+ >>> cat('.installed.cfg') # doctest: +ELLIPSIS
+ [buildout]
+ installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link
+ parts = data-dir debug
+ ...
+
+Extending sections (macros)
+---------------------------
+
+A section (other than the buildout section) can extend one or more
+other sections using the ``<=`` option. Options from the referenced
+sections are copied to the refering section *before* variable
+substitution. This, together with the ability to refer to variables
+of the current section allows sections to be used as macros.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = myfiles
+ ... log-level = INFO
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ...
+ ... [with_file1]
+ ... <= debug
+ ... file1 = ${:path}/file1
+ ... color = red
+ ...
+ ... [with_file2]
+ ... <= debug
+ ... file2 = ${:path}/file2
+ ... color = blue
+ ...
+ ... [myfiles]
+ ... <= with_file1
+ ... with_file2
+ ... path = mydata
+ ... """)
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Uninstalling data-dir.
+ Installing myfiles.
+ color blue
+ file1 mydata/file1
+ file2 mydata/file2
+ path mydata
+ recipe recipes:debug
+
+In this example, the debug, with_file1 and with_file2 sections act as
+macros. In particular, the variable substitutions are performed
+relative to the myfiles section.
+
+Adding and removing options
+---------------------------
+
+We can append and remove values to an option by using the + and -
+operators.
+
+This is illustrated below; first we define a base configuration.
+
+ >>> write(sample_buildout, 'base.cfg',
+ ... """
+ ... [buildout]
+ ... parts = part1 part2 part3
+ ...
+ ... [part1]
+ ... recipe =
+ ... option = a1 a2
+ ...
+ ... [part2]
+ ... recipe =
+ ... option = b1 b2 b3 b4
+ ...
+ ... [part3]
+ ... recipe =
+ ... option = c1 c2
+ ...
+ ... """)
+
+Extending this configuration, we can "adjust" the values set in the
+base configuration file.
+
+ >>> write(sample_buildout, 'extension1.cfg',
+ ... """
+ ... [buildout]
+ ... extends = base.cfg
+ ...
+ ... # appending values
+ ... [part1]
+ ... option += a3 a4
+ ...
+ ... # removing values
+ ... [part2]
+ ... option -= b1 b2
+ ...
+ ... # alt. spelling
+ ... [part3]
+ ... option+=c3 c4 c5
+ ...
+ ... # normal assignment
+ ... [part4]
+ ... option = h1 h2
+ ...
+ ... """)
+
+An additional extension.
+
+ >>> write(sample_buildout, 'extension2.cfg',
+ ... """
+ ... [buildout]
+ ... extends = extension1.cfg
+ ...
+ ... # appending values
+ ... [part1]
+ ... option += a5
+ ...
+ ... # removing values
+ ... [part2]
+ ... option -= b1 b2 b3
+ ...
+ ... """)
+
+To verify that the options are adjusted correctly, we'll set up an
+extension that prints out the options.
+
+ >>> mkdir(sample_buildout, 'demo')
+ >>> write(sample_buildout, 'demo', 'demo.py',
+ ... """
+ ... def ext(buildout):
+ ... print [part['option'] for name, part in buildout.items() \
+ ... if name.startswith('part')]
+ ... """)
+
+ >>> write(sample_buildout, 'demo', 'setup.py',
+ ... """
+ ... from setuptools import setup
+ ...
+ ... setup(
+ ... name="demo",
+ ... entry_points={'zc.buildout.extension': ['ext = demo:ext']},
+ ... )
+ ... """)
+
+Set up a buildout configuration for this extension.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = demo
+ ... parts =
+ ... """)
+
+ >>> os.chdir(sample_buildout)
+ >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')),
+ Develop: '/sample-buildout/demo'
+ Uninstalling myfiles.
+ Getting distribution for 'recipes'.
+ zip_safe flag not set; analyzing archive contents...
+ Got recipes 0.0.0.
+ warning: install_lib: 'build/lib' does not exist -- no Python modules to install
+
+Verify option values.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = demo
+ ... extensions = demo
+ ... extends = extension2.cfg
+ ... """)
+
+ >>> print system(os.path.join('bin', 'buildout')),
+ ['a1 a2/na3 a4/na5', 'b1 b2 b3 b4', 'c1 c2/nc3 c4 c5', 'h1 h2']
+ Develop: '/sample-buildout/demo'
+
+Annotated sections output shows which files are responsible for which
+operations.
+
+ >>> print system(os.path.join('bin', 'buildout') + ' annotate'),
+ ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+ <BLANKLINE>
+ Annotated sections
+ ==================
+ ...
+ <BLANKLINE>
+ [part1]
+ option= a1 a2
+ a3 a4
+ a5
+ /sample-buildout/base.cfg
+ += /sample-buildout/extension1.cfg
+ += /sample-buildout/extension2.cfg
+ recipe=
+ /sample-buildout/base.cfg
+ <BLANKLINE>
+ [part2]
+ option= b1 b2 b3 b4
+ /sample-buildout/base.cfg
+ -= /sample-buildout/extension1.cfg
+ -= /sample-buildout/extension2.cfg
+ recipe=
+ /sample-buildout/base.cfg
+ <BLANKLINE>
+ [part3]
+ option= c1 c2
+ c3 c4 c5
+ /sample-buildout/base.cfg
+ += /sample-buildout/extension1.cfg
+ recipe=
+ /sample-buildout/base.cfg
+ <BLANKLINE>
+ [part4]
+ option= h1 h2
+ /sample-buildout/extension1.cfg
+
+Cleanup.
+
+ >>> os.remove(os.path.join(sample_buildout, 'base.cfg'))
+ >>> os.remove(os.path.join(sample_buildout, 'extension1.cfg'))
+ >>> os.remove(os.path.join(sample_buildout, 'extension2.cfg'))
+
+Multiple configuration files
+----------------------------
+
+A configuration file can "extend" another configuration file.
+Options are read from the other configuration file if they aren't
+already defined by your configuration file.
+
+The configuration files your file extends can extend
+other configuration files. The same file may be
+used more than once although, of course, cycles aren't allowed.
+
+To see how this works, we use an example:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... extends = base.cfg
+ ...
+ ... [debug]
+ ... op = buildout
+ ... """)
+
+ >>> write(sample_buildout, 'base.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... op = base
+ ... """)
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Installing debug.
+ op buildout
+ recipe recipes:debug
+
+The example is pretty trivial, but the pattern it illustrates is
+pretty common. In a more practical example, the base buildout might
+represent a product and the extending buildout might be a
+customization.
+
+Here is a more elaborate example.
+
+ >>> other = tmpdir('other')
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... extends = b1.cfg b2.cfg %(b3)s
+ ...
+ ... [debug]
+ ... op = buildout
+ ... """ % dict(b3=os.path.join(other, 'b3.cfg')))
+
+ >>> write(sample_buildout, 'b1.cfg',
+ ... """
+ ... [buildout]
+ ... extends = base.cfg
+ ...
+ ... [debug]
+ ... op1 = b1 1
+ ... op2 = b1 2
+ ... """)
+
+ >>> write(sample_buildout, 'b2.cfg',
+ ... """
+ ... [buildout]
+ ... extends = base.cfg
+ ...
+ ... [debug]
+ ... op2 = b2 2
+ ... op3 = b2 3
+ ... """)
+
+ >>> write(other, 'b3.cfg',
+ ... """
+ ... [buildout]
+ ... extends = b3base.cfg
+ ...
+ ... [debug]
+ ... op4 = b3 4
+ ... """)
+
+ >>> write(other, 'b3base.cfg',
+ ... """
+ ... [debug]
+ ... op5 = b3base 5
+ ... """)
+
+ >>> write(sample_buildout, 'base.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... name = base
+ ... """)
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Installing debug.
+ name base
+ op buildout
+ op1 b1 1
+ op2 b2 2
+ op3 b2 3
+ op4 b3 4
+ op5 b3base 5
+ recipe recipes:debug
+
+There are several things to note about this example:
+
+- We can name multiple files in an extends option.
+
+- We can reference files recursively.
+
+- Relative file names in extended options are interpreted relative to
+ the directory containing the referencing configuration file.
+
+Loading Configuration from URLs
+-------------------------------
+
+Configuration files can be loaded from URLs. To see how this works,
+we'll set up a web server with some configuration files.
+
+ >>> server_data = tmpdir('server_data')
+
+ >>> write(server_data, "r1.cfg",
+ ... """
+ ... [debug]
+ ... op1 = r1 1
+ ... op2 = r1 2
+ ... """)
+
+ >>> write(server_data, "r2.cfg",
+ ... """
+ ... [buildout]
+ ... extends = r1.cfg
+ ...
+ ... [debug]
+ ... op2 = r2 2
+ ... op3 = r2 3
+ ... """)
+
+ >>> server_url = start_server(server_data)
+
+ >>> write('client.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug
+ ... extends = %(url)s/r2.cfg
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... name = base
+ ... """ % dict(url=server_url))
+
+
+ >>> print system(buildout+ ' -c client.cfg'),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Installing debug.
+ name base
+ op1 r1 1
+ op2 r2 2
+ op3 r2 3
+ recipe recipes:debug
+
+Here we specified a URL for the file we extended. The file we
+downloaded, itself referred to a file on the server using a relative
+URL reference. Relative references are interpreted relative to the
+base URL when they appear in configuration files loaded via URL.
+
+We can also specify a URL as the configuration file to be used by a
+buildout.
+
+ >>> os.remove('client.cfg')
+ >>> write(server_data, 'remote.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug
+ ... extends = r2.cfg
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... name = remote
+ ... """)
+
+ >>> print system(buildout + ' -c ' + server_url + '/remote.cfg'),
+ While:
+ Initializing.
+ Error: Missing option: buildout:directory
+
+Normally, the buildout directory defaults to directory
+containing a configuration file. This won't work for configuration
+files loaded from URLs. In this case, the buildout directory would
+normally be defined on the command line:
+
+ >>> print system(buildout
+ ... + ' -c ' + server_url + '/remote.cfg'
+ ... + ' buildout:directory=' + sample_buildout
+ ... ),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Installing debug.
+ name remote
+ op1 r1 1
+ op2 r2 2
+ op3 r2 3
+ recipe recipes:debug
+
+User defaults
+-------------
+
+If the file $HOME/.buildout/default.cfg, exists, it is read before
+reading the configuration file. ($HOME is the value of the HOME
+environment variable. The '/' is replaced by the operating system file
+delimiter.)
+
+ >>> old_home = os.environ['HOME']
+ >>> home = tmpdir('home')
+ >>> mkdir(home, '.buildout')
+ >>> write(home, '.buildout', 'default.cfg',
+ ... """
+ ... [debug]
+ ... op1 = 1
+ ... op7 = 7
+ ... """)
+
+ >>> os.environ['HOME'] = home
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Installing debug.
+ name base
+ op buildout
+ op1 b1 1
+ op2 b2 2
+ op3 b2 3
+ op4 b3 4
+ op5 b3base 5
+ op7 7
+ recipe recipes:debug
+
+A buildout command-line argument, -U, can be used to suppress reading
+user defaults:
+
+ >>> print system(buildout + ' -U'),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Installing debug.
+ name base
+ op buildout
+ op1 b1 1
+ op2 b2 2
+ op3 b2 3
+ op4 b3 4
+ op5 b3base 5
+ recipe recipes:debug
+
+ >>> os.environ['HOME'] = old_home
+
+Log level
+---------
+
+We can control the level of logging by specifying a log level in out
+configuration file. For example, so suppress info messages, we can
+set the logging level to WARNING
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... log-level = WARNING
+ ... extends = b1.cfg b2.cfg
+ ... """)
+
+ >>> print system(buildout),
+ name base
+ op1 b1 1
+ op2 b2 2
+ op3 b2 3
+ recipe recipes:debug
+
+Uninstall recipes
+-----------------
+
+As we've seen, when parts are installed, buildout keeps track of files
+and directories that they create. When the parts are uninstalled these
+files and directories are deleted.
+
+Sometimes more clean up is needed. For example, a recipe might add a
+system service by calling chkconfig --add during installation. Later
+during uninstallation, chkconfig --del will need to be called to
+remove the system service.
+
+In order to deal with these uninstallation issues, you can register
+uninstall recipes. Uninstall recipes are registered using the
+'zc.buildout.uninstall' entry point. Parts specify uninstall recipes
+using the 'uninstall' option.
+
+In comparison to regular recipes, uninstall recipes are much
+simpler. They are simply callable objects that accept the name of the
+part to be uninstalled and the part's options dictionary. Uninstall
+recipes don't have access to the part itself since it maybe not be
+able to be instantiated at uninstallation time.
+
+Here's a recipe that simulates installation of a system service, along
+with an uninstall recipe that simulates removing the service.
+
+ >>> write(sample_buildout, 'recipes', 'service.py',
+ ... """
+ ... class Service:
+ ...
+ ... def __init__(self, buildout, name, options):
+ ... self.buildout = buildout
+ ... self.name = name
+ ... self.options = options
+ ...
+ ... def install(self):
+ ... print "chkconfig --add %s" % self.options['script']
+ ... return ()
+ ...
+ ... def update(self):
+ ... pass
+ ...
+ ...
+ ... def uninstall_service(name, options):
+ ... print "chkconfig --del %s" % options['script']
+ ... """)
+
+To use these recipes we must register them using entry points. Make
+sure to use the same name for the recipe and uninstall recipe. This is
+required to let buildout know which uninstall recipe goes with which
+recipe.
+
+ >>> write(sample_buildout, 'recipes', 'setup.py',
+ ... """
+ ... from setuptools import setup
+ ... entry_points = (
+ ... '''
+ ... [zc.buildout]
+ ... mkdir = mkdir:Mkdir
+ ... debug = debug:Debug
+ ... service = service:Service
+ ...
+ ... [zc.buildout.uninstall]
+ ... service = service:uninstall_service
+ ... ''')
+ ... setup(name="recipes", entry_points=entry_points)
+ ... """)
+
+Here's how these recipes could be used in a buildout:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = service
+ ...
+ ... [service]
+ ... recipe = recipes:service
+ ... script = /path/to/script
+ ... """)
+
+When the buildout is run the service will be installed
+
+ >>> print system(buildout)
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Installing service.
+ chkconfig --add /path/to/script
+ <BLANKLINE>
+
+The service has been installed. If the buildout is run again with no
+changes, the service shouldn't be changed.
+
+ >>> print system(buildout)
+ Develop: '/sample-buildout/recipes'
+ Updating service.
+ <BLANKLINE>
+
+Now we change the service part to trigger uninstallation and
+re-installation.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = service
+ ...
+ ... [service]
+ ... recipe = recipes:service
+ ... script = /path/to/a/different/script
+ ... """)
+
+ >>> print system(buildout)
+ Develop: '/sample-buildout/recipes'
+ Uninstalling service.
+ Running uninstall recipe.
+ chkconfig --del /path/to/script
+ Installing service.
+ chkconfig --add /path/to/a/different/script
+ <BLANKLINE>
+
+Now we remove the service part, and add another part.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... """)
+
+ >>> print system(buildout)
+ Develop: '/sample-buildout/recipes'
+ Uninstalling service.
+ Running uninstall recipe.
+ chkconfig --del /path/to/a/different/script
+ Installing debug.
+ recipe recipes:debug
+ <BLANKLINE>
+
+Uninstall recipes don't have to take care of removing all the files
+and directories created by the part. This is still done automatically,
+following the execution of the uninstall recipe. An upshot is that an
+uninstallation recipe can access files and directories created by a
+recipe before they are deleted.
+
+For example, here's an uninstallation recipe that simulates backing up
+a directory before it is deleted. It is designed to work with the
+mkdir recipe introduced earlier.
+
+ >>> write(sample_buildout, 'recipes', 'backup.py',
+ ... """
+ ... import os
+ ... def backup_directory(name, options):
+ ... path = options['path']
+ ... size = len(os.listdir(path))
+ ... print "backing up directory %s of size %s" % (path, size)
+ ... """)
+
+It must be registered with the zc.buildout.uninstall entry
+point. Notice how it is given the name 'mkdir' to associate it with
+the mkdir recipe.
+
+ >>> write(sample_buildout, 'recipes', 'setup.py',
+ ... """
+ ... from setuptools import setup
+ ... entry_points = (
+ ... '''
+ ... [zc.buildout]
+ ... mkdir = mkdir:Mkdir
+ ... debug = debug:Debug
+ ... service = service:Service
+ ...
+ ... [zc.buildout.uninstall]
+ ... uninstall_service = service:uninstall_service
+ ... mkdir = backup:backup_directory
+ ... ''')
+ ... setup(name="recipes", entry_points=entry_points)
+ ... """)
+
+Now we can use it with a mkdir part.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = dir debug
+ ...
+ ... [dir]
+ ... recipe = recipes:mkdir
+ ... path = my_directory
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... """)
+
+Run the buildout to install the part.
+
+ >>> print system(buildout)
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Installing dir.
+ dir: Creating directory my_directory
+ Installing debug.
+ recipe recipes:debug
+ <BLANKLINE>
+
+Now we remove the part from the configuration file.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... """)
+
+When the buildout is run the part is removed, and the uninstall recipe
+is run before the directory is deleted.
+
+ >>> print system(buildout)
+ Develop: '/sample-buildout/recipes'
+ Uninstalling dir.
+ Running uninstall recipe.
+ backing up directory /sample-buildout/my_directory of size 0
+ Updating debug.
+ recipe recipes:debug
+ <BLANKLINE>
+
+Now we will return the registration to normal for the benefit of the
+rest of the examples.
+
+ >>> write(sample_buildout, 'recipes', 'setup.py',
+ ... """
+ ... from setuptools import setup
+ ... entry_points = (
+ ... '''
+ ... [zc.buildout]
+ ... mkdir = mkdir:Mkdir
+ ... debug = debug:Debug
+ ... ''')
+ ... setup(name="recipes", entry_points=entry_points)
+ ... """)
+
+
+Command-line usage
+------------------
+
+A number of arguments can be given on the buildout command line. The
+command usage is::
+
+ buildout [options and assignments] [command [command arguments]]
+
+The following options are supported:
+
+-h (or --help)
+ Print basic usage information. If this option is used, then all
+ other options are ignored.
+
+-c filename
+ The -c option can be used to specify a configuration file, rather than
+ buildout.cfg in the current directory.
+
+
+-t socket_timeout
+
+ Specify the socket timeout in seconds.
+
+-v
+ Increment the verbosity by 10. The verbosity is used to adjust
+ the logging level. The verbosity is subtracted from the numeric
+ value of the log-level option specified in the configuration file.
+
+-q
+ Decrement the verbosity by 10.
+
+-U
+ Don't read user-default configuration.
+
+-o
+ Run in off-line mode. This is equivalent to the assignment
+ buildout:offline=true.
+
+-O
+ Run in non-off-line mode. This is equivalent to the assignment
+ buildout:offline=false. This is the default buildout mode. The
+ -O option would normally be used to override a true offline
+ setting in a configuration file.
+
+-n
+ Run in newest mode. This is equivalent to the assignment
+ buildout:newest=true. With this setting, which is the default,
+ buildout will try to find the newest versions of distributions
+ available that satisfy its requirements.
+
+-N
+ Run in non-newest mode. This is equivalent to the assignment
+ buildout:newest=false. With this setting, buildout will not seek
+ new distributions if installed distributions satisfy it's
+ requirements.
+
+Assignments are of the form::
+
+ section_name:option_name=value
+
+Options and assignments can be given in any order.
+
+Here's an example:
+
+ >>> write(sample_buildout, 'other.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug
+ ... installed = .other.cfg
+ ... log-level = WARNING
+ ...
+ ... [debug]
+ ... name = other
+ ... recipe = recipes:debug
+ ... """)
+
+Note that we used the installed buildout option to specify an
+alternate file to store information about installed parts.
+
+ >>> print system(buildout+' -c other.cfg debug:op1=foo -v'),
+ Develop: '/sample-buildout/recipes'
+ Installing debug.
+ name other
+ op1 foo
+ recipe recipes:debug
+
+Here we used the -c option to specify an alternate configuration file,
+and the -v option to increase the level of logging from the default,
+WARNING.
+
+Options can also be combined in the usual Unix way, as in:
+
+ >>> print system(buildout+' -vcother.cfg debug:op1=foo'),
+ Develop: '/sample-buildout/recipes'
+ Updating debug.
+ name other
+ op1 foo
+ recipe recipes:debug
+
+Here we combined the -v and -c options with the configuration file
+name. Note that the -c option has to be last, because it takes an
+argument.
+
+ >>> os.remove(os.path.join(sample_buildout, 'other.cfg'))
+ >>> os.remove(os.path.join(sample_buildout, '.other.cfg'))
+
+The most commonly used command is 'install' and it takes a list of
+parts to install. if any parts are specified, only those parts are
+installed. To illustrate this, we'll update our configuration and run
+the buildout in the usual way:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug d1 d2 d3
+ ...
+ ... [d1]
+ ... recipe = recipes:mkdir
+ ... path = d1
+ ...
+ ... [d2]
+ ... recipe = recipes:mkdir
+ ... path = d2
+ ...
+ ... [d3]
+ ... recipe = recipes:mkdir
+ ... path = d3
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... """)
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling debug.
+ Installing debug.
+ recipe recipes:debug
+ Installing d1.
+ d1: Creating directory d1
+ Installing d2.
+ d2: Creating directory d2
+ Installing d3.
+ d3: Creating directory d3
+
+ >>> ls(sample_buildout)
+ - .installed.cfg
+ - b1.cfg
+ - b2.cfg
+ - base.cfg
+ d bin
+ - buildout.cfg
+ d d1
+ d d2
+ d d3
+ d demo
+ d develop-eggs
+ d eggs
+ d parts
+ d recipes
+
+ >>> cat(sample_buildout, '.installed.cfg')
+ ... # doctest: +NORMALIZE_WHITESPACE
+ [buildout]
+ installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link
+ parts = debug d1 d2 d3
+ <BLANKLINE>
+ [debug]
+ __buildout_installed__ =
+ __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
+ recipe = recipes:debug
+ <BLANKLINE>
+ [d1]
+ __buildout_installed__ = /sample-buildout/d1
+ __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
+ path = /sample-buildout/d1
+ recipe = recipes:mkdir
+ <BLANKLINE>
+ [d2]
+ __buildout_installed__ = /sample-buildout/d2
+ __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
+ path = /sample-buildout/d2
+ recipe = recipes:mkdir
+ <BLANKLINE>
+ [d3]
+ __buildout_installed__ = /sample-buildout/d3
+ __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
+ path = /sample-buildout/d3
+ recipe = recipes:mkdir
+
+Now we'll update our configuration file:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug d2 d3 d4
+ ...
+ ... [d2]
+ ... recipe = recipes:mkdir
+ ... path = data2
+ ...
+ ... [d3]
+ ... recipe = recipes:mkdir
+ ... path = data3
+ ...
+ ... [d4]
+ ... recipe = recipes:mkdir
+ ... path = ${d2:path}-extra
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... x = 1
+ ... """)
+
+and run the buildout specifying just d3 and d4:
+
+ >>> print system(buildout+' install d3 d4'),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling d3.
+ Installing d3.
+ d3: Creating directory data3
+ Installing d4.
+ d4: Creating directory data2-extra
+
+ >>> ls(sample_buildout)
+ - .installed.cfg
+ - b1.cfg
+ - b2.cfg
+ - base.cfg
+ d bin
+ - buildout.cfg
+ d d1
+ d d2
+ d data2-extra
+ d data3
+ d demo
+ d develop-eggs
+ d eggs
+ d parts
+ d recipes
+
+Only the d3 and d4 recipes ran. d3 was removed and data3 and data2-extra
+were created.
+
+The .installed.cfg is only updated for the recipes that ran:
+
+ >>> cat(sample_buildout, '.installed.cfg')
+ ... # doctest: +NORMALIZE_WHITESPACE
+ [buildout]
+ installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link
+ parts = debug d1 d2 d3 d4
+ <BLANKLINE>
+ [debug]
+ __buildout_installed__ =
+ __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
+ recipe = recipes:debug
+ <BLANKLINE>
+ [d1]
+ __buildout_installed__ = /sample-buildout/d1
+ __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
+ path = /sample-buildout/d1
+ recipe = recipes:mkdir
+ <BLANKLINE>
+ [d2]
+ __buildout_installed__ = /sample-buildout/d2
+ __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
+ path = /sample-buildout/d2
+ recipe = recipes:mkdir
+ <BLANKLINE>
+ [d3]
+ __buildout_installed__ = /sample-buildout/data3
+ __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
+ path = /sample-buildout/data3
+ recipe = recipes:mkdir
+ <BLANKLINE>
+ [d4]
+ __buildout_installed__ = /sample-buildout/data2-extra
+ __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg==
+ path = /sample-buildout/data2-extra
+ recipe = recipes:mkdir
+
+Note that the installed data for debug, d1, and d2 haven't changed,
+because we didn't install those parts and that the d1 and d2
+directories are still there.
+
+Now, if we run the buildout without the install command:
+
+ >>> print system(buildout),
+ Develop: '/sample-buildout/recipes'
+ Uninstalling d2.
+ Uninstalling d1.
+ Uninstalling debug.
+ Installing debug.
+ recipe recipes:debug
+ x 1
+ Installing d2.
+ d2: Creating directory data2
+ Updating d3.
+ Updating d4.
+
+We see the output of the debug recipe and that data2 was created. We
+also see that d1 and d2 have gone away:
+
+ >>> ls(sample_buildout)
+ - .installed.cfg
+ - b1.cfg
+ - b2.cfg
+ - base.cfg
+ d bin
+ - buildout.cfg
+ d data2
+ d data2-extra
+ d data3
+ d demo
+ d develop-eggs
+ d eggs
+ d parts
+ d recipes
+
+Alternate directory and file locations
+--------------------------------------
+
+The buildout normally puts the bin, eggs, and parts directories in the
+directory in the directory containing the configuration file. You can
+provide alternate locations, and even names for these directories.
+
+ >>> alt = tmpdir('sample-alt')
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts =
+ ... develop-eggs-directory = %(developbasket)s
+ ... eggs-directory = %(basket)s
+ ... bin-directory = %(scripts)s
+ ... parts-directory = %(work)s
+ ... """ % dict(
+ ... developbasket = os.path.join(alt, 'developbasket'),
+ ... basket = os.path.join(alt, 'basket'),
+ ... scripts = os.path.join(alt, 'scripts'),
+ ... work = os.path.join(alt, 'work'),
+ ... ))
+
+ >>> print system(buildout),
+ Creating directory '/sample-alt/scripts'.
+ Creating directory '/sample-alt/work'.
+ Creating directory '/sample-alt/basket'.
+ Creating directory '/sample-alt/developbasket'.
+ Develop: '/sample-buildout/recipes'
+ Uninstalling d4.
+ Uninstalling d3.
+ Uninstalling d2.
+ Uninstalling debug.
+
+ >>> ls(alt)
+ d basket
+ d developbasket
+ d scripts
+ d work
+
+ >>> ls(alt, 'developbasket')
+ - recipes.egg-link
+
+You can also specify an alternate buildout directory:
+
+ >>> rmdir(alt)
+ >>> alt = tmpdir('sample-alt')
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... directory = %(alt)s
+ ... develop = %(recipes)s
+ ... parts =
+ ... """ % dict(
+ ... alt=alt,
+ ... recipes=os.path.join(sample_buildout, 'recipes'),
+ ... ))
+
+ >>> print system(buildout),
+ Creating directory '/sample-alt/bin'.
+ Creating directory '/sample-alt/parts'.
+ Creating directory '/sample-alt/eggs'.
+ Creating directory '/sample-alt/develop-eggs'.
+ Develop: '/sample-buildout/recipes'
+
+ >>> ls(alt)
+ - .installed.cfg
+ d bin
+ d develop-eggs
+ d eggs
+ d parts
+
+ >>> ls(alt, 'develop-eggs')
+ - recipes.egg-link
+
+Logging control
+---------------
+
+Three buildout options are used to control logging:
+
+log-level
+ specifies the log level
+
+verbosity
+ adjusts the log level
+
+log-format
+ allows an alternate logging for mat to be specified
+
+We've already seen the log level and verbosity. Let's look at an example
+of changing the format:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts =
+ ... log-level = 25
+ ... verbosity = 5
+ ... log-format = %(levelname)s %(message)s
+ ... """)
+
+Here, we've changed the format to include the log-level name, rather
+than the logger name.
+
+We've also illustrated, with a contrived example, that the log level
+can be a numeric value and that the verbosity can be specified in the
+configuration file. Because the verbosity is subtracted from the log
+level, we get a final log level of 20, which is the INFO level.
+
+ >>> print system(buildout),
+ INFO Develop: '/sample-buildout/recipes'
+
+Predefined buildout options
+---------------------------
+
+Buildouts have a number of predefined options that recipes can use
+and that users can override in their configuration files. To see
+these, we'll run a minimal buildout configuration with a debug logging
+level. One of the features of debug logging is that the configuration
+database is shown.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... parts =
+ ... """)
+
+ >>> print system(buildout+' -vv'), # doctest: +NORMALIZE_WHITESPACE
+ Installing 'zc.buildout', 'setuptools'.
+ We have a develop egg: zc.buildout X.X.
+ We have the best distribution that satisfies 'setuptools'.
+ Picked: setuptools = V.V
+ <BLANKLINE>
+ Configuration data:
+ [buildout]
+ accept-buildout-test-releases = false
+ allow-hosts = *
+ allow-picked-versions = true
+ allowed-eggs-from-site-packages = *
+ bin-directory = /sample-buildout/bin
+ develop-eggs-directory = /sample-buildout/develop-eggs
+ directory = /sample-buildout
+ eggs-directory = /sample-buildout/eggs
+ exec-sitecustomize = true
+ executable = python
+ find-links =
+ include-site-packages = true
+ install-from-cache = false
+ installed = /sample-buildout/.installed.cfg
+ log-format =
+ log-level = INFO
+ newest = true
+ offline = false
+ parts =
+ parts-directory = /sample-buildout/parts
+ prefer-final = false
+ python = buildout
+ relative-paths = false
+ socket-timeout =
+ unzip = false
+ use-dependency-links = true
+ verbosity = 20
+ <BLANKLINE>
+
+All of these options can be overridden by configuration files or by
+command-line assignments. We've discussed most of these options
+already, but let's review them and touch on some we haven't discussed:
+
+allowed-eggs-from-site-packages
+ Sometimes you need or want to control what eggs from site-packages are
+ used. The allowed-eggs-from-site-packages option allows you to specify a
+ whitelist of project names that may be included from site-packages. You
+ can use globs to specify the value. It defaults to a single value of '*',
+ indicating that any package may come from site-packages.
+
+ Here's a usage example::
+
+ [buildout]
+ ...
+
+ allowed-eggs-from-site-packages =
+ demo
+ bigdemo
+ zope.*
+
+ This option interacts with the ``include-site-packages`` option in the
+ following ways.
+
+ If ``include-site-packages`` is true, then
+ ``allowed-eggs-from-site-packages`` filters what eggs from site-packages
+ may be chosen. Therefore, if ``allowed-eggs-from-site-packages`` is an
+ empty list, then no eggs from site-packages are chosen, but site-packages
+ will still be included at the end of path lists.
+
+ If ``include-site-packages`` is false, the value of
+ ``allowed-eggs-from-site-packages`` is irrelevant.
+
+ See the ``include-site-packages`` description for more information.
+
+bin-directory
+ The directory path where scripts are written. This can be a
+ relative path, which is interpreted relative to the directory
+ option.
+
+develop-eggs-directory
+ The directory path where development egg links are created for software
+ being created in the local project. This can be a relative path,
+ which is interpreted relative to the directory option.
+
+directory
+ The buildout directory. This is the base for other buildout file
+ and directory locations, when relative locations are used.
+
+eggs-directory
+ The directory path where downloaded eggs are put. It is common to share
+ this directory across buildouts. Eggs in this directory should
+ *never* be modified. This can be a relative path, which is
+ interpreted relative to the directory option.
+
+exec-sitecustomize
+ Normally the Python's real sitecustomize module is processed.
+ If you do not want it to be processed in order to increase the
+ repeatability of your buildout, set this value to 'false'. This will
+ be honored irrespective of the setting for include-site-packages.
+ This option will be honored by some recipes and not others.
+ z3c.recipe.scripts honors this and zc.recipe.egg does not, for
+ instance.
+
+executable
+ The Python executable used to run the buildout. See the python
+ option below.
+
+include-site-packages
+ You can choose not to have the site-packages of the underlying Python
+ available to your script or interpreter, in addition to the packages
+ from your eggs. This can increase repeatability for your buildout.
+ This option will be better used by some recipes than others.
+ z3c.recipe.scripts honors this fully and zc.recipe.egg only
+ partially, for instance.
+
+installed
+ The file path where information about the results of the previous
+ buildout run is written. This can be a relative path, which is
+ interpreted relative to the directory option. This file provides
+ an inventory of installed parts with information needed to decide
+ which if any parts need to be uninstalled.
+
+log-format
+ The format used for logging messages.
+
+log-level
+ The log level before verbosity adjustment
+
+parts
+ A white space separated list of parts to be installed.
+
+parts-directory
+ A working directory that parts can used to store data.
+
+python
+ The name of a section containing information about the default
+ Python interpreter. Recipes that need a installation
+ typically have options to tell them which Python installation to
+ use. By convention, if a section-specific option isn't used, the
+ option is looked for in the buildout section. The option must
+ point to a section with an executable option giving the path to a
+ Python executable. By default, the buildout section defines the
+ default Python as the Python used to run the buildout.
+
+relative-paths
+ The paths generated by zc.buildout are absolute by default, and this
+ option is ``false``. However, if you set this value to be ``true``,
+ bin/buildout will be generated with code that makes the paths relative.
+ Some recipes, such as zc.recipe.egg and z3c.recipe.scripts, honor this
+ value as well.
+
+unzip
+ By default, zc.buildout doesn't unzip zip-safe eggs ("unzip = false").
+ This follows the policy followed by setuptools itself. Experience shows
+ this policy to to be inconvenient. Zipped eggs make debugging more
+ difficult and often import more slowly. You can include an unzip option in
+ the buildout section to change the default unzipping policy ("unzip =
+ true").
+
+use-dependency-links
+ By default buildout will obey the setuptools dependency_links metadata
+ when it looks for dependencies. This behavior can be controlled with
+ the use-dependency-links buildout option::
+
+ [buildout]
+ ...
+ use-dependency-links = false
+
+ The option defaults to true. If you set it to false, then dependency
+ links are only looked for in the locations specified by find-links.
+
+verbosity
+ A log-level adjustment. Typically, this is set via the -q and -v
+ command-line options.
+
+
+Creating new buildouts and bootstrapping
+----------------------------------------
+
+If zc.buildout is installed, you can use it to create a new buildout
+with it's own local copies of zc.buildout and setuptools and with
+local buildout scripts.
+
+ >>> sample_bootstrapped = tmpdir('sample-bootstrapped')
+
+ >>> print system(buildout
+ ... +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg')
+ ... +' init'),
+ Creating '/sample-bootstrapped/setup.cfg'.
+ Creating directory '/sample-bootstrapped/bin'.
+ Creating directory '/sample-bootstrapped/parts'.
+ Creating directory '/sample-bootstrapped/eggs'.
+ Creating directory '/sample-bootstrapped/develop-eggs'.
+ Generated script '/sample-bootstrapped/bin/buildout'.
+
+Note that a basic setup.cfg was created for us.
+
+ >>> ls(sample_bootstrapped)
+ d bin
+ d develop-eggs
+ d eggs
+ d parts
+ - setup.cfg
+
+ >>> ls(sample_bootstrapped, 'bin')
+ - buildout
+
+ >>> _ = (ls(sample_bootstrapped, 'eggs'),
+ ... ls(sample_bootstrapped, 'develop-eggs'))
+ - setuptools-0.6-py2.3.egg
+ - zc.buildout-1.0-py2.3.egg
+
+(We list both the eggs and develop-eggs directories because the
+buildout or setuptools egg could be installed in the develop-eggs
+directory if the original buildout had develop eggs for either
+buildout or setuptools.)
+
+If relative-paths is ``true``, the buildout script uses relative paths.
+
+ >>> write(sample_bootstrapped, 'setup.cfg',
+ ... '''
+ ... [buildout]
+ ... relative-paths = true
+ ... parts =
+ ... ''')
+
+ >>> print system(buildout
+ ... +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg')
+ ... +' bootstrap'),
+ Generated script '/sample-bootstrapped/bin/buildout'.
+
+ >>> buildout_script = join(sample_bootstrapped, 'bin', 'buildout')
+ >>> import sys
+ >>> if sys.platform.startswith('win'):
+ ... buildout_script += '-script.py'
+ >>> print open(buildout_script).read() # doctest: +ELLIPSIS
+ #!... -S
+ <BLANKLINE>
+ import os
+ <BLANKLINE>
+ join = os.path.join
+ base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
+ base = os.path.dirname(base)
+ <BLANKLINE>
+ import sys
+ sys.path[0:0] = [
+ join(base, 'parts/buildout'),
+ ]
+ <BLANKLINE>
+ <BLANKLINE>
+ import os
+ path = sys.path[0]
+ if os.environ.get('PYTHONPATH'):
+ path = os.pathsep.join([path, os.environ['PYTHONPATH']])
+ os.environ['BUILDOUT_ORIGINAL_PYTHONPATH'] = os.environ.get('PYTHONPATH', '')
+ os.environ['PYTHONPATH'] = path
+ import site # imports custom buildout-generated site.py
+ <BLANKLINE>
+ import zc.buildout.buildout
+ <BLANKLINE>
+ if __name__ == '__main__':
+ zc.buildout.buildout.main()
+ <BLANKLINE>
+
+
+Note that, in the above two examples, the buildout script was installed
+but not run. To run the buildout, we'd have to run the installed
+buildout script.
+
+If we have an existing buildout that already has a buildout.cfg, we'll
+normally use the bootstrap command instead of init. It will complain
+if there isn't a configuration file:
+
+ >>> sample_bootstrapped2 = tmpdir('sample-bootstrapped2')
+
+ >>> print system(buildout
+ ... +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg')
+ ... +' bootstrap'),
+ While:
+ Initializing.
+ Error: Couldn't open /sample-bootstrapped2/setup.cfg
+
+ >>> write(sample_bootstrapped2, 'setup.cfg',
+ ... """
+ ... [buildout]
+ ... parts =
+ ... """)
+
+ >>> print system(buildout
+ ... +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg')
+ ... +' bootstrap'),
+ Creating directory '/sample-bootstrapped2/bin'.
+ Creating directory '/sample-bootstrapped2/parts'.
+ Creating directory '/sample-bootstrapped2/eggs'.
+ Creating directory '/sample-bootstrapped2/develop-eggs'.
+ Generated script '/sample-bootstrapped2/bin/buildout'.
+
+
+Newest and Offline Modes
+------------------------
+
+By default buildout and recipes will try to find the newest versions
+of distributions needed to satisfy requirements. This can be very
+time consuming, especially when incrementally working on setting up a
+buildout or working on a recipe. The buildout newest option can be
+used to to suppress this. If the newest option is set to false, then
+new distributions won't be sought if an installed distribution meets
+requirements. The newest option can be set to false using the -N
+command-line option.
+
+The offline option goes a bit further. If the buildout offline option
+is given a value of "true", the buildout and recipes that are aware of
+the option will avoid doing network access. This is handy when
+running the buildout when not connected to the internet. It also
+makes buildouts run much faster. This option is typically set using
+the buildout -o option.
+
+Preferring Final Releases
+-------------------------
+
+Currently, when searching for new releases of your project's
+dependencies, the newest available release is used. This isn't usually
+ideal, as you may get a development release or alpha releases not ready
+to be widely used. You can request that final releases be preferred
+using the ``prefer-final`` option in the buildout section::
+
+ [buildout]
+ ...
+ prefer-final = true
+
+When the ``prefer-final`` option is set to true, then when searching for
+new releases, final releases are preferred. If there are final
+releases that satisfy distribution requirements, then those releases
+are used even if newer non-final releases are available.
+
+In buildout version 2, all final releases will be preferred by
+default--that is ``prefer-final`` will also default to 'true'. You will
+then need to use a 'false' value for ``prefer-final`` to get the newest
+releases.
+
+A separate option controls the behavior of the build system itself.
+When buildout looks for recipes, extensions, and for updates to itself,
+it does prefer final releases by default, as of the 1.5.0 release. The
+``accept-buildout-test-releases`` option will let you override this behavior.
+However, it is typically changed by the --accept-buildout-test-releases
+option to the bootstrap script, since bootstrapping is the first step to
+selecting a buildout.
+
+Finding distributions
+---------------------
+
+By default, buildout searches the Python Package Index when looking
+for distributions. You can, instead, specify your own index to search
+using the `index` option::
+
+ [buildout]
+ ...
+ index = http://index.example.com/
+
+This index, or the default of http://pypi.python.org/simple/ if no
+index is specified, will always be searched for distributions unless
+running buildout with options that prevent searching for
+distributions. The latest version of the distribution that meets the
+requirements of the buildout will always be used.
+
+You can also specify more locations to search for distributions using
+the `find-links` option. All locations specified will be searched for
+distributions along with the package index as described before.
+
+Locations can be urls::
+
+ [buildout]
+ ...
+ find-links = http://download.zope.org/distribution/
+
+They can also be directories on disk::
+
+ [buildout]
+ ...
+ find-links = /some/path
+
+Finally, they can also be direct paths to distributions::
+
+ [buildout]
+ ...
+ find-links = /some/path/someegg-1.0.0-py2.3.egg
+
+Any number of locations can be specified in the `find-links` option::
+
+ [buildout]
+ ...
+ find-links =
+ http://download.zope.org/distribution/
+ /some/otherpath
+ /some/path/someegg-1.0.0-py2.3.egg
+
+Dependency links
+----------------
+
+By default buildout will obey the setuptools dependency_links metadata
+when it looks for dependencies. This behavior can be controlled with
+the use-dependency-links buildout option::
+
+ [buildout]
+ ...
+ use-dependency-links = false
+
+The option defaults to true. If you set it to false, then dependency
+links are only looked for in the locations specified by find-links.
+
+Controlling the installation database
+-------------------------------------
+
+The buildout installed option is used to specify the file used to save
+information on installed parts. This option is initialized to
+".installed.cfg", but it can be overridden in the configuration file
+or on the command line:
+
+ >>> write('buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = debug
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... """)
+
+ >>> print system(buildout+' buildout:installed=inst.cfg'),
+ Develop: '/sample-buildout/recipes'
+ Installing debug.
+ recipe recipes:debug
+
+ >>> ls(sample_buildout)
+ - b1.cfg
+ - b2.cfg
+ - base.cfg
+ d bin
+ - buildout.cfg
+ d demo
+ d develop-eggs
+ d eggs
+ - inst.cfg
+ d parts
+ d recipes
+
+The installation database can be disabled by supplying an empty
+buildout installed option:
+
+ >>> os.remove('inst.cfg')
+ >>> print system(buildout+' buildout:installed='),
+ Develop: '/sample-buildout/recipes'
+ Installing debug.
+ recipe recipes:debug
+
+ >>> ls(sample_buildout)
+ - b1.cfg
+ - b2.cfg
+ - base.cfg
+ d bin
+ - buildout.cfg
+ d demo
+ d develop-eggs
+ d eggs
+ d parts
+ d recipes
+
+
+Note that there will be no installation database if there are no parts:
+
+ >>> write('buildout.cfg',
+ ... """
+ ... [buildout]
+ ... parts =
+ ... """)
+
+ >>> print system(buildout+' buildout:installed=inst.cfg'),
+
+ >>> ls(sample_buildout)
+ - b1.cfg
+ - b2.cfg
+ - base.cfg
+ d bin
+ - buildout.cfg
+ d demo
+ d develop-eggs
+ d eggs
+ d parts
+ d recipes
+
+Extensions
+----------
+
+A feature allows code to be loaded and run after
+configuration files have been read but before the buildout has begun
+any processing. The intent is to allow special plugins such as
+urllib2 request handlers to be loaded.
+
+To load an extension, we use the extensions option and list one or
+more distribution requirements, on separate lines. The distributions
+named will be loaded and any ``zc.buildout.extension`` entry points found
+will be called with the buildout as an argument. When buildout
+finishes processing, any ``zc.buildout.unloadextension`` entry points
+found will be called with the buildout as an argument.
+
+Let's create a sample extension in our sample buildout created in the
+previous section:
+
+ >>> mkdir(sample_bootstrapped, 'demo')
+
+ >>> write(sample_bootstrapped, 'demo', 'demo.py',
+ ... """
+ ... def ext(buildout):
+ ... print 'ext', list(buildout)
+ ... def unload(buildout):
+ ... print 'unload', list(buildout)
+ ... """)
+
+ >>> write(sample_bootstrapped, 'demo', 'setup.py',
+ ... """
+ ... from setuptools import setup
+ ...
+ ... setup(
+ ... name = "demo",
+ ... entry_points = {
+ ... 'zc.buildout.extension': ['ext = demo:ext'],
+ ... 'zc.buildout.unloadextension': ['ext = demo:unload'],
+ ... },
+ ... )
+ ... """)
+
+Our extension just prints out the word 'demo', and lists the sections
+found in the buildout passed to it.
+
+We'll update our buildout.cfg to list the demo directory as a develop
+egg to be built:
+
+ >>> write(sample_bootstrapped, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = demo
+ ... parts =
+ ... """)
+
+ >>> os.chdir(sample_bootstrapped)
+ >>> print system(os.path.join(sample_bootstrapped, 'bin', 'buildout')),
+ Develop: '/sample-bootstrapped/demo'
+
+Now we can add the extensions option. We were a bit tricky and ran
+the buildout once with the demo develop egg defined but without the
+extension option. This is because extensions are loaded before the
+buildout creates develop eggs. We needed to use a separate buildout
+run to create the develop egg. Normally, when eggs are loaded from
+the network, we wouldn't need to do anything special.
+
+ >>> write(sample_bootstrapped, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = demo
+ ... extensions = demo
+ ... parts =
+ ... """)
+
+We see that our extension is loaded and executed:
+
+ >>> print system(os.path.join(sample_bootstrapped, 'bin', 'buildout')),
+ ext ['buildout']
+ Develop: '/sample-bootstrapped/demo'
+ unload ['buildout']
+
+Allow hosts
+-----------
+
+On some environments the links visited by `zc.buildout` can be forbidden
+by paranoiac firewalls. These URL might be on the chain of links
+visited by `zc.buildout` wheter they are defined in the `find-links` option,
+wheter they are defined by various eggs in their `url`, `download_url`,
+`dependency_links` metadata.
+
+It is even harder to track that package_index works like a spider and
+might visit links and go to other location.
+
+The `allow-hosts` option provides a way to prevent this, and
+works exactly like the one provided in `easy_install`.
+
+You can provide a list of allowed host, together with wildcards::
+
+ [buildout]
+ ...
+
+ allow-hosts =
+ *.python.org
+ example.com
+
+All urls that does not match these hosts will not be visited.
+
+.. [#future_recipe_methods] In the future, additional methods may be
+ added. Older recipes with fewer methods will still be
+ supported.
+
+.. [#packaging_info] If we wanted to create a distribution from this
+ package, we would need specify much more information. See the
+ `setuptools documentation
+ <http://peak.telecommunity.com/DevCenter/setuptools>`_.