[Checkins] SVN: zc.zope3recipes/tags/0.13.0/ tag release 0.13.0

Fred Drake fdrake at gmail.com
Wed Nov 24 12:23:54 EST 2010


Log message for revision 118572:
  tag release 0.13.0

Changed:
  A   zc.zope3recipes/tags/0.13.0/
  D   zc.zope3recipes/tags/0.13.0/README.txt
  A   zc.zope3recipes/tags/0.13.0/README.txt
  U   zc.zope3recipes/tags/0.13.0/setup.py
  D   zc.zope3recipes/tags/0.13.0/zc/zope3recipes/README.txt
  A   zc.zope3recipes/tags/0.13.0/zc/zope3recipes/README.txt
  D   zc.zope3recipes/tags/0.13.0/zc/zope3recipes/recipes.py
  A   zc.zope3recipes/tags/0.13.0/zc/zope3recipes/recipes.py

-=-
Deleted: zc.zope3recipes/tags/0.13.0/README.txt
===================================================================
--- zc.zope3recipes/trunk/README.txt	2010-11-24 16:02:02 UTC (rev 118564)
+++ zc.zope3recipes/tags/0.13.0/README.txt	2010-11-24 17:23:54 UTC (rev 118572)
@@ -1,125 +0,0 @@
-**************************************
-Zope3 Application and Instance Recipes
-**************************************
-
-Recipes for creating Zope 3 instances with distinguishing features:
-
-- Don't use a skeleton
-
-- Separates application and instance definition
-
-- Don't support package-includes
-
-Unfortunately, partial Windows support at this time. It works but it's alpha.
-
-.. contents::
-
-Releases
-********
-
-===================
-0.12.0 (2010/11/22)
-===================
-
-- Provide control for generation of the logrotate configuration, include the
-  ability to suppress it when not desired.
-
-===================
-0.11.1 (2010/11/12)
-===================
-
-- Added an environment hook to enable logging for debugzope
-
-===================
-0.11.0 (2009/10/01)
-===================
-
-- Added support and tests for relative paths buildout option.
-- Changed the dependency requirements to >=1.2.0 for zc.buildout and
-  zc.recipe.egg because relative paths are added in these releases.
-- Added missing release date for the previous release (0.10.0).
-
-===================
-0.10.0 (2009/09/16)
-===================
-
-Removed support for creating a logrotate script for the access.log because it
-is not possible to reopen the log with ZDaemons ``reopen_transacript``. Note
-however that is is possible to declare ``when`` and ``interval`` in a logfile
-section to rotate logfiles internally.
-
-
-==================
-0.9.0 (2009/07/21)
-==================
-
-Updated tests to work with latest package versions.
-
-==================
-0.8.0 (2009/04/03)
-==================
-
-Added the "newest=false" option in the SetUp to prevent upgrade during tests
-
-Added support for creating logrotate scripts when using a deployment recipe.
-
-==================
-0.7.0 (2008/02/01)
-==================
-
-Use the deployment name option (as provided by zc.recipe.deployment
-0.6.0 and later) if present when generating instance file names.
-
-You can now specify an instance name option that overrides the part
-name for generated files.
-
-==================
-0.6.1 (2007/12/17)
-==================
-
-Fixed bug: The zope.conf site-definition option could not be overridden.
-
-==================
-0.6.0 (2007/11/03)
-==================
-
-Final release with Windows support.
-
-==================
-0.6b1 (2007/08/21)
-==================
-
-Windows support was added.
-
-==================
-0.5.5 (2007/07/26)
-==================
-
-Now debugzope takes the servers key of the application into account.
-
-==================
-0.5.3 (2007/07/14)
-==================
-
-Created another recipe called 'application' that installs Zope 3
-solely from eggs.  The 'app' recipe is just an extension that also
-supports Zope 3 from checkout or tarball.
-
-==================
-0.5.2 (2007/06/21)
-==================
-
-Use ZConfig's schema-free configuration parsing gain support for
-%import.
-
-==================
-0.5.1 (2007/05/22)
-==================
-
-Support repeated keys in ZConfig sections.
-
-==================
-0.5.0 (2007/03/21)
-==================
-
-Support building Zope 3 application solely from eggs.

Copied: zc.zope3recipes/tags/0.13.0/README.txt (from rev 118571, zc.zope3recipes/trunk/README.txt)
===================================================================
--- zc.zope3recipes/tags/0.13.0/README.txt	                        (rev 0)
+++ zc.zope3recipes/tags/0.13.0/README.txt	2010-11-24 17:23:54 UTC (rev 118572)
@@ -0,0 +1,132 @@
+**************************************
+Zope3 Application and Instance Recipes
+**************************************
+
+Recipes for creating Zope 3 instances with distinguishing features:
+
+- Don't use a skeleton
+
+- Separates application and instance definition
+
+- Don't support package-includes
+
+Unfortunately, partial Windows support at this time. It works but it's alpha.
+
+.. contents::
+
+Releases
+********
+
+===================
+0.13.0 (2010/11/24)
+===================
+
+- Support inserting additional code into the runzope & debugzope scripts
+  using ``initialization`` and ``debug-initialization``.
+
+===================
+0.12.0 (2010/11/22)
+===================
+
+- Provide control for generation of the logrotate configuration, include the
+  ability to suppress it when not desired.
+
+===================
+0.11.1 (2010/11/12)
+===================
+
+- Added an environment hook to enable logging for debugzope
+
+===================
+0.11.0 (2009/10/01)
+===================
+
+- Added support and tests for relative paths buildout option.
+- Changed the dependency requirements to >=1.2.0 for zc.buildout and
+  zc.recipe.egg because relative paths are added in these releases.
+- Added missing release date for the previous release (0.10.0).
+
+===================
+0.10.0 (2009/09/16)
+===================
+
+Removed support for creating a logrotate script for the access.log because it
+is not possible to reopen the log with ZDaemons ``reopen_transacript``. Note
+however that is is possible to declare ``when`` and ``interval`` in a logfile
+section to rotate logfiles internally.
+
+
+==================
+0.9.0 (2009/07/21)
+==================
+
+Updated tests to work with latest package versions.
+
+==================
+0.8.0 (2009/04/03)
+==================
+
+Added the "newest=false" option in the SetUp to prevent upgrade during tests
+
+Added support for creating logrotate scripts when using a deployment recipe.
+
+==================
+0.7.0 (2008/02/01)
+==================
+
+Use the deployment name option (as provided by zc.recipe.deployment
+0.6.0 and later) if present when generating instance file names.
+
+You can now specify an instance name option that overrides the part
+name for generated files.
+
+==================
+0.6.1 (2007/12/17)
+==================
+
+Fixed bug: The zope.conf site-definition option could not be overridden.
+
+==================
+0.6.0 (2007/11/03)
+==================
+
+Final release with Windows support.
+
+==================
+0.6b1 (2007/08/21)
+==================
+
+Windows support was added.
+
+==================
+0.5.5 (2007/07/26)
+==================
+
+Now debugzope takes the servers key of the application into account.
+
+==================
+0.5.3 (2007/07/14)
+==================
+
+Created another recipe called 'application' that installs Zope 3
+solely from eggs.  The 'app' recipe is just an extension that also
+supports Zope 3 from checkout or tarball.
+
+==================
+0.5.2 (2007/06/21)
+==================
+
+Use ZConfig's schema-free configuration parsing gain support for
+%import.
+
+==================
+0.5.1 (2007/05/22)
+==================
+
+Support repeated keys in ZConfig sections.
+
+==================
+0.5.0 (2007/03/21)
+==================
+
+Support building Zope 3 application solely from eggs.

Modified: zc.zope3recipes/tags/0.13.0/setup.py
===================================================================
--- zc.zope3recipes/trunk/setup.py	2010-11-24 16:02:02 UTC (rev 118564)
+++ zc.zope3recipes/tags/0.13.0/setup.py	2010-11-24 17:23:54 UTC (rev 118572)
@@ -7,7 +7,7 @@
 name = "zc.zope3recipes"
 setup(
     name = name,
-    version = '0',
+    version = '0.13.0',
     author = "Jim Fulton",
     author_email = "jim at zope.com",
     description = "ZC Buildout recipe for defining Zope 3 applications",

Deleted: zc.zope3recipes/tags/0.13.0/zc/zope3recipes/README.txt
===================================================================
--- zc.zope3recipes/trunk/zc/zope3recipes/README.txt	2010-11-24 16:02:02 UTC (rev 118564)
+++ zc.zope3recipes/tags/0.13.0/zc/zope3recipes/README.txt	2010-11-24 17:23:54 UTC (rev 118572)
@@ -1,2280 +0,0 @@
-=============
-Zope3 Recipes
-=============
-
-The Zope 3 recipes allow one to define Zope applications and instances
-of those applications.  A Zope application is a collection of software
-and software configuration, expressed as ZCML.  A Zope instance
-invokes the application with a specific instance configuration.  A
-single application may have many instances.
-
-Building Zope 3 applications (from eggs)
-========================================
-
-The 'application' recipe can be used to define a Zope application.  It
-is designed to work with with Zope solely from eggs.  The app recipe
-causes a part to be created. The part will contain the scripts runzope
-and debugzope and the application's site.zcml.  Both of the scripts
-will require providing a -C option and the path to a zope.conf file
-when run.  The debugzope script can be run with a script name and
-arguments, in which case it will run the script, rather than starting
-an interactive session.
-
-The 'application' recipe accepts the following options:
-
-site.zcml
-  The contents of site.zcml.
-
-eggs
-  The names of one or more eggs, with their dependencies that should
-  be included in the Python path of the generated scripts.
-
-
-Lets define some (bogus) eggs that we can use in our application:
-
-    >>> mkdir('demo1')
-    >>> write('demo1', 'setup.py',
-    ... '''
-    ... from setuptools import setup
-    ... setup(name = 'demo1')
-    ... ''')
-
-    >>> mkdir('demo2')
-    >>> write('demo2', 'setup.py',
-    ... '''
-    ... from setuptools import setup
-    ... setup(name = 'demo2', install_requires='demo1')
-    ... ''')
-
-.. Please note that the "newest=false" option is set in the test SetUp to
-   prevent upgrades
-
-We'll create a buildout.cfg file that defines our application:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = myapp
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:application
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ... ''' % globals())
-
-Now, Let's run the buildout and see what we get:
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-
-The runzope script runs the Web server:
-
-    >>> cat('parts', 'myapp', 'runzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      '/sample-buildout/demo2',
-      '/sample-buildout/demo1',
-      ]
-    <BLANKLINE>
-    import zope.app.twisted.main
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zope.app.twisted.main.main()
-
-Here, unlike the above example the location path is not included
-in sys.path .  Similarly debugzope script is also changed:
-
-    >>> cat('parts', 'myapp', 'debugzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      '/sample-buildout/demo2',
-      '/sample-buildout/demo1',
-      '/zope3recipes',
-      ]
-    <BLANKLINE>
-    import zope.app.twisted.main
-    <BLANKLINE>
-    <BLANKLINE>
-    import zc.zope3recipes.debugzope
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)
-
-
-Relative paths
---------------
-
-If requested in a buildout configuration, the scripts will be generated
-with relative paths instead of absolute.
-
-Let's change a buildout configuration to include ``relative-paths``.
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = myapp
-    ... relative-paths = true
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:application
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling myapp.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-
-We get runzope script with relative paths.
-
-    >>> cat('parts', 'myapp', 'runzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import os
-    <BLANKLINE>
-    join = os.path.join
-    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
-    base = os.path.dirname(base)
-    base = os.path.dirname(base)
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      join(base, 'demo2'),
-      join(base, 'demo1'),
-      ]
-    <BLANKLINE>
-    import zope.app.twisted.main
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zope.app.twisted.main.main()
-
-Similarly, debugzope script has relative paths.
-
-    >>> cat('parts', 'myapp', 'debugzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import os
-    <BLANKLINE>
-    join = os.path.join
-    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
-    base = os.path.dirname(base)
-    base = os.path.dirname(base)
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      join(base, 'demo2'),
-      join(base, 'demo1'),
-      '/zope3recipes',
-      ]
-    <BLANKLINE>
-    import zope.app.twisted.main
-    <BLANKLINE>
-    <BLANKLINE>
-    import zc.zope3recipes.debugzope
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)
-
-
-Building Zope 3 Applications (from Zope 3 checkouts/tarballs)
-=============================================================
-
-The 'app' recipe works much like the 'application' recipe.  It takes
-the same configuration options plus the following one:
-
-zope3
-  The name of a section defining a location option that gives the
-  location of a Zope installation.  This can be either a checkout or a
-  distribution.  If the location has a lib/python subdirectory, it is
-  treated as a distribution, otherwise, it must have a src
-  subdirectory and will be treated as a checkout. This option defaults
-  to "zope3".  And if location is empty, the application will run solely
-  from eggs.
-
-Let's look at an example.  We'll make a faux zope installation:
-
-    >>> zope3 = tmpdir('zope3')
-    >>> mkdir(zope3, 'src')
-
-Now we'll create a buildout.cfg file that defines our application:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = myapp
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ... ''' % globals())
-
-Note that our site.zcml file is very small.  It expect the application
-zcml to define almost everything.  In fact, a site.zcml file will often
-include just a single include directive.  We don't need to include the
-surrounding configure element, unless we want a namespace other than
-the zope namespace.  A configure directive will be included for us.
-
-Let's run the buildout and see what we get:
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling myapp.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-
-A directory is created in the parts directory for our application files:
-
-    >>> ls('parts')
-    d  myapp
-
-    >>> ls('parts', 'myapp')
-    -  debugzope
-    -  runzope
-    -  site.zcml
-
-We get 3 files, two scripts and a site.zcml file.  The site.zcml file
-is just what we had in the buildout configuration:
-
-    >>> cat('parts', 'myapp', 'site.zcml')
-    <configure xmlns='http://namespaces.zope.org/zope'
-               xmlns:meta="http://namespaces.zope.org/meta"
-               >
-    <include package="demo2" />
-    <principal
-    id="zope.manager"
-    title="Manager"
-    login="jim"
-    password_manager="SHA1"
-    password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    />
-    <grant
-    role="zope.Manager"
-    principal="zope.manager"
-    />
-    </configure>
-
-Unfortunately, the leading whitespace is stripped from the
-configuration file lines.  This is a consequence of the way
-ConfigParser works.
-
-The runzope script runs the Web server:
-
-    >>> cat('parts', 'myapp', 'runzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      '/sample-buildout/demo2',
-      '/sample-buildout/demo1',
-      '/zope3/src',
-      ]
-    <BLANKLINE>
-    import zope.app.twisted.main
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zope.app.twisted.main.main()
-
-It includes in it's path the eggs we specified in the configuration
-file, along with their dependencies. Note that we haven't specified a
-configuration file.  When runzope is run, a -C option must be used to
-provide a configuration file.  -X options can also be provided to
-override configuration file options.
-
-The debugzope script provides access to the object system.  When
-debugzope is run, a -C option must be used to provide a configuration
-file.  -X options can also be provided to override configuration file
-options.  If run without any additional arguments, then an interactive
-interpreter will be started with databases specified in the
-configuration file opened and with the variable root set to the
-application root object.  The debugger variable is set to a Zope 3
-debugger.  If additional arguments are provided, then the first
-argument should be a script name and the remaining arguments are
-script arguments.  The script will be run with the root and debugger
-variables available as global variables.
-
-..
-
-    >>> cat('parts', 'myapp', 'debugzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      '/sample-buildout/demo2',
-      '/sample-buildout/demo1',
-      '/zope3/src',
-      '/zope3recipes',
-      ]
-    <BLANKLINE>
-    import zope.app.twisted.main
-    <BLANKLINE>
-    <BLANKLINE>
-    import zc.zope3recipes.debugzope
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)
-
-Note that the runzope shown above uses the default, twisted-based
-server components.  It's possible to specify which set of server
-components is used: the "servers" setting can be set to either
-"zserver" or "twisted".  For the application, this affects the runzope
-script; we'll see additional differences when we create instances of
-the application.
-
-Let's continue to use the twisted servers, but make the selection
-explicit:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = myapp
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... servers = twisted
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Updating myapp.
-
-Note that this is recognized as not being a change to the
-configuration; the messages say that myapp was updated, not
-uninstalled and then re-installed.
-
-The runzope script generated is identical to what we saw before:
-
-    >>> cat('parts', 'myapp', 'runzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      '/sample-buildout/demo2',
-      '/sample-buildout/demo1',
-      '/zope3/src',
-      ]
-    <BLANKLINE>
-    import zope.app.twisted.main
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zope.app.twisted.main.main()
-
-We can also specify the ZServer servers explicitly:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = myapp
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... servers = zserver
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling myapp.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-
-The part has been re-installed, and the runzope script generated is
-different now.  Note that the main() function is imported from a
-different package this time:
-
-    >>> cat('parts', 'myapp', 'runzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      '/sample-buildout/demo2',
-      '/sample-buildout/demo1',
-      '/zope3/src',
-      ]
-    <BLANKLINE>
-    import zope.app.server.main
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zope.app.server.main.main()
-
-The debugzope script has also been modified to take this into account.
-
-    >>> cat('parts', 'myapp', 'debugzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      '/sample-buildout/demo2',
-      '/sample-buildout/demo1',
-      '/zope3/src',
-      '/zope3recipes',
-      ]
-    <BLANKLINE>
-    import zope.app.server.main
-    <BLANKLINE>
-    <BLANKLINE>
-    import zc.zope3recipes.debugzope
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zc.zope3recipes.debugzope.debug(main_module=zope.app.server.main)
-
-
-Relative paths
---------------
-
-We can also request relative paths.
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = myapp
-    ... relative-paths = true
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... servers = zserver
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling myapp.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-
-The runzope script has relative paths.
-
-    >>> cat('parts', 'myapp', 'runzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import os
-    <BLANKLINE>
-    join = os.path.join
-    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
-    base = os.path.dirname(base)
-    base = os.path.dirname(base)
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      join(base, 'demo2'),
-      join(base, 'demo1'),
-      '/zope3/src',
-      ]
-    <BLANKLINE>
-    import zope.app.server.main
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zope.app.server.main.main()
-
-The debugzope script also has relative paths.
-
-    >>> cat('parts', 'myapp', 'debugzope')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import os
-    <BLANKLINE>
-    join = os.path.join
-    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
-    base = os.path.dirname(base)
-    base = os.path.dirname(base)
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      join(base, 'demo2'),
-      join(base, 'demo1'),
-      '/zope3/src',
-      '/zope3recipes',
-      ]
-    <BLANKLINE>
-    import zope.app.server.main
-    <BLANKLINE>
-    <BLANKLINE>
-    import zc.zope3recipes.debugzope
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zc.zope3recipes.debugzope.debug(main_module=zope.app.server.main)
-
-
-Legacy Functional Testing Support
----------------------------------
-
-Zope 3's functional testing support is based on zope.testing test
-layers. There is a default functional test layer that older functional
-tests use.  This layer loads the default configuration for the Zope
-application server.  It exists to provide support for older functional
-tests that were written before layers were added to the testing
-infrastructure.   The default testing layer has a number of
-disadvantages:
-
-- It loads configurations for a large number of packages.  This has
-  the potential to introduce testing dependency on all of these
-  packages.
-
-- It required a ftesting.zcml file and makes assumptions about where
-  that file is.  In particular, it assumes a location relative to the
-  current working directory when the test is run.
-
-Newer software and maintained software should use their own functional
-testing layers that use test-configuration files defined in packages.
-
-To support older packages that use the default layer, a ftesting.zcml
-option is provided.  If it is used, then the contents of the option
-are written to a ftesting.zcml file in the application.  In addition,
-an ftesting-base.zcml file is written that includes configuration
-traditionally found in a Zope 3 ftesting-base.zcml excluding reference
-to package-includes.
-
-If we modify our buildout to include an ftesting.zcml option:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = myapp
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... ftesting.zcml =
-    ...    <meta:provides feature="devmode" />
-    ...    <include file="ftesting-base.zcml" />
-    ...    <includeOverrides package="demo2" />
-    ... eggs = demo2
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling myapp.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-
-We'll get ftesting.zcml files and ftesting-base.zcml files created in
-the application:
-
-    >>> cat('parts', 'myapp', 'ftesting.zcml')
-    <configure xmlns='http://namespaces.zope.org/zope'
-               xmlns:meta="http://namespaces.zope.org/meta"
-               >
-    <BLANKLINE>
-    <meta:provides feature="devmode" />
-    <include file="ftesting-base.zcml" />
-    <includeOverrides package="demo2" />
-    </configure>
-
-    >>> cat('parts', 'myapp', 'ftesting-base.zcml')
-    <BLANKLINE>
-    <configure
-       xmlns="http://namespaces.zope.org/zope"
-       i18n_domain="zope"
-       >
-      <include package="zope.app" />
-      <include package="zope.app" file="ftesting.zcml" />
-      <include package="zope.app.securitypolicy" file="meta.zcml" />
-      <include package="zope.app.securitypolicy" />
-      <securityPolicy
-        component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
-      <role id="zope.Anonymous" title="Everybody"
-                     description="All users have this role implicitly" />
-      <role id="zope.Manager" title="Site Manager" />
-      <role id="zope.Member" title="Site Member" />
-      <grant permission="zope.View"
-                      role="zope.Anonymous" />
-      <grant permission="zope.app.dublincore.view"
-                      role="zope.Anonymous" />
-      <grantAll role="zope.Manager" />
-      <include package="zope.app.securitypolicy.tests"
-               file="functional.zcml" />
-      <unauthenticatedPrincipal
-          id="zope.anybody"
-          title="Unauthenticated User"
-          />
-      <unauthenticatedGroup
-        id="zope.Anybody"
-        title="Unauthenticated Users"
-        />
-      <authenticatedGroup
-        id="zope.Authenticated"
-        title="Authenticated Users"
-        />
-      <everybodyGroup
-        id="zope.Everybody"
-        title="All Users"
-        />
-      <principal
-          id="zope.mgr"
-          title="Manager"
-          login="mgr"
-          password="mgrpw" />
-      <principal
-          id="zope.globalmgr"
-          title="Manager"
-          login="globalmgr"
-          password="globalmgrpw" />
-      <grant role="zope.Manager" principal="zope.globalmgr" />
-    </configure>
-
-Defining Zope3 instances
-========================
-
-Having defined an application, we can define one or more instances of
-the application.  We do this using the zc.zope3recipes instance
-recipe.  The instance recipe has 2 modes, a development and a
-production mode.  We'll start with the development mode.  In
-development mode, a part directory will be created for each instance
-containing the instance's configuration files. This directory will
-also contain run-time files created by the instances, such as log
-files or zdaemon socket files.
-
-When defining an instance, we need to specify a zope.conf file.  The
-recipe can do most of the work for us.  Let's look at a a basic
-example:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ... ''' % globals())
-
-The application option names an application part.  The application
-part will be used to determine the location of the site.zcml file and
-the name of the control script to run.
-
-We specified a zope.conf option which contains a start at our final
-zope.conf file.  The recipe will add some bits we leave out.  The one
-thing we really need to have is a database definition.  We simply
-include the zconfig option from the database section, which we provide
-as a file storage part using the zc.recipe.filestorage recipe.  The
-filestorage recipe will create a directory to hold our database and
-compute a zconfig option that we can use in our instance section.
-
-Note that we've replaced the myapp part with the instance part.  The
-myapp part will be included by virtue of the reference from the
-instance part.
-
-Let's run the buildout, and see what we get:
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling myapp.
-    Installing database.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-We see that the database and myapp parts were included by virtue of
-being referenced from the instance part.
-
-We get new directories for our database and instance:
-
-    >>> ls('parts')
-    d  database
-    d  instance
-    d  myapp
-
-The instance directory contains zdaemon.conf and zope.conf files:
-
-    >>> ls('parts', 'instance')
-    -  zdaemon.conf
-    -  zope.conf
-
-Let's look at the zope.conf file that was generated:
-
-    >>> cat('parts', 'instance', 'zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <filestorage>
-        path /sample-buildout/parts/database/Data.fs
-      </filestorage>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8080
-      type HTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /sample-buildout/parts/instance/access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-This uses the twisted server types, since that's the default
-configuration for Zope 3.  If we specify use of the ZServer servers,
-the names of the server types are adjusted appropriately:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... servers = zserver
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Uninstalling myapp.
-    Updating database.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-The generated zope.conf file now uses the ZServer server components
-instead:
-
-    >>> cat('parts', 'instance', 'zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <filestorage>
-        path /sample-buildout/parts/database/Data.fs
-      </filestorage>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8080
-      type WSGI-HTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /sample-buildout/parts/instance/access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-The Twisted-based servers can also be specified explicitly:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... servers = twisted
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Uninstalling myapp.
-    Updating database.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-The generated zope.conf file now uses the Twisted server components
-once more:
-
-    >>> cat('parts', 'instance', 'zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <filestorage>
-        path /sample-buildout/parts/database/Data.fs
-      </filestorage>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8080
-      type HTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /sample-buildout/parts/instance/access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-It includes the database definition that we provided in the zope.conf
-option.  It has a site-definition option that names the site.zcml file
-from our application directory.
-
-We didn't specify any server or logging ZConfig sections, so some were
-generated for us.
-
-Note that, by default, the event-log output goes to standard output.
-We'll say more about that when we talk about the zdaemon
-configuration later.
-
-If we specify a server section ourselves:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ...    <server>
-    ...        type PostmortemDebuggingHTTP
-    ...        address 8080
-    ...    </server>
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Updating database.
-    Updating myapp.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-Then the section (or sections) we provide will be used and new ones
-won't be added:
-
-    >>> cat('parts', 'instance', 'zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <filestorage>
-        path /sample-buildout/parts/database/Data.fs
-      </filestorage>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8080
-      type PostmortemDebuggingHTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /sample-buildout/parts/instance/access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-If we just want to specify alternate ports or addresses, we can use
-the address option which accepts zero or more address specifications:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ... address = 8081 foo.com:8082
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Updating database.
-    Updating myapp.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-    >>> cat('parts', 'instance', 'zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <filestorage>
-        path /sample-buildout/parts/database/Data.fs
-      </filestorage>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8081
-      type HTTP
-    </server>
-    <BLANKLINE>
-    <server>
-      address foo.com:8082
-      type HTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /sample-buildout/parts/instance/access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-We can specify our own accesslog and eventlog configuration.  For
-example, to send the event-log output to a file and suppress the
-access log:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ...    <eventlog>
-    ...      <logfile>
-    ...        path ${buildout:parts-directory}/instance/event.log
-    ...        formatter zope.exceptions.log.Formatter
-    ...      </logfile>
-    ...    </eventlog>
-    ...    <accesslog>
-    ...    </accesslog>
-    ...
-    ... address = 8081
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Updating database.
-    Updating myapp.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-    >>> cat('parts', 'instance', 'zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <filestorage>
-        path /sample-buildout/parts/database/Data.fs
-      </filestorage>
-    </zodb>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path /sample-buildout/parts/instance/event.log
-      </logfile>
-    </eventlog>
-    <BLANKLINE>
-    <accesslog>
-    </accesslog>
-    <BLANKLINE>
-    <server>
-      address 8081
-      type HTTP
-    </server>
-
-Let's look at the zdaemon.conf file:
-
-    >>> cat('parts', 'instance', 'zdaemon.conf')
-    <runner>
-      daemon on
-      directory /sample-buildout/parts/instance
-      program /sample-buildout/parts/myapp/runzope -C /sample-buildout/parts/instance/zope.conf
-      socket-name /sample-buildout/parts/instance/zdaemon.sock
-      transcript /sample-buildout/parts/instance/z3.log
-    </runner>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        path /sample-buildout/parts/instance/z3.log
-      </logfile>
-    </eventlog>
-
-Here we see a fairly ordinary zdaemon.conf file.  The program option
-refers to the runzope script in our application directory.  The socket
-file, used for communication between the zdaemon command-line script
-and the zademon manager is placed in the instance directory.
-
-If you want to override any part of the generated zdaemon output,
-simply provide a zdaemon.conf option in your instance section:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ... address = 8081
-    ... zdaemon.conf =
-    ...     <runner>
-    ...       daemon off
-    ...       socket-name /sample-buildout/parts/instance/sock
-    ...       transcript /dev/null
-    ...     </runner>
-    ...     <eventlog>
-    ...     </eventlog>
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Updating database.
-    Updating myapp.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-    >>> cat('parts', 'instance', 'zdaemon.conf')
-    <runner>
-      daemon off
-      directory /sample-buildout/parts/instance
-      program /sample-buildout/parts/myapp/runzope -C /sample-buildout/parts/instance/zope.conf
-      socket-name /sample-buildout/parts/instance/sock
-      transcript /dev/null
-    </runner>
-    <BLANKLINE>
-    <eventlog>
-    </eventlog>
-
-In addition to the configuration files, a control script is generated
-in the buildout bin directory:
-
-    >>> ls('bin')
-    -  buildout
-    -  instance
-
-..
-
-    >>> cat('bin', 'instance')
-    #!/usr/local/bin/python2.4
-    <BLANKLINE>
-    import sys
-    sys.path[0:0] = [
-      '/sample-buildout/eggs/zdaemon-2.0-py2.4.egg',
-      '/sample-buildout/eggs/setuptools-0.6-py2.4.egg',
-      '/sample-buildout/eggs/ZConfig-2.3-py2.4.egg',
-      '/zope3recipes',
-      ]
-    <BLANKLINE>
-    import zc.zope3recipes.ctl
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zc.zope3recipes.ctl.main([
-            '/sample-buildout/parts/myapp/debugzope',
-            '/sample-buildout/parts/instance/zope.conf',
-            '-C', '/sample-buildout/parts/instance/zdaemon.conf',
-            ]+sys.argv[1:]
-            )
-
-Some configuration sections can include a key multiple times; the ZEO
-client section works this way.  When a key is given multiple times,
-all values are included in the resulting configuration in the order in
-which they're give in the input::
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf =
-    ...     <zodb>
-    ...       <zeoclient>
-    ...         server 127.0.0.1:8001
-    ...         server 127.0.0.1:8002
-    ...       </zeoclient>
-    ...     </zodb>
-    ... address = 8081
-    ... zdaemon.conf =
-    ...     <runner>
-    ...       daemon off
-    ...       socket-name /sample-buildout/parts/instance/sock
-    ...       transcript /dev/null
-    ...     </runner>
-    ...     <eventlog>
-    ...     </eventlog>
-    ...
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Uninstalling database.
-    Updating myapp.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-    >>> cat('parts', 'instance', 'zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <zeoclient>
-        server 127.0.0.1:8001
-        server 127.0.0.1:8002
-      </zeoclient>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8081
-      type HTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /sample-buildout/parts/instance/access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-Instance names
---------------
-
-The instance recipe generates files or directories based on its name,
-which defaults to the part name.  We can specify a different name
-using the name option.  This doesn't effect which parts directory is
-used, but it does affect the name of the run script in bin:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... name = server
-    ... application = myapp
-    ... zope.conf =
-    ...     <zodb>
-    ...       <zeoclient>
-    ...         server 127.0.0.1:8001
-    ...         server 127.0.0.1:8002
-    ...       </zeoclient>
-    ...     </zodb>
-    ... address = 8081
-    ... zdaemon.conf =
-    ...     <runner>
-    ...       daemon off
-    ...       socket-name /sample-buildout/parts/instance/sock
-    ...       transcript /dev/null
-    ...     </runner>
-    ...     <eventlog>
-    ...     </eventlog>
-    ...
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Updating myapp.
-    Installing instance.
-    Generated script '/sample-buildout/bin/server'.
-
-
-Specifying an alternate site definition
----------------------------------------
-
-Ideally, ZCML is used to configure the software used by an application
-and zope.conf is used to provide instance-specific configuration.  For
-historical reasons, there are ZCML directives that provide process
-configuration.  A good example of this is the smtpMailer directive
-provided by the zope.sendmail package.  We can override the
-site-definition option in the zope.conf file to specify an alternate
-zcml file.  Here, we'll update out instance configuration to use an
-alternate site definition:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf =
-    ...     site-definition ${buildout:directory}/site.zcml
-    ...     <zodb>
-    ...       <zeoclient>
-    ...         server 127.0.0.1:8001
-    ...         server 127.0.0.1:8002
-    ...       </zeoclient>
-    ...     </zodb>
-    ... address = 8081
-    ... zdaemon.conf =
-    ...     <runner>
-    ...       daemon off
-    ...       socket-name /sample-buildout/parts/instance/sock
-    ...       transcript /dev/null
-    ...     </runner>
-    ...     <eventlog>
-    ...     </eventlog>
-    ...
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Updating myapp.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-    >>> cat('parts', 'instance', 'zope.conf')
-    site-definition /sample-buildout/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <zeoclient>
-        server 127.0.0.1:8001
-        server 127.0.0.1:8002
-      </zeoclient>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8081
-      type HTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /sample-buildout/parts/instance/access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-(Note that, in practice, you'll often use the
-zc.recipe.deployment:configuration recipe,
-http://pypi.python.org/pypi/zc.recipe.deployment#configuration-files,
-to define a site.zcml file using the buildout.)
-
-Log files
----------
-
-The log file settings deserver some explanation.  The Zope event log
-only captures output from logging calls.  In particular, it doesn't
-capture startup errors written to standard error.  The zdaemon
-transcript log is very useful for capturing this output.  Without it,
-error written to standard error are lost when running as a daemon.
-The default Zope 3 configuration in the past was to write the Zope
-access and event log output to both files and standard output and to
-define a transcript log.  This had the effect that the transcript
-duplicated the contents of the event log and access logs, in addition
-to capturing other output.  This was space inefficient.
-
-This recipe's approach is to combine the zope and zdaemon event-log
-information as well as Zope error output into a single log file.  We
-do this by directing Zope's event log to standard output, where it is
-useful when running Zope in foreground mode and where it can be
-captured by the zdaemon transcript log.
-
-Unix Deployments
-----------------
-
-The instance recipe provides support for Unix deployments, as provided
-by the zc.recipe.deployment recipe.  A deployment part defines a number of
-options used by the instance recipe:
-
-etc-directory
-    The name of the directory where configuration files should be
-    placed.  This defaults to /etc/NAME, where NAME is the deployment
-    name.
-
-log-directory
-    The name of the directory where application instances should write
-    their log files.  This defaults to /var/log/NAME, where NAME is
-    the deployment name.
-
-run-directory
-    The name of the directory where application instances should put
-    their run-time files such as pid files and inter-process
-    communication socket files.  This defaults to /var/run/NAME, where
-    NAME is the deployment name.
-
-rc-directory
-    The name of the directory where run-control scripts should be
-    installed.
-
-logrotate-directory
-    The name ot the directory where logrotate configuration files should be
-    installed.
-    
-user
-    The name of a user that processes should run as.
-
-The deployment recipe has to be run as root for various reasons, but
-we can create a faux deployment by providing a section with the needed
-data. Let's update our configuration to use a deployment.  We'll first
-create a faux installation root:
-
-    >>> root = tmpdir('root')
-    >>> mkdir(root, 'etc')
-    >>> mkdir(root, 'etc', 'myapp-run')
-    >>> mkdir(root, 'etc', 'init.d')
-    >>> mkdir(root, 'etc', 'logrotate.d')
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ... address = 8081
-    ... deployment = myapp-deployment
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ...
-    ... [myapp-deployment]
-    ... name = myapp-run
-    ... etc-directory = %(root)s/etc/myapp-run
-    ... rc-directory = %(root)s/etc/init.d
-    ... logrotate-directory = %(root)s/etc/logrotate.d
-    ... log-directory = %(root)s/var/log/myapp-run
-    ... run-directory = %(root)s/var/run/myapp-run
-    ... user = zope
-    ... ''' % globals())
-
-Here we've added a deployment section, myapp-deployment, and added a
-deployment option to our instance part telling the instance recipe to
-use the deployment.  If we rerun the buildout:
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Installing database.
-    Updating myapp.
-    Installing instance.
-    Generated script '/root/etc/init.d/myapp-run-instance'.
-
-The installer files will move.  We'll no-longer have the instance part:
-
-    >>> ls('parts')
-    d  database
-    d  myapp
-
-or the control script:
-
-    >>> ls('bin')
-    -  buildout
-
-Rather, we'll get our configuration files in the /etc/myapp-run directory:
-
-    >>> ls(root, 'etc', 'myapp-run')
-    -  instance-zdaemon.conf
-    -  instance-zope.conf
-
-Note that the instance name was added as a prefix to the file names,
-since we'll typically have additional instances in the deployment.
-
-The control script is in the init.d directory:
-
-    >>> ls(root, 'etc', 'init.d')
-    -  myapp-run-instance
-
-Note that the deployment name is added as a prefix of the control
-script name.
-
-The logrotate file is in the logrotate.d directory:
-
-    >>> ls(root, 'etc', 'logrotate.d')
-    -  myapp-run-instance
-
-
-The configuration files have changed to reflect the deployment
-locations:
-
-    >>> cat(root, 'etc', 'myapp-run', 'instance-zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <filestorage>
-        path /sample-buildout/parts/database/Data.fs
-      </filestorage>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8081
-      type HTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /root/var/log/myapp-run/instance-access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-    >>> cat(root, 'etc', 'myapp-run', 'instance-zdaemon.conf')
-    <runner>
-      daemon on
-      directory /root/var/run/myapp-run
-      program /sample-buildout/parts/myapp/runzope -C /root/etc/myapp-run/instance-zope.conf
-      socket-name /root/var/run/myapp-run/instance-zdaemon.sock
-      transcript /root/var/log/myapp-run/instance-z3.log
-      user zope
-    </runner>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        path /root/var/log/myapp-run/instance-z3.log
-      </logfile>
-    </eventlog>
-
-    >>> cat(root, 'etc', 'logrotate.d', 'myapp-run-instance')
-    /root/var/log/myapp-run/instance-z3.log {
-      rotate 5
-      weekly
-      postrotate
-        /root/etc/init.d/myapp-run-instance reopen_transcript
-      endscript
-    }
-    
-
-If we provide an alternate instance name, that will be reflected in
-the generated files:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... name = server
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ... address = 8081
-    ... deployment = myapp-deployment
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ...
-    ... [myapp-deployment]
-    ... name = myapp-run
-    ... etc-directory = %(root)s/etc/myapp-run
-    ... rc-directory = %(root)s/etc/init.d
-    ... logrotate-directory = %(root)s/etc/logrotate.d
-    ... log-directory = %(root)s/var/log/myapp-run
-    ... run-directory = %(root)s/var/run/myapp-run
-    ... user = zope
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Updating database.
-    Updating myapp.
-    Installing instance.
-    Generated script '/root/etc/init.d/myapp-run-server'.
-
-    >>> cat(root, 'etc', 'myapp-run', 'server-zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <filestorage>
-        path /sample-buildout/parts/database/Data.fs
-      </filestorage>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8081
-      type HTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /root/var/log/myapp-run/server-access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-    >>> cat(root, 'etc', 'myapp-run', 'server-zdaemon.conf')
-    <runner>
-      daemon on
-      directory /root/var/run/myapp-run
-      program /sample-buildout/parts/myapp/runzope -C /root/etc/myapp-run/server-zope.conf
-      socket-name /root/var/run/myapp-run/server-zdaemon.sock
-      transcript /root/var/log/myapp-run/server-z3.log
-      user zope
-    </runner>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        path /root/var/log/myapp-run/server-z3.log
-      </logfile>
-    </eventlog>
-
-
-Controlling logrotate configuration
------------------------------------
-
-Some applications control their own log rotation policies.  In these
-cases, we don't want the logrotate configuration to be generated.
-
-Setting the logrotate.conf setting affects the configuration.  Setting
-it explicitly controls the content of the logrotate file for the
-instance; setting it to an empty string causes it not to be generated at
-all.
-
-Let's take a look at setting the content to a non-empty value directly:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ... address = 8081
-    ... deployment = myapp-deployment
-    ... logrotate.conf =
-    ...       /root/var/log/myapp-run/instance-z3.log {
-    ...         rotate 10
-    ...         daily
-    ...         postrotate
-    ...           /root/etc/init.d/myapp-run-instance reopen_transcript
-    ...         endscript
-    ...       }
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ...
-    ... [myapp-deployment]
-    ... name = myapp-run
-    ... etc-directory = %(root)s/etc/myapp-run
-    ... rc-directory = %(root)s/etc/init.d
-    ... logrotate-directory = %(root)s/etc/logrotate.d
-    ... log-directory = %(root)s/var/log/myapp-run
-    ... run-directory = %(root)s/var/run/myapp-run
-    ... user = zope
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Uninstalling myapp.
-    Updating database.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-    Installing instance.
-    Generated script '/root/etc/init.d/myapp-run-instance'.
-
-    >>> cat(root, 'etc', 'logrotate.d', 'myapp-run-instance')
-    /root/var/log/myapp-run/instance-z3.log {
-      rotate 10
-      daily
-      postrotate
-        /root/etc/init.d/myapp-run-instance reopen_transcript
-      endscript
-    }
-
-If we set ``logrotate.conf`` to an empty string, the file is not generated:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ... address = 8081
-    ... deployment = myapp-deployment
-    ... logrotate.conf =
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ...
-    ... [myapp-deployment]
-    ... name = myapp-run
-    ... etc-directory = %(root)s/etc/myapp-run
-    ... rc-directory = %(root)s/etc/init.d
-    ... logrotate-directory = %(root)s/etc/logrotate.d
-    ... log-directory = %(root)s/var/log/myapp-run
-    ... run-directory = %(root)s/var/run/myapp-run
-    ... user = zope
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Updating database.
-    Updating myapp.
-    Installing instance.
-    Generated script '/root/etc/init.d/myapp-run-instance'.
-
-    >>> ls(root, 'etc', 'logrotate.d')
-
-
-Defining multiple similar instances
------------------------------------
-
-Often you want to define multiple instances that differ only by one or
-two options (e.g. an address).  The extends option lets you name a
-section from which default options should be loaded.  Any options in
-the source section not defined in the extending section are added to
-the extending section.
-
-Let's update our buildout to add a new instance:
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance instance2
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ... address = 8081
-    ... deployment = myapp-deployment
-    ...
-    ... [instance2]
-    ... recipe = zc.zope3recipes:instance
-    ... extends = instance
-    ... address = 8082
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ...
-    ... [myapp-deployment]
-    ... name = myapp-run
-    ... etc-directory = %(root)s/etc/myapp-run
-    ... rc-directory = %(root)s/etc/init.d
-    ... logrotate-directory = %(root)s/etc/logrotate.d
-    ... log-directory = %(root)s/var/log/myapp-run
-    ... run-directory = %(root)s/var/run/myapp-run
-    ... user = zope
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance.
-    Uninstalling myapp.
-    Updating database.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-    Installing instance.
-    Generated script '/root/etc/init.d/myapp-run-instance'.
-    Installing instance2.
-    Generated script '/root/etc/init.d/myapp-run-instance2'.
-
-Now, we have the new instance configuration files:
-
-    >>> ls(root, 'etc', 'myapp-run')
-    -  instance-zdaemon.conf
-    -  instance-zope.conf
-    -  instance2-zdaemon.conf
-    -  instance2-zope.conf
-
-    >>> cat(root, 'etc', 'myapp-run', 'instance2-zope.conf')
-    site-definition /sample-buildout/parts/myapp/site.zcml
-    <BLANKLINE>
-    <zodb>
-      <filestorage>
-        path /sample-buildout/parts/database/Data.fs
-      </filestorage>
-    </zodb>
-    <BLANKLINE>
-    <server>
-      address 8082
-      type HTTP
-    </server>
-    <BLANKLINE>
-    <accesslog>
-      <logfile>
-        path /root/var/log/myapp-run/instance2-access.log
-      </logfile>
-    </accesslog>
-    <BLANKLINE>
-    <eventlog>
-      <logfile>
-        formatter zope.exceptions.log.Formatter
-        path STDOUT
-      </logfile>
-    </eventlog>
-
-
-Relative paths
---------------
-
-Relative paths will be used in the control script if they are requested
-in a buildout configuration.
-
-    >>> write('buildout.cfg',
-    ... '''
-    ... [buildout]
-    ... develop = demo1 demo2
-    ... parts = instance
-    ... relative-paths = true
-    ...
-    ... [zope3]
-    ... location = %(zope3)s
-    ...
-    ... [myapp]
-    ... recipe = zc.zope3recipes:app
-    ... site.zcml = <include package="demo2" />
-    ...             <principal
-    ...                 id="zope.manager"
-    ...                 title="Manager"
-    ...                 login="jim"
-    ...                 password_manager="SHA1"
-    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
-    ...                 />
-    ...             <grant
-    ...                 role="zope.Manager"
-    ...                 principal="zope.manager"
-    ...                 />
-    ... eggs = demo2
-    ...
-    ... [instance]
-    ... recipe = zc.zope3recipes:instance
-    ... application = myapp
-    ... zope.conf = ${database:zconfig}
-    ...
-    ... [database]
-    ... recipe = zc.recipe.filestorage
-    ... ''' % globals())
-
-    >>> print system(join('bin', 'buildout')),
-    Develop: '/sample-buildout/demo1'
-    Develop: '/sample-buildout/demo2'
-    Uninstalling instance2.
-    Uninstalling instance.
-    Uninstalling myapp.
-    Updating database.
-    Installing myapp.
-    Generated script '/sample-buildout/parts/myapp/runzope'.
-    Generated script '/sample-buildout/parts/myapp/debugzope'.
-    Installing instance.
-    Generated script '/sample-buildout/bin/instance'.
-
-    Both ``sys.path`` and arguments to the `ctl` are using relative
-    paths now.
-
-    >>> cat('bin', 'instance')
-    #!/usr/local/bin/python2.4
-    <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, 'eggs/zdaemon-pyN.N.egg'),
-      join(base, 'eggs/setuptools-pyN.N.egg'),
-      join(base, 'eggs/ZConfig-pyN.N.egg'),
-      '/zope3recipes',
-      ]
-    <BLANKLINE>
-    import zc.zope3recipes.ctl
-    <BLANKLINE>
-    if __name__ == '__main__':
-        zc.zope3recipes.ctl.main([
-            join(base, 'parts/myapp/debugzope'),
-            join(base, 'parts/instance/zope.conf'),
-            '-C', join(base, 'parts/instance/zdaemon.conf'),
-            ]+sys.argv[1:]
-            )

Copied: zc.zope3recipes/tags/0.13.0/zc/zope3recipes/README.txt (from rev 118571, zc.zope3recipes/trunk/zc/zope3recipes/README.txt)
===================================================================
--- zc.zope3recipes/tags/0.13.0/zc/zope3recipes/README.txt	                        (rev 0)
+++ zc.zope3recipes/tags/0.13.0/zc/zope3recipes/README.txt	2010-11-24 17:23:54 UTC (rev 118572)
@@ -0,0 +1,2460 @@
+=============
+Zope3 Recipes
+=============
+
+The Zope 3 recipes allow one to define Zope applications and instances
+of those applications.  A Zope application is a collection of software
+and software configuration, expressed as ZCML.  A Zope instance
+invokes the application with a specific instance configuration.  A
+single application may have many instances.
+
+Building Zope 3 applications (from eggs)
+========================================
+
+The 'application' recipe can be used to define a Zope application.  It
+is designed to work with with Zope solely from eggs.  The app recipe
+causes a part to be created. The part will contain the scripts runzope
+and debugzope and the application's site.zcml.  Both of the scripts
+will require providing a -C option and the path to a zope.conf file
+when run.  The debugzope script can be run with a script name and
+arguments, in which case it will run the script, rather than starting
+an interactive session.
+
+The 'application' recipe accepts the following options:
+
+site.zcml
+  The contents of site.zcml.
+
+eggs
+  The names of one or more eggs, with their dependencies that should
+  be included in the Python path of the generated scripts.
+
+
+Lets define some (bogus) eggs that we can use in our application:
+
+    >>> mkdir('demo1')
+    >>> write('demo1', 'setup.py',
+    ... '''
+    ... from setuptools import setup
+    ... setup(name = 'demo1')
+    ... ''')
+
+    >>> mkdir('demo2')
+    >>> write('demo2', 'setup.py',
+    ... '''
+    ... from setuptools import setup
+    ... setup(name = 'demo2', install_requires='demo1')
+    ... ''')
+
+.. Please note that the "newest=false" option is set in the test SetUp to
+   prevent upgrades
+
+We'll create a buildout.cfg file that defines our application:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:application
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ... ''' % globals())
+
+Now, Let's run the buildout and see what we get:
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+
+The runzope script runs the Web server:
+
+    >>> cat('parts', 'myapp', 'runzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      ]
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zope.app.twisted.main.main()
+
+Here, unlike the above example the location path is not included
+in ``sys.path``.  Similarly debugzope script is also changed:
+
+    >>> cat('parts', 'myapp', 'debugzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    <BLANKLINE>
+    import zc.zope3recipes.debugzope
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)
+
+The ``initialization`` setting can be used to provide a bit of
+additional code that will be included in the runzope and debugzope
+scripts just before the server's main function is called:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:application
+    ... site.zcml = <include package="demo2" />
+    ... eggs = demo2
+    ... initialization =
+    ...     print "Starting application server."
+    ... ''')
+
+Now, Let's run the buildout and see what we get:
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling myapp.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+
+The runzope and debugzope scripts now include the additional code just
+before server is started:
+
+    >>> cat('parts', 'myapp', 'runzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      ]
+    <BLANKLINE>
+    print "Starting application server."
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zope.app.twisted.main.main()
+
+    >>> cat('parts', 'myapp', 'debugzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    print "Starting application server."
+    import zope.app.twisted.main
+    <BLANKLINE>
+    <BLANKLINE>
+    import zc.zope3recipes.debugzope
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)
+
+If the additional initialization for debugzope needs to be different
+from that of runzope, the ``debug-initialization`` setting can be used.
+If set, that is used for debugzope *instead* of the value of
+``initialization``.
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:application
+    ... site.zcml = <include package="demo2" />
+    ... eggs = demo2
+    ... initialization =
+    ...     print "Starting application server."
+    ... debug-initialization =
+    ...     print "Starting debugging interaction."
+    ... ''')
+
+Now, Let's run the buildout and see what we get:
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling myapp.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+
+    >>> cat('parts', 'myapp', 'debugzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    print "Starting debugging interaction."
+    import zope.app.twisted.main
+    <BLANKLINE>
+    <BLANKLINE>
+    import zc.zope3recipes.debugzope
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)
+
+The runzope script still uses the ``initialization`` setting::
+
+    >>> cat('parts', 'myapp', 'runzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      ]
+    <BLANKLINE>
+    print "Starting application server."
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zope.app.twisted.main.main()
+
+Setting ``debug-initialization`` to an empty string suppresses the
+``initialization`` setting for the debugzope script:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:application
+    ... site.zcml = <include package="demo2" />
+    ... eggs = demo2
+    ... initialization =
+    ...     print "Starting application server."
+    ... debug-initialization =
+    ... ''')
+
+Now, Let's run the buildout and see what we get:
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling myapp.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+
+    >>> cat('parts', 'myapp', 'debugzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    <BLANKLINE>
+    import zc.zope3recipes.debugzope
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)
+
+
+Relative paths
+--------------
+
+If requested in a buildout configuration, the scripts will be generated
+with relative paths instead of absolute.
+
+Let's change a buildout configuration to include ``relative-paths``.
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ... relative-paths = true
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:application
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling myapp.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+
+We get runzope script with relative paths.
+
+    >>> cat('parts', 'myapp', 'runzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import os
+    <BLANKLINE>
+    join = os.path.join
+    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
+    base = os.path.dirname(base)
+    base = os.path.dirname(base)
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      join(base, 'demo2'),
+      join(base, 'demo1'),
+      ]
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zope.app.twisted.main.main()
+
+Similarly, debugzope script has relative paths.
+
+    >>> cat('parts', 'myapp', 'debugzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import os
+    <BLANKLINE>
+    join = os.path.join
+    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
+    base = os.path.dirname(base)
+    base = os.path.dirname(base)
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      join(base, 'demo2'),
+      join(base, 'demo1'),
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    <BLANKLINE>
+    import zc.zope3recipes.debugzope
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)
+
+
+Building Zope 3 Applications (from Zope 3 checkouts/tarballs)
+=============================================================
+
+The 'app' recipe works much like the 'application' recipe.  It takes
+the same configuration options plus the following one:
+
+zope3
+  The name of a section defining a location option that gives the
+  location of a Zope installation.  This can be either a checkout or a
+  distribution.  If the location has a lib/python subdirectory, it is
+  treated as a distribution, otherwise, it must have a src
+  subdirectory and will be treated as a checkout. This option defaults
+  to "zope3".  And if location is empty, the application will run solely
+  from eggs.
+
+Let's look at an example.  We'll make a faux zope installation:
+
+    >>> zope3 = tmpdir('zope3')
+    >>> mkdir(zope3, 'src')
+
+Now we'll create a buildout.cfg file that defines our application:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ... ''' % globals())
+
+Note that our site.zcml file is very small.  It expect the application
+zcml to define almost everything.  In fact, a site.zcml file will often
+include just a single include directive.  We don't need to include the
+surrounding configure element, unless we want a namespace other than
+the zope namespace.  A configure directive will be included for us.
+
+Let's run the buildout and see what we get:
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling myapp.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+
+A directory is created in the parts directory for our application files:
+
+    >>> ls('parts')
+    d  myapp
+
+    >>> ls('parts', 'myapp')
+    -  debugzope
+    -  runzope
+    -  site.zcml
+
+We get 3 files, two scripts and a site.zcml file.  The site.zcml file
+is just what we had in the buildout configuration:
+
+    >>> cat('parts', 'myapp', 'site.zcml')
+    <configure xmlns='http://namespaces.zope.org/zope'
+               xmlns:meta="http://namespaces.zope.org/meta"
+               >
+    <include package="demo2" />
+    <principal
+    id="zope.manager"
+    title="Manager"
+    login="jim"
+    password_manager="SHA1"
+    password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    />
+    <grant
+    role="zope.Manager"
+    principal="zope.manager"
+    />
+    </configure>
+
+Unfortunately, the leading whitespace is stripped from the
+configuration file lines.  This is a consequence of the way
+ConfigParser works.
+
+The runzope script runs the Web server:
+
+    >>> cat('parts', 'myapp', 'runzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      '/zope3/src',
+      ]
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zope.app.twisted.main.main()
+
+It includes in it's path the eggs we specified in the configuration
+file, along with their dependencies. Note that we haven't specified a
+configuration file.  When runzope is run, a -C option must be used to
+provide a configuration file.  -X options can also be provided to
+override configuration file options.
+
+The debugzope script provides access to the object system.  When
+debugzope is run, a -C option must be used to provide a configuration
+file.  -X options can also be provided to override configuration file
+options.  If run without any additional arguments, then an interactive
+interpreter will be started with databases specified in the
+configuration file opened and with the variable root set to the
+application root object.  The debugger variable is set to a Zope 3
+debugger.  If additional arguments are provided, then the first
+argument should be a script name and the remaining arguments are
+script arguments.  The script will be run with the root and debugger
+variables available as global variables.
+
+..
+
+    >>> cat('parts', 'myapp', 'debugzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      '/zope3/src',
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    <BLANKLINE>
+    import zc.zope3recipes.debugzope
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)
+
+Note that the runzope shown above uses the default, twisted-based
+server components.  It's possible to specify which set of server
+components is used: the "servers" setting can be set to either
+"zserver" or "twisted".  For the application, this affects the runzope
+script; we'll see additional differences when we create instances of
+the application.
+
+Let's continue to use the twisted servers, but make the selection
+explicit:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... servers = twisted
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Updating myapp.
+
+Note that this is recognized as not being a change to the
+configuration; the messages say that myapp was updated, not
+uninstalled and then re-installed.
+
+The runzope script generated is identical to what we saw before:
+
+    >>> cat('parts', 'myapp', 'runzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      '/zope3/src',
+      ]
+    <BLANKLINE>
+    import zope.app.twisted.main
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zope.app.twisted.main.main()
+
+We can also specify the ZServer servers explicitly:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... servers = zserver
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling myapp.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+
+The part has been re-installed, and the runzope script generated is
+different now.  Note that the main() function is imported from a
+different package this time:
+
+    >>> cat('parts', 'myapp', 'runzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      '/zope3/src',
+      ]
+    <BLANKLINE>
+    import zope.app.server.main
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zope.app.server.main.main()
+
+The debugzope script has also been modified to take this into account.
+
+    >>> cat('parts', 'myapp', 'debugzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/demo2',
+      '/sample-buildout/demo1',
+      '/zope3/src',
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    import zope.app.server.main
+    <BLANKLINE>
+    <BLANKLINE>
+    import zc.zope3recipes.debugzope
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.debugzope.debug(main_module=zope.app.server.main)
+
+
+Relative paths
+--------------
+
+We can also request relative paths.
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ... relative-paths = true
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... servers = zserver
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling myapp.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+
+The runzope script has relative paths.
+
+    >>> cat('parts', 'myapp', 'runzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import os
+    <BLANKLINE>
+    join = os.path.join
+    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
+    base = os.path.dirname(base)
+    base = os.path.dirname(base)
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      join(base, 'demo2'),
+      join(base, 'demo1'),
+      '/zope3/src',
+      ]
+    <BLANKLINE>
+    import zope.app.server.main
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zope.app.server.main.main()
+
+The debugzope script also has relative paths.
+
+    >>> cat('parts', 'myapp', 'debugzope')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import os
+    <BLANKLINE>
+    join = os.path.join
+    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
+    base = os.path.dirname(base)
+    base = os.path.dirname(base)
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      join(base, 'demo2'),
+      join(base, 'demo1'),
+      '/zope3/src',
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    import zope.app.server.main
+    <BLANKLINE>
+    <BLANKLINE>
+    import zc.zope3recipes.debugzope
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.debugzope.debug(main_module=zope.app.server.main)
+
+
+Legacy Functional Testing Support
+---------------------------------
+
+Zope 3's functional testing support is based on zope.testing test
+layers. There is a default functional test layer that older functional
+tests use.  This layer loads the default configuration for the Zope
+application server.  It exists to provide support for older functional
+tests that were written before layers were added to the testing
+infrastructure.   The default testing layer has a number of
+disadvantages:
+
+- It loads configurations for a large number of packages.  This has
+  the potential to introduce testing dependency on all of these
+  packages.
+
+- It required a ftesting.zcml file and makes assumptions about where
+  that file is.  In particular, it assumes a location relative to the
+  current working directory when the test is run.
+
+Newer software and maintained software should use their own functional
+testing layers that use test-configuration files defined in packages.
+
+To support older packages that use the default layer, a ftesting.zcml
+option is provided.  If it is used, then the contents of the option
+are written to a ftesting.zcml file in the application.  In addition,
+an ftesting-base.zcml file is written that includes configuration
+traditionally found in a Zope 3 ftesting-base.zcml excluding reference
+to package-includes.
+
+If we modify our buildout to include an ftesting.zcml option:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = myapp
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... ftesting.zcml =
+    ...    <meta:provides feature="devmode" />
+    ...    <include file="ftesting-base.zcml" />
+    ...    <includeOverrides package="demo2" />
+    ... eggs = demo2
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling myapp.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+
+We'll get ftesting.zcml files and ftesting-base.zcml files created in
+the application:
+
+    >>> cat('parts', 'myapp', 'ftesting.zcml')
+    <configure xmlns='http://namespaces.zope.org/zope'
+               xmlns:meta="http://namespaces.zope.org/meta"
+               >
+    <BLANKLINE>
+    <meta:provides feature="devmode" />
+    <include file="ftesting-base.zcml" />
+    <includeOverrides package="demo2" />
+    </configure>
+
+    >>> cat('parts', 'myapp', 'ftesting-base.zcml')
+    <BLANKLINE>
+    <configure
+       xmlns="http://namespaces.zope.org/zope"
+       i18n_domain="zope"
+       >
+      <include package="zope.app" />
+      <include package="zope.app" file="ftesting.zcml" />
+      <include package="zope.app.securitypolicy" file="meta.zcml" />
+      <include package="zope.app.securitypolicy" />
+      <securityPolicy
+        component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+      <role id="zope.Anonymous" title="Everybody"
+                     description="All users have this role implicitly" />
+      <role id="zope.Manager" title="Site Manager" />
+      <role id="zope.Member" title="Site Member" />
+      <grant permission="zope.View"
+                      role="zope.Anonymous" />
+      <grant permission="zope.app.dublincore.view"
+                      role="zope.Anonymous" />
+      <grantAll role="zope.Manager" />
+      <include package="zope.app.securitypolicy.tests"
+               file="functional.zcml" />
+      <unauthenticatedPrincipal
+          id="zope.anybody"
+          title="Unauthenticated User"
+          />
+      <unauthenticatedGroup
+        id="zope.Anybody"
+        title="Unauthenticated Users"
+        />
+      <authenticatedGroup
+        id="zope.Authenticated"
+        title="Authenticated Users"
+        />
+      <everybodyGroup
+        id="zope.Everybody"
+        title="All Users"
+        />
+      <principal
+          id="zope.mgr"
+          title="Manager"
+          login="mgr"
+          password="mgrpw" />
+      <principal
+          id="zope.globalmgr"
+          title="Manager"
+          login="globalmgr"
+          password="globalmgrpw" />
+      <grant role="zope.Manager" principal="zope.globalmgr" />
+    </configure>
+
+Defining Zope3 instances
+========================
+
+Having defined an application, we can define one or more instances of
+the application.  We do this using the zc.zope3recipes instance
+recipe.  The instance recipe has 2 modes, a development and a
+production mode.  We'll start with the development mode.  In
+development mode, a part directory will be created for each instance
+containing the instance's configuration files. This directory will
+also contain run-time files created by the instances, such as log
+files or zdaemon socket files.
+
+When defining an instance, we need to specify a zope.conf file.  The
+recipe can do most of the work for us.  Let's look at a a basic
+example:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ... ''' % globals())
+
+The application option names an application part.  The application
+part will be used to determine the location of the site.zcml file and
+the name of the control script to run.
+
+We specified a zope.conf option which contains a start at our final
+zope.conf file.  The recipe will add some bits we leave out.  The one
+thing we really need to have is a database definition.  We simply
+include the zconfig option from the database section, which we provide
+as a file storage part using the zc.recipe.filestorage recipe.  The
+filestorage recipe will create a directory to hold our database and
+compute a zconfig option that we can use in our instance section.
+
+Note that we've replaced the myapp part with the instance part.  The
+myapp part will be included by virtue of the reference from the
+instance part.
+
+Let's run the buildout, and see what we get:
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling myapp.
+    Installing database.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+We see that the database and myapp parts were included by virtue of
+being referenced from the instance part.
+
+We get new directories for our database and instance:
+
+    >>> ls('parts')
+    d  database
+    d  instance
+    d  myapp
+
+The instance directory contains zdaemon.conf and zope.conf files:
+
+    >>> ls('parts', 'instance')
+    -  zdaemon.conf
+    -  zope.conf
+
+Let's look at the zope.conf file that was generated:
+
+    >>> cat('parts', 'instance', 'zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8080
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /sample-buildout/parts/instance/access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+This uses the twisted server types, since that's the default
+configuration for Zope 3.  If we specify use of the ZServer servers,
+the names of the server types are adjusted appropriately:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... servers = zserver
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Uninstalling myapp.
+    Updating database.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+The generated zope.conf file now uses the ZServer server components
+instead:
+
+    >>> cat('parts', 'instance', 'zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8080
+      type WSGI-HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /sample-buildout/parts/instance/access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+The Twisted-based servers can also be specified explicitly:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... servers = twisted
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Uninstalling myapp.
+    Updating database.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+The generated zope.conf file now uses the Twisted server components
+once more:
+
+    >>> cat('parts', 'instance', 'zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8080
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /sample-buildout/parts/instance/access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+It includes the database definition that we provided in the zope.conf
+option.  It has a site-definition option that names the site.zcml file
+from our application directory.
+
+We didn't specify any server or logging ZConfig sections, so some were
+generated for us.
+
+Note that, by default, the event-log output goes to standard output.
+We'll say more about that when we talk about the zdaemon
+configuration later.
+
+If we specify a server section ourselves:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ...    <server>
+    ...        type PostmortemDebuggingHTTP
+    ...        address 8080
+    ...    </server>
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Updating database.
+    Updating myapp.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+Then the section (or sections) we provide will be used and new ones
+won't be added:
+
+    >>> cat('parts', 'instance', 'zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8080
+      type PostmortemDebuggingHTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /sample-buildout/parts/instance/access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+If we just want to specify alternate ports or addresses, we can use
+the address option which accepts zero or more address specifications:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ... address = 8081 foo.com:8082
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Updating database.
+    Updating myapp.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+    >>> cat('parts', 'instance', 'zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8081
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <server>
+      address foo.com:8082
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /sample-buildout/parts/instance/access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+We can specify our own accesslog and eventlog configuration.  For
+example, to send the event-log output to a file and suppress the
+access log:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ...    <eventlog>
+    ...      <logfile>
+    ...        path ${buildout:parts-directory}/instance/event.log
+    ...        formatter zope.exceptions.log.Formatter
+    ...      </logfile>
+    ...    </eventlog>
+    ...    <accesslog>
+    ...    </accesslog>
+    ...
+    ... address = 8081
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Updating database.
+    Updating myapp.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+    >>> cat('parts', 'instance', 'zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    </zodb>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path /sample-buildout/parts/instance/event.log
+      </logfile>
+    </eventlog>
+    <BLANKLINE>
+    <accesslog>
+    </accesslog>
+    <BLANKLINE>
+    <server>
+      address 8081
+      type HTTP
+    </server>
+
+Let's look at the zdaemon.conf file:
+
+    >>> cat('parts', 'instance', 'zdaemon.conf')
+    <runner>
+      daemon on
+      directory /sample-buildout/parts/instance
+      program /sample-buildout/parts/myapp/runzope -C /sample-buildout/parts/instance/zope.conf
+      socket-name /sample-buildout/parts/instance/zdaemon.sock
+      transcript /sample-buildout/parts/instance/z3.log
+    </runner>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        path /sample-buildout/parts/instance/z3.log
+      </logfile>
+    </eventlog>
+
+Here we see a fairly ordinary zdaemon.conf file.  The program option
+refers to the runzope script in our application directory.  The socket
+file, used for communication between the zdaemon command-line script
+and the zademon manager is placed in the instance directory.
+
+If you want to override any part of the generated zdaemon output,
+simply provide a zdaemon.conf option in your instance section:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ... address = 8081
+    ... zdaemon.conf =
+    ...     <runner>
+    ...       daemon off
+    ...       socket-name /sample-buildout/parts/instance/sock
+    ...       transcript /dev/null
+    ...     </runner>
+    ...     <eventlog>
+    ...     </eventlog>
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Updating database.
+    Updating myapp.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+    >>> cat('parts', 'instance', 'zdaemon.conf')
+    <runner>
+      daemon off
+      directory /sample-buildout/parts/instance
+      program /sample-buildout/parts/myapp/runzope -C /sample-buildout/parts/instance/zope.conf
+      socket-name /sample-buildout/parts/instance/sock
+      transcript /dev/null
+    </runner>
+    <BLANKLINE>
+    <eventlog>
+    </eventlog>
+
+In addition to the configuration files, a control script is generated
+in the buildout bin directory:
+
+    >>> ls('bin')
+    -  buildout
+    -  instance
+
+..
+
+    >>> cat('bin', 'instance')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/eggs/zdaemon-2.0-py2.4.egg',
+      '/sample-buildout/eggs/setuptools-0.6-py2.4.egg',
+      '/sample-buildout/eggs/ZConfig-2.3-py2.4.egg',
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    import zc.zope3recipes.ctl
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.ctl.main([
+            '/sample-buildout/parts/myapp/debugzope',
+            '/sample-buildout/parts/instance/zope.conf',
+            '-C', '/sample-buildout/parts/instance/zdaemon.conf',
+            ]+sys.argv[1:]
+            )
+
+Some configuration sections can include a key multiple times; the ZEO
+client section works this way.  When a key is given multiple times,
+all values are included in the resulting configuration in the order in
+which they're give in the input::
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf =
+    ...     <zodb>
+    ...       <zeoclient>
+    ...         server 127.0.0.1:8001
+    ...         server 127.0.0.1:8002
+    ...       </zeoclient>
+    ...     </zodb>
+    ... address = 8081
+    ... zdaemon.conf =
+    ...     <runner>
+    ...       daemon off
+    ...       socket-name /sample-buildout/parts/instance/sock
+    ...       transcript /dev/null
+    ...     </runner>
+    ...     <eventlog>
+    ...     </eventlog>
+    ...
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Uninstalling database.
+    Updating myapp.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+    >>> cat('parts', 'instance', 'zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <zeoclient>
+        server 127.0.0.1:8001
+        server 127.0.0.1:8002
+      </zeoclient>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8081
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /sample-buildout/parts/instance/access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+Instance names
+--------------
+
+The instance recipe generates files or directories based on its name,
+which defaults to the part name.  We can specify a different name
+using the name option.  This doesn't effect which parts directory is
+used, but it does affect the name of the run script in bin:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... name = server
+    ... application = myapp
+    ... zope.conf =
+    ...     <zodb>
+    ...       <zeoclient>
+    ...         server 127.0.0.1:8001
+    ...         server 127.0.0.1:8002
+    ...       </zeoclient>
+    ...     </zodb>
+    ... address = 8081
+    ... zdaemon.conf =
+    ...     <runner>
+    ...       daemon off
+    ...       socket-name /sample-buildout/parts/instance/sock
+    ...       transcript /dev/null
+    ...     </runner>
+    ...     <eventlog>
+    ...     </eventlog>
+    ...
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Updating myapp.
+    Installing instance.
+    Generated script '/sample-buildout/bin/server'.
+
+
+Specifying an alternate site definition
+---------------------------------------
+
+Ideally, ZCML is used to configure the software used by an application
+and zope.conf is used to provide instance-specific configuration.  For
+historical reasons, there are ZCML directives that provide process
+configuration.  A good example of this is the smtpMailer directive
+provided by the zope.sendmail package.  We can override the
+site-definition option in the zope.conf file to specify an alternate
+zcml file.  Here, we'll update out instance configuration to use an
+alternate site definition:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf =
+    ...     site-definition ${buildout:directory}/site.zcml
+    ...     <zodb>
+    ...       <zeoclient>
+    ...         server 127.0.0.1:8001
+    ...         server 127.0.0.1:8002
+    ...       </zeoclient>
+    ...     </zodb>
+    ... address = 8081
+    ... zdaemon.conf =
+    ...     <runner>
+    ...       daemon off
+    ...       socket-name /sample-buildout/parts/instance/sock
+    ...       transcript /dev/null
+    ...     </runner>
+    ...     <eventlog>
+    ...     </eventlog>
+    ...
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Updating myapp.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+    >>> cat('parts', 'instance', 'zope.conf')
+    site-definition /sample-buildout/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <zeoclient>
+        server 127.0.0.1:8001
+        server 127.0.0.1:8002
+      </zeoclient>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8081
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /sample-buildout/parts/instance/access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+(Note that, in practice, you'll often use the
+zc.recipe.deployment:configuration recipe,
+http://pypi.python.org/pypi/zc.recipe.deployment#configuration-files,
+to define a site.zcml file using the buildout.)
+
+Log files
+---------
+
+The log file settings deserver some explanation.  The Zope event log
+only captures output from logging calls.  In particular, it doesn't
+capture startup errors written to standard error.  The zdaemon
+transcript log is very useful for capturing this output.  Without it,
+error written to standard error are lost when running as a daemon.
+The default Zope 3 configuration in the past was to write the Zope
+access and event log output to both files and standard output and to
+define a transcript log.  This had the effect that the transcript
+duplicated the contents of the event log and access logs, in addition
+to capturing other output.  This was space inefficient.
+
+This recipe's approach is to combine the zope and zdaemon event-log
+information as well as Zope error output into a single log file.  We
+do this by directing Zope's event log to standard output, where it is
+useful when running Zope in foreground mode and where it can be
+captured by the zdaemon transcript log.
+
+Unix Deployments
+----------------
+
+The instance recipe provides support for Unix deployments, as provided
+by the zc.recipe.deployment recipe.  A deployment part defines a number of
+options used by the instance recipe:
+
+etc-directory
+    The name of the directory where configuration files should be
+    placed.  This defaults to /etc/NAME, where NAME is the deployment
+    name.
+
+log-directory
+    The name of the directory where application instances should write
+    their log files.  This defaults to /var/log/NAME, where NAME is
+    the deployment name.
+
+run-directory
+    The name of the directory where application instances should put
+    their run-time files such as pid files and inter-process
+    communication socket files.  This defaults to /var/run/NAME, where
+    NAME is the deployment name.
+
+rc-directory
+    The name of the directory where run-control scripts should be
+    installed.
+
+logrotate-directory
+    The name ot the directory where logrotate configuration files should be
+    installed.
+    
+user
+    The name of a user that processes should run as.
+
+The deployment recipe has to be run as root for various reasons, but
+we can create a faux deployment by providing a section with the needed
+data. Let's update our configuration to use a deployment.  We'll first
+create a faux installation root:
+
+    >>> root = tmpdir('root')
+    >>> mkdir(root, 'etc')
+    >>> mkdir(root, 'etc', 'myapp-run')
+    >>> mkdir(root, 'etc', 'init.d')
+    >>> mkdir(root, 'etc', 'logrotate.d')
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ... address = 8081
+    ... deployment = myapp-deployment
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ...
+    ... [myapp-deployment]
+    ... name = myapp-run
+    ... etc-directory = %(root)s/etc/myapp-run
+    ... rc-directory = %(root)s/etc/init.d
+    ... logrotate-directory = %(root)s/etc/logrotate.d
+    ... log-directory = %(root)s/var/log/myapp-run
+    ... run-directory = %(root)s/var/run/myapp-run
+    ... user = zope
+    ... ''' % globals())
+
+Here we've added a deployment section, myapp-deployment, and added a
+deployment option to our instance part telling the instance recipe to
+use the deployment.  If we rerun the buildout:
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Installing database.
+    Updating myapp.
+    Installing instance.
+    Generated script '/root/etc/init.d/myapp-run-instance'.
+
+The installer files will move.  We'll no-longer have the instance part:
+
+    >>> ls('parts')
+    d  database
+    d  myapp
+
+or the control script:
+
+    >>> ls('bin')
+    -  buildout
+
+Rather, we'll get our configuration files in the /etc/myapp-run directory:
+
+    >>> ls(root, 'etc', 'myapp-run')
+    -  instance-zdaemon.conf
+    -  instance-zope.conf
+
+Note that the instance name was added as a prefix to the file names,
+since we'll typically have additional instances in the deployment.
+
+The control script is in the init.d directory:
+
+    >>> ls(root, 'etc', 'init.d')
+    -  myapp-run-instance
+
+Note that the deployment name is added as a prefix of the control
+script name.
+
+The logrotate file is in the logrotate.d directory:
+
+    >>> ls(root, 'etc', 'logrotate.d')
+    -  myapp-run-instance
+
+
+The configuration files have changed to reflect the deployment
+locations:
+
+    >>> cat(root, 'etc', 'myapp-run', 'instance-zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8081
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /root/var/log/myapp-run/instance-access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+    >>> cat(root, 'etc', 'myapp-run', 'instance-zdaemon.conf')
+    <runner>
+      daemon on
+      directory /root/var/run/myapp-run
+      program /sample-buildout/parts/myapp/runzope -C /root/etc/myapp-run/instance-zope.conf
+      socket-name /root/var/run/myapp-run/instance-zdaemon.sock
+      transcript /root/var/log/myapp-run/instance-z3.log
+      user zope
+    </runner>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        path /root/var/log/myapp-run/instance-z3.log
+      </logfile>
+    </eventlog>
+
+    >>> cat(root, 'etc', 'logrotate.d', 'myapp-run-instance')
+    /root/var/log/myapp-run/instance-z3.log {
+      rotate 5
+      weekly
+      postrotate
+        /root/etc/init.d/myapp-run-instance reopen_transcript
+      endscript
+    }
+    
+
+If we provide an alternate instance name, that will be reflected in
+the generated files:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... name = server
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ... address = 8081
+    ... deployment = myapp-deployment
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ...
+    ... [myapp-deployment]
+    ... name = myapp-run
+    ... etc-directory = %(root)s/etc/myapp-run
+    ... rc-directory = %(root)s/etc/init.d
+    ... logrotate-directory = %(root)s/etc/logrotate.d
+    ... log-directory = %(root)s/var/log/myapp-run
+    ... run-directory = %(root)s/var/run/myapp-run
+    ... user = zope
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Updating database.
+    Updating myapp.
+    Installing instance.
+    Generated script '/root/etc/init.d/myapp-run-server'.
+
+    >>> cat(root, 'etc', 'myapp-run', 'server-zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8081
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /root/var/log/myapp-run/server-access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+    >>> cat(root, 'etc', 'myapp-run', 'server-zdaemon.conf')
+    <runner>
+      daemon on
+      directory /root/var/run/myapp-run
+      program /sample-buildout/parts/myapp/runzope -C /root/etc/myapp-run/server-zope.conf
+      socket-name /root/var/run/myapp-run/server-zdaemon.sock
+      transcript /root/var/log/myapp-run/server-z3.log
+      user zope
+    </runner>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        path /root/var/log/myapp-run/server-z3.log
+      </logfile>
+    </eventlog>
+
+
+Controlling logrotate configuration
+-----------------------------------
+
+Some applications control their own log rotation policies.  In these
+cases, we don't want the logrotate configuration to be generated.
+
+Setting the logrotate.conf setting affects the configuration.  Setting
+it explicitly controls the content of the logrotate file for the
+instance; setting it to an empty string causes it not to be generated at
+all.
+
+Let's take a look at setting the content to a non-empty value directly:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ... address = 8081
+    ... deployment = myapp-deployment
+    ... logrotate.conf =
+    ...       /root/var/log/myapp-run/instance-z3.log {
+    ...         rotate 10
+    ...         daily
+    ...         postrotate
+    ...           /root/etc/init.d/myapp-run-instance reopen_transcript
+    ...         endscript
+    ...       }
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ...
+    ... [myapp-deployment]
+    ... name = myapp-run
+    ... etc-directory = %(root)s/etc/myapp-run
+    ... rc-directory = %(root)s/etc/init.d
+    ... logrotate-directory = %(root)s/etc/logrotate.d
+    ... log-directory = %(root)s/var/log/myapp-run
+    ... run-directory = %(root)s/var/run/myapp-run
+    ... user = zope
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Uninstalling myapp.
+    Updating database.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+    Installing instance.
+    Generated script '/root/etc/init.d/myapp-run-instance'.
+
+    >>> cat(root, 'etc', 'logrotate.d', 'myapp-run-instance')
+    /root/var/log/myapp-run/instance-z3.log {
+      rotate 10
+      daily
+      postrotate
+        /root/etc/init.d/myapp-run-instance reopen_transcript
+      endscript
+    }
+
+If we set ``logrotate.conf`` to an empty string, the file is not generated:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ... address = 8081
+    ... deployment = myapp-deployment
+    ... logrotate.conf =
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ...
+    ... [myapp-deployment]
+    ... name = myapp-run
+    ... etc-directory = %(root)s/etc/myapp-run
+    ... rc-directory = %(root)s/etc/init.d
+    ... logrotate-directory = %(root)s/etc/logrotate.d
+    ... log-directory = %(root)s/var/log/myapp-run
+    ... run-directory = %(root)s/var/run/myapp-run
+    ... user = zope
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Updating database.
+    Updating myapp.
+    Installing instance.
+    Generated script '/root/etc/init.d/myapp-run-instance'.
+
+    >>> ls(root, 'etc', 'logrotate.d')
+
+
+Defining multiple similar instances
+-----------------------------------
+
+Often you want to define multiple instances that differ only by one or
+two options (e.g. an address).  The extends option lets you name a
+section from which default options should be loaded.  Any options in
+the source section not defined in the extending section are added to
+the extending section.
+
+Let's update our buildout to add a new instance:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance instance2
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ... address = 8081
+    ... deployment = myapp-deployment
+    ...
+    ... [instance2]
+    ... recipe = zc.zope3recipes:instance
+    ... extends = instance
+    ... address = 8082
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ...
+    ... [myapp-deployment]
+    ... name = myapp-run
+    ... etc-directory = %(root)s/etc/myapp-run
+    ... rc-directory = %(root)s/etc/init.d
+    ... logrotate-directory = %(root)s/etc/logrotate.d
+    ... log-directory = %(root)s/var/log/myapp-run
+    ... run-directory = %(root)s/var/run/myapp-run
+    ... user = zope
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance.
+    Uninstalling myapp.
+    Updating database.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+    Installing instance.
+    Generated script '/root/etc/init.d/myapp-run-instance'.
+    Installing instance2.
+    Generated script '/root/etc/init.d/myapp-run-instance2'.
+
+Now, we have the new instance configuration files:
+
+    >>> ls(root, 'etc', 'myapp-run')
+    -  instance-zdaemon.conf
+    -  instance-zope.conf
+    -  instance2-zdaemon.conf
+    -  instance2-zope.conf
+
+    >>> cat(root, 'etc', 'myapp-run', 'instance2-zope.conf')
+    site-definition /sample-buildout/parts/myapp/site.zcml
+    <BLANKLINE>
+    <zodb>
+      <filestorage>
+        path /sample-buildout/parts/database/Data.fs
+      </filestorage>
+    </zodb>
+    <BLANKLINE>
+    <server>
+      address 8082
+      type HTTP
+    </server>
+    <BLANKLINE>
+    <accesslog>
+      <logfile>
+        path /root/var/log/myapp-run/instance2-access.log
+      </logfile>
+    </accesslog>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        formatter zope.exceptions.log.Formatter
+        path STDOUT
+      </logfile>
+    </eventlog>
+
+
+Relative paths
+--------------
+
+Relative paths will be used in the control script if they are requested
+in a buildout configuration.
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... develop = demo1 demo2
+    ... parts = instance
+    ... relative-paths = true
+    ...
+    ... [zope3]
+    ... location = %(zope3)s
+    ...
+    ... [myapp]
+    ... recipe = zc.zope3recipes:app
+    ... site.zcml = <include package="demo2" />
+    ...             <principal
+    ...                 id="zope.manager"
+    ...                 title="Manager"
+    ...                 login="jim"
+    ...                 password_manager="SHA1"
+    ...                 password="40bd001563085fc35165329ea1ff5c5ecbdbbeef"
+    ...                 />
+    ...             <grant
+    ...                 role="zope.Manager"
+    ...                 principal="zope.manager"
+    ...                 />
+    ... eggs = demo2
+    ...
+    ... [instance]
+    ... recipe = zc.zope3recipes:instance
+    ... application = myapp
+    ... zope.conf = ${database:zconfig}
+    ...
+    ... [database]
+    ... recipe = zc.recipe.filestorage
+    ... ''' % globals())
+
+    >>> print system(join('bin', 'buildout')),
+    Develop: '/sample-buildout/demo1'
+    Develop: '/sample-buildout/demo2'
+    Uninstalling instance2.
+    Uninstalling instance.
+    Uninstalling myapp.
+    Updating database.
+    Installing myapp.
+    Generated script '/sample-buildout/parts/myapp/runzope'.
+    Generated script '/sample-buildout/parts/myapp/debugzope'.
+    Installing instance.
+    Generated script '/sample-buildout/bin/instance'.
+
+    Both ``sys.path`` and arguments to the `ctl` are using relative
+    paths now.
+
+    >>> cat('bin', 'instance')
+    #!/usr/local/bin/python2.4
+    <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, 'eggs/zdaemon-pyN.N.egg'),
+      join(base, 'eggs/setuptools-pyN.N.egg'),
+      join(base, 'eggs/ZConfig-pyN.N.egg'),
+      '/zope3recipes',
+      ]
+    <BLANKLINE>
+    import zc.zope3recipes.ctl
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zc.zope3recipes.ctl.main([
+            join(base, 'parts/myapp/debugzope'),
+            join(base, 'parts/instance/zope.conf'),
+            '-C', join(base, 'parts/instance/zdaemon.conf'),
+            ]+sys.argv[1:]
+            )

Deleted: zc.zope3recipes/tags/0.13.0/zc/zope3recipes/recipes.py
===================================================================
--- zc.zope3recipes/trunk/zc/zope3recipes/recipes.py	2010-11-24 16:02:02 UTC (rev 118564)
+++ zc.zope3recipes/tags/0.13.0/zc/zope3recipes/recipes.py	2010-11-24 17:23:54 UTC (rev 118572)
@@ -1,494 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Collected Zope 3 recipes
-"""
-
-import os, sys, shutil
-import logging
-import zc.buildout
-import zc.recipe.egg
-import pkg_resources
-import ZConfig.schemaless
-import cStringIO
-
-this_loc = pkg_resources.working_set.find(
-    pkg_resources.Requirement.parse('zc.zope3recipes')).location
-
-server_types = {
-    # name     (module,                  http-name)
-    'twisted': ('zope.app.twisted.main', 'HTTP'),
-    'zserver': ('zope.app.server.main',  'WSGI-HTTP'),
-    }
-
-WIN = False
-if sys.platform[:3].lower() == "win":
-    WIN = True
-
-class Application(object):
-
-    def __init__(self, buildout, name, options):
-        self.options = options
-        self.name = name
-
-        options['location'] = os.path.join(
-            buildout['buildout']['parts-directory'],
-            name,
-            )
-
-        options['servers'] = options.get('servers', 'twisted')
-        if options['servers'] not in server_types:
-            raise ValueError(
-                'servers setting must be one of "twisted" or "zserver"')
-
-        options['scripts'] = ''
-        self.egg = zc.recipe.egg.Egg(buildout, name, options)
-
-    def install(self):
-        options = self.options
-
-        dest = options['location']
-        if not os.path.exists(dest):
-            os.mkdir(dest)
-            created = True
-        else:
-            created = False
-
-        try:
-            open(os.path.join(dest, 'site.zcml'), 'w').write(
-                site_zcml_template % self.options['site.zcml']
-                )
-
-            self.egg.install()
-            requirements, ws = self.egg.working_set()
-
-            # install subprograms and ctl scripts
-            server_module = server_types[options['servers']][0]
-            extra_paths = options.get('extra-paths', '')
-            zc.buildout.easy_install.scripts(
-                [('runzope', server_module, 'main')],
-                ws, options['executable'], dest,
-                extra_paths = extra_paths.split(),
-                relative_paths=self.egg._relative_paths,
-                )
-
-            options['extra-paths'] = extra_paths + '\n' + this_loc
-
-            initialization = 'import %s\n' % server_module
-            arguments = 'main_module=%s' % server_module
-            zc.buildout.easy_install.scripts(
-                [('debugzope', 'zc.zope3recipes.debugzope', 'debug')],
-                ws, options['executable'], dest,
-                extra_paths = options['extra-paths'].split(),
-                initialization = initialization,
-                arguments = arguments,
-                relative_paths=self.egg._relative_paths,
-                )
-
-            ftesting_zcml = options.get('ftesting.zcml')
-            if ftesting_zcml:
-                open(os.path.join(dest, 'ftesting.zcml'), 'w'
-                     ).write(site_zcml_template % ftesting_zcml)
-                open(os.path.join(dest, 'ftesting-base.zcml'), 'w'
-                     ).write(ftesting_base)
-
-            return dest
-
-        except:
-            if created:
-                shutil.rmtree(dest)
-            raise
-
-        return dest
-
-    def update(self):
-        self.install()
-
-class App(Application):
-
-    def __init__(self, buildout, name, options):
-        super(App, self).__init__(buildout, name, options)
-
-        location = buildout[options.get('zope3', 'zope3')]['location']
-        if location:
-            options['zope3-location'] = os.path.join(
-                buildout['buildout']['directory'],
-                location,
-                )
-
-    def install(self):
-        options = self.options
-        z3path = options.get('zope3-location')
-        logger = logging.getLogger(self.name)
-        if z3path is not None:
-            if not os.path.exists(z3path):
-                logger.error("The directory, %r, doesn't exist." % z3path)
-                raise zc.buildout.UserError("No directory:", z3path)
-
-            path = os.path.join(z3path, 'lib', 'python')
-            if not os.path.exists(path):
-                path = os.path.join(z3path, 'src')
-                if not os.path.exists(path):
-                    logger.error(
-                        "The directory, %r, isn't a valid checkout or release."
-                        % z3)
-                    raise zc.buildout.UserError(
-                        "Invalid Zope 3 installation:", z3path)
-
-            extra = options.get('extra-paths')
-            if extra:
-                extra += '\n' + path
-            else:
-                extra = path
-            options['extra-paths'] = extra
-
-        return super(App, self).install()
-
-site_zcml_template = """\
-<configure xmlns='http://namespaces.zope.org/zope'
-           xmlns:meta="http://namespaces.zope.org/meta"
-           >
-%s
-</configure>
-"""
-
-class Instance:
-
-    deployment = None
-
-    def __init__(self, buildout, name, options):
-        self.name, self.options = options.get('name', name), options
-
-        for section in options.get('extends', '').split():
-            options.update(
-                [(k, v) for (k, v) in buildout[section].items()
-                 if k not in options
-                 ])
-
-        options['application-location'] = buildout[options['application']
-                                                   ]['location']
-
-        options['scripts'] = ''
-        options['servers'] = buildout[options['application']]['servers']
-        options['eggs'] = options.get('eggs', 'zdaemon\nsetuptools')
-        self.egg = zc.recipe.egg.Egg(buildout, name, options)
-
-        deployment = options.get('deployment')
-        if deployment:
-            # Note we use get below to work with old zc.recipe.deployment eggs.
-            self.deployment = buildout[deployment].get('name', deployment)
-
-            options['bin-directory'] = buildout[deployment]['rc-directory']
-            options['run-directory'] = buildout[deployment]['run-directory']
-            options['log-directory'] = buildout[deployment]['log-directory']
-            options['etc-directory'] = buildout[deployment]['etc-directory']
-            options['logrotate-directory'] = buildout[deployment][
-                'logrotate-directory']
-            options['user'] = buildout[deployment]['user']
-        else:
-            options['bin-directory'] = buildout['buildout']['bin-directory']
-            options['run-directory'] = os.path.join(
-                buildout['buildout']['parts-directory'],
-                name,
-                )
-
-    def install(self):
-        options = self.options
-        run_directory = options['run-directory']
-        deployment = self.deployment
-        if deployment:
-            zope_conf_path = os.path.join(options['etc-directory'],
-                                          self.name+'-zope.conf')
-            zdaemon_conf_path = os.path.join(options['etc-directory'],
-                                             self.name+'-zdaemon.conf')
-            event_log_path = os.path.join(options['log-directory'],
-                                          self.name+'-z3.log')
-            access_log_path = os.path.join(options['log-directory'],
-                                           self.name+'-access.log')
-            socket_path = os.path.join(run_directory,
-                                       self.name+'-zdaemon.sock')
-            rc = deployment + '-' + self.name
-            logrotate_path = os.path.join(options['logrotate-directory'],
-                                          rc)
-            creating = [zope_conf_path, zdaemon_conf_path,
-                        os.path.join(options['bin-directory'], rc),
-                        ]
-            logrotate_conf = options.get("logrotate.conf")
-            if isinstance(logrotate_conf, basestring):
-                if logrotate_conf.strip():
-                    creating.append(logrotate_path)
-                else:
-                    logrotate_conf = None
-            else:
-                logrotate_conf = logrotate_template % dict(
-                    logfile=event_log_path,
-                    rc=os.path.join(options['bin-directory'], rc),
-                    conf=zdaemon_conf_path,
-                )
-                creating.append(logrotate_path)
-        else:
-            zope_conf_path = os.path.join(run_directory, 'zope.conf')
-            zdaemon_conf_path = os.path.join(run_directory, 'zdaemon.conf')
-            event_log_path = os.path.join(run_directory, 'z3.log')
-            access_log_path = os.path.join(run_directory, 'access.log')
-            socket_path = os.path.join(run_directory, 'zdaemon.sock')
-            rc = self.name
-            creating = [run_directory,
-                        os.path.join(options['bin-directory'], rc),
-                        ]
-            if not os.path.exists(run_directory):
-                os.mkdir(run_directory)
-
-        try:
-            app_loc = options['application-location']
-
-            zope_conf = options.get('zope.conf', '')+'\n'
-            zope_conf = ZConfig.schemaless.loadConfigFile(
-                cStringIO.StringIO(zope_conf))
-
-            if 'site-definition' not in zope_conf:
-                zope_conf['site-definition'] = [
-                    os.path.join(app_loc, 'site.zcml')
-                    ]
-
-            server_type = server_types[options['servers']][1]
-            for address in options.get('address', '').split():
-                zope_conf.sections.append(
-                    ZConfig.schemaless.Section(
-                        'server',
-                        data=dict(type=[server_type], address=[address]))
-                    )
-            if not [s for s in zope_conf.sections
-                    if ('server' in s.type)]:
-                zope_conf.sections.append(
-                    ZConfig.schemaless.Section(
-                        'server',
-                        data=dict(type=[server_type], address=['8080']))
-                    )
-
-            if not [s for s in zope_conf.sections if s.type == 'zodb']:
-                raise zc.buildout.UserError(
-                    'No database sections have been defined.')
-
-            if not [s for s in zope_conf.sections if s.type == 'accesslog']:
-                zope_conf.sections.append(access_log(access_log_path))
-
-            if not [s for s in zope_conf.sections if s.type == 'eventlog']:
-                zope_conf.sections.append(event_log('STDOUT'))
-
-
-            zdaemon_conf = options.get('zdaemon.conf', '')+'\n'
-            zdaemon_conf = ZConfig.schemaless.loadConfigFile(
-                cStringIO.StringIO(zdaemon_conf))
-
-            defaults = {
-                'program': "%s -C %s" % (os.path.join(app_loc, 'runzope'),
-                                         zope_conf_path,
-                                         ),
-                'daemon': 'on',
-                'transcript': event_log_path,
-                'socket-name': socket_path,
-                'directory' : run_directory,
-                }
-            if deployment:
-                defaults['user'] = options['user']
-            runner = [s for s in zdaemon_conf.sections
-                      if s.type == 'runner']
-            if runner:
-                runner = runner[0]
-            else:
-                runner = ZConfig.schemaless.Section('runner')
-                zdaemon_conf.sections.insert(0, runner)
-            for name, value in defaults.items():
-                if name not in runner:
-                    runner[name] = [value]
-
-            if not [s for s in zdaemon_conf.sections
-                    if s.type == 'eventlog']:
-                # No database, specify a default one
-                zdaemon_conf.sections.append(event_log2(event_log_path))
-
-            zdaemon_conf = str(zdaemon_conf)
-
-            self.egg.install()
-            requirements, ws = self.egg.working_set()
-
-            open(zope_conf_path, 'w').write(str(zope_conf))
-            open(zdaemon_conf_path, 'w').write(str(zdaemon_conf))
-
-            if deployment and logrotate_conf:
-                open(logrotate_path, 'w').write(logrotate_conf)
-
-            # XXX: We are using a private zc.buildout.easy_install
-            # function below.  It would be better if self.egg had a
-            # method to install scripts.  All recipe options and
-            # relative path information would be available to the egg
-            # instance and the recipe would have no need to call
-            # zc.buildout.easy_install.scripts directly.  Since that
-            # requires changes to zc.recipe.egg/zc.buildout we are
-            # fixing our immediate need to generate correct relative
-            # paths by using the private API.
-            # This should be done "right" in the future.
-            if self.egg._relative_paths:
-                arg_paths = (
-                    os.path.join(app_loc, 'debugzope'),
-                    zope_conf_path,
-                    zdaemon_conf_path,
-                    )
-                spath, x = zc.buildout.easy_install._relative_path_and_setup(
-                    os.path.join(options['bin-directory'], 'ctl'),
-                    arg_paths,
-                    self.egg._relative_paths,
-                    )
-                rpath = spath.split(',\n  ')
-                debugzope_loc, zope_conf_path, zdaemon_conf_path = rpath
-                arguments = ('['
-                             '\n        %s,'
-                             '\n        %s,'
-                             '\n        %r, %s,'
-                             '\n        ]+sys.argv[1:]'
-                             '\n        '
-                             % (debugzope_loc,
-                                zope_conf_path,
-                                '-C', zdaemon_conf_path,
-                                )
-                             )
-            else:
-                arguments = ('['
-                             '\n        %r,'
-                             '\n        %r,'
-                             '\n        %r, %r,'
-                             '\n        ]+sys.argv[1:]'
-                             '\n        '
-                             % (os.path.join(app_loc, 'debugzope'),
-                                zope_conf_path,
-                                '-C', zdaemon_conf_path,
-                                )
-                             )
-
-            if WIN:
-                zc.buildout.easy_install.scripts(
-                    [(rc, 'zc.zope3recipes.winctl', 'main')],
-                    ws, options['executable'], options['bin-directory'],
-                    extra_paths=[this_loc],
-                    arguments=arguments,
-                    relative_paths=self.egg._relative_paths,
-                    )
-            else:
-                zc.buildout.easy_install.scripts(
-                    [(rc, 'zc.zope3recipes.ctl', 'main')],
-                    ws, options['executable'], options['bin-directory'],
-                    extra_paths=[this_loc],
-                    arguments=arguments,
-                    relative_paths=self.egg._relative_paths,
-                    )
-
-            return creating
-
-        except:
-            for f in creating:
-                if os.path.isdir(f):
-                    shutil.rmtree(f)
-                elif os.path.exists(f):
-                    os.remove(f)
-            raise
-
-
-    update = install
-
-def access_log(path):
-    return ZConfig.schemaless.Section(
-        'accesslog', '',
-        sections=[ZConfig.schemaless.Section('logfile', '', dict(path=[path]))]
-        )
-
-def event_log(path, *data):
-    return ZConfig.schemaless.Section(
-        'eventlog', '', None,
-        [ZConfig.schemaless.Section(
-             'logfile',
-             '',
-             dict(path=[path], formatter=['zope.exceptions.log.Formatter'])),
-         ])
-
-def event_log2(path, *data):
-    return ZConfig.schemaless.Section(
-        'eventlog', '', None,
-        [ZConfig.schemaless.Section(
-             'logfile',
-             '',
-             dict(path=[path])),
-         ])
-
-
-logrotate_template = """%(logfile)s {
-  rotate 5
-  weekly
-  postrotate
-    %(rc)s reopen_transcript
-  endscript
-}
-"""
-
-
-ftesting_base = """
-<configure
-   xmlns="http://namespaces.zope.org/zope"
-   i18n_domain="zope"
-   >
-  <include package="zope.app" />
-  <include package="zope.app" file="ftesting.zcml" />
-  <include package="zope.app.securitypolicy" file="meta.zcml" />
-  <include package="zope.app.securitypolicy" />
-  <securityPolicy
-    component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
-  <role id="zope.Anonymous" title="Everybody"
-                 description="All users have this role implicitly" />
-  <role id="zope.Manager" title="Site Manager" />
-  <role id="zope.Member" title="Site Member" />
-  <grant permission="zope.View"
-                  role="zope.Anonymous" />
-  <grant permission="zope.app.dublincore.view"
-                  role="zope.Anonymous" />
-  <grantAll role="zope.Manager" />
-  <include package="zope.app.securitypolicy.tests"
-           file="functional.zcml" />
-  <unauthenticatedPrincipal
-      id="zope.anybody"
-      title="Unauthenticated User"
-      />
-  <unauthenticatedGroup
-    id="zope.Anybody"
-    title="Unauthenticated Users"
-    />
-  <authenticatedGroup
-    id="zope.Authenticated"
-    title="Authenticated Users"
-    />
-  <everybodyGroup
-    id="zope.Everybody"
-    title="All Users"
-    />
-  <principal
-      id="zope.mgr"
-      title="Manager"
-      login="mgr"
-      password="mgrpw" />
-  <principal
-      id="zope.globalmgr"
-      title="Manager"
-      login="globalmgr"
-      password="globalmgrpw" />
-  <grant role="zope.Manager" principal="zope.globalmgr" />
-</configure>
-"""

Copied: zc.zope3recipes/tags/0.13.0/zc/zope3recipes/recipes.py (from rev 118571, zc.zope3recipes/trunk/zc/zope3recipes/recipes.py)
===================================================================
--- zc.zope3recipes/tags/0.13.0/zc/zope3recipes/recipes.py	                        (rev 0)
+++ zc.zope3recipes/tags/0.13.0/zc/zope3recipes/recipes.py	2010-11-24 17:23:54 UTC (rev 118572)
@@ -0,0 +1,503 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Collected Zope 3 recipes
+"""
+
+import os, sys, shutil
+import logging
+import zc.buildout
+import zc.recipe.egg
+import pkg_resources
+import ZConfig.schemaless
+import cStringIO
+
+this_loc = pkg_resources.working_set.find(
+    pkg_resources.Requirement.parse('zc.zope3recipes')).location
+
+server_types = {
+    # name     (module,                  http-name)
+    'twisted': ('zope.app.twisted.main', 'HTTP'),
+    'zserver': ('zope.app.server.main',  'WSGI-HTTP'),
+    }
+
+WIN = False
+if sys.platform[:3].lower() == "win":
+    WIN = True
+
+class Application(object):
+
+    def __init__(self, buildout, name, options):
+        self.options = options
+        self.name = name
+
+        options['location'] = os.path.join(
+            buildout['buildout']['parts-directory'],
+            name,
+            )
+
+        options['servers'] = options.get('servers', 'twisted')
+        if options['servers'] not in server_types:
+            raise ValueError(
+                'servers setting must be one of "twisted" or "zserver"')
+
+        options['scripts'] = ''
+        self.egg = zc.recipe.egg.Egg(buildout, name, options)
+
+    def install(self):
+        options = self.options
+
+        dest = options['location']
+        if not os.path.exists(dest):
+            os.mkdir(dest)
+            created = True
+        else:
+            created = False
+
+        try:
+            open(os.path.join(dest, 'site.zcml'), 'w').write(
+                site_zcml_template % self.options['site.zcml']
+                )
+
+            self.egg.install()
+            requirements, ws = self.egg.working_set()
+
+            # install subprograms and ctl scripts
+            server_module = server_types[options['servers']][0]
+            extra_paths = options.get('extra-paths', '')
+            initialization = options.get('initialization') or ''
+            zc.buildout.easy_install.scripts(
+                [('runzope', server_module, 'main')],
+                ws, options['executable'], dest,
+                extra_paths=extra_paths.split(),
+                initialization=initialization,
+                relative_paths=self.egg._relative_paths,
+                )
+
+            options['extra-paths'] = extra_paths + '\n' + this_loc
+
+            initialization = options.get('debug-initialization')
+            if initialization is None:
+                initialization = options.get('initialization')
+            if initialization:
+                initialization += '\n'
+            else:
+                initialization = ''
+            initialization += 'import %s\n' % server_module
+            arguments = 'main_module=%s' % server_module
+            zc.buildout.easy_install.scripts(
+                [('debugzope', 'zc.zope3recipes.debugzope', 'debug')],
+                ws, options['executable'], dest,
+                extra_paths = options['extra-paths'].split(),
+                initialization = initialization,
+                arguments = arguments,
+                relative_paths=self.egg._relative_paths,
+                )
+
+            ftesting_zcml = options.get('ftesting.zcml')
+            if ftesting_zcml:
+                open(os.path.join(dest, 'ftesting.zcml'), 'w'
+                     ).write(site_zcml_template % ftesting_zcml)
+                open(os.path.join(dest, 'ftesting-base.zcml'), 'w'
+                     ).write(ftesting_base)
+
+            return dest
+
+        except:
+            if created:
+                shutil.rmtree(dest)
+            raise
+
+        return dest
+
+    def update(self):
+        self.install()
+
+class App(Application):
+
+    def __init__(self, buildout, name, options):
+        super(App, self).__init__(buildout, name, options)
+
+        location = buildout[options.get('zope3', 'zope3')]['location']
+        if location:
+            options['zope3-location'] = os.path.join(
+                buildout['buildout']['directory'],
+                location,
+                )
+
+    def install(self):
+        options = self.options
+        z3path = options.get('zope3-location')
+        logger = logging.getLogger(self.name)
+        if z3path is not None:
+            if not os.path.exists(z3path):
+                logger.error("The directory, %r, doesn't exist." % z3path)
+                raise zc.buildout.UserError("No directory:", z3path)
+
+            path = os.path.join(z3path, 'lib', 'python')
+            if not os.path.exists(path):
+                path = os.path.join(z3path, 'src')
+                if not os.path.exists(path):
+                    logger.error(
+                        "The directory, %r, isn't a valid checkout or release."
+                        % z3path)
+                    raise zc.buildout.UserError(
+                        "Invalid Zope 3 installation:", z3path)
+
+            extra = options.get('extra-paths')
+            if extra:
+                extra += '\n' + path
+            else:
+                extra = path
+            options['extra-paths'] = extra
+
+        return super(App, self).install()
+
+site_zcml_template = """\
+<configure xmlns='http://namespaces.zope.org/zope'
+           xmlns:meta="http://namespaces.zope.org/meta"
+           >
+%s
+</configure>
+"""
+
+class Instance:
+
+    deployment = None
+
+    def __init__(self, buildout, name, options):
+        self.name, self.options = options.get('name', name), options
+
+        for section in options.get('extends', '').split():
+            options.update(
+                [(k, v) for (k, v) in buildout[section].items()
+                 if k not in options
+                 ])
+
+        options['application-location'] = buildout[options['application']
+                                                   ]['location']
+
+        options['scripts'] = ''
+        options['servers'] = buildout[options['application']]['servers']
+        options['eggs'] = options.get('eggs', 'zdaemon\nsetuptools')
+        self.egg = zc.recipe.egg.Egg(buildout, name, options)
+
+        deployment = options.get('deployment')
+        if deployment:
+            # Note we use get below to work with old zc.recipe.deployment eggs.
+            self.deployment = buildout[deployment].get('name', deployment)
+
+            options['bin-directory'] = buildout[deployment]['rc-directory']
+            options['run-directory'] = buildout[deployment]['run-directory']
+            options['log-directory'] = buildout[deployment]['log-directory']
+            options['etc-directory'] = buildout[deployment]['etc-directory']
+            options['logrotate-directory'] = buildout[deployment][
+                'logrotate-directory']
+            options['user'] = buildout[deployment]['user']
+        else:
+            options['bin-directory'] = buildout['buildout']['bin-directory']
+            options['run-directory'] = os.path.join(
+                buildout['buildout']['parts-directory'],
+                name,
+                )
+
+    def install(self):
+        options = self.options
+        run_directory = options['run-directory']
+        deployment = self.deployment
+        if deployment:
+            zope_conf_path = os.path.join(options['etc-directory'],
+                                          self.name+'-zope.conf')
+            zdaemon_conf_path = os.path.join(options['etc-directory'],
+                                             self.name+'-zdaemon.conf')
+            event_log_path = os.path.join(options['log-directory'],
+                                          self.name+'-z3.log')
+            access_log_path = os.path.join(options['log-directory'],
+                                           self.name+'-access.log')
+            socket_path = os.path.join(run_directory,
+                                       self.name+'-zdaemon.sock')
+            rc = deployment + '-' + self.name
+            logrotate_path = os.path.join(options['logrotate-directory'],
+                                          rc)
+            creating = [zope_conf_path, zdaemon_conf_path,
+                        os.path.join(options['bin-directory'], rc),
+                        ]
+            logrotate_conf = options.get("logrotate.conf")
+            if isinstance(logrotate_conf, basestring):
+                if logrotate_conf.strip():
+                    creating.append(logrotate_path)
+                else:
+                    logrotate_conf = None
+            else:
+                logrotate_conf = logrotate_template % dict(
+                    logfile=event_log_path,
+                    rc=os.path.join(options['bin-directory'], rc),
+                    conf=zdaemon_conf_path,
+                )
+                creating.append(logrotate_path)
+        else:
+            zope_conf_path = os.path.join(run_directory, 'zope.conf')
+            zdaemon_conf_path = os.path.join(run_directory, 'zdaemon.conf')
+            event_log_path = os.path.join(run_directory, 'z3.log')
+            access_log_path = os.path.join(run_directory, 'access.log')
+            socket_path = os.path.join(run_directory, 'zdaemon.sock')
+            rc = self.name
+            creating = [run_directory,
+                        os.path.join(options['bin-directory'], rc),
+                        ]
+            if not os.path.exists(run_directory):
+                os.mkdir(run_directory)
+
+        try:
+            app_loc = options['application-location']
+
+            zope_conf = options.get('zope.conf', '')+'\n'
+            zope_conf = ZConfig.schemaless.loadConfigFile(
+                cStringIO.StringIO(zope_conf))
+
+            if 'site-definition' not in zope_conf:
+                zope_conf['site-definition'] = [
+                    os.path.join(app_loc, 'site.zcml')
+                    ]
+
+            server_type = server_types[options['servers']][1]
+            for address in options.get('address', '').split():
+                zope_conf.sections.append(
+                    ZConfig.schemaless.Section(
+                        'server',
+                        data=dict(type=[server_type], address=[address]))
+                    )
+            if not [s for s in zope_conf.sections
+                    if ('server' in s.type)]:
+                zope_conf.sections.append(
+                    ZConfig.schemaless.Section(
+                        'server',
+                        data=dict(type=[server_type], address=['8080']))
+                    )
+
+            if not [s for s in zope_conf.sections if s.type == 'zodb']:
+                raise zc.buildout.UserError(
+                    'No database sections have been defined.')
+
+            if not [s for s in zope_conf.sections if s.type == 'accesslog']:
+                zope_conf.sections.append(access_log(access_log_path))
+
+            if not [s for s in zope_conf.sections if s.type == 'eventlog']:
+                zope_conf.sections.append(event_log('STDOUT'))
+
+
+            zdaemon_conf = options.get('zdaemon.conf', '')+'\n'
+            zdaemon_conf = ZConfig.schemaless.loadConfigFile(
+                cStringIO.StringIO(zdaemon_conf))
+
+            defaults = {
+                'program': "%s -C %s" % (os.path.join(app_loc, 'runzope'),
+                                         zope_conf_path,
+                                         ),
+                'daemon': 'on',
+                'transcript': event_log_path,
+                'socket-name': socket_path,
+                'directory' : run_directory,
+                }
+            if deployment:
+                defaults['user'] = options['user']
+            runner = [s for s in zdaemon_conf.sections
+                      if s.type == 'runner']
+            if runner:
+                runner = runner[0]
+            else:
+                runner = ZConfig.schemaless.Section('runner')
+                zdaemon_conf.sections.insert(0, runner)
+            for name, value in defaults.items():
+                if name not in runner:
+                    runner[name] = [value]
+
+            if not [s for s in zdaemon_conf.sections
+                    if s.type == 'eventlog']:
+                # No database, specify a default one
+                zdaemon_conf.sections.append(event_log2(event_log_path))
+
+            zdaemon_conf = str(zdaemon_conf)
+
+            self.egg.install()
+            requirements, ws = self.egg.working_set()
+
+            open(zope_conf_path, 'w').write(str(zope_conf))
+            open(zdaemon_conf_path, 'w').write(str(zdaemon_conf))
+
+            if deployment and logrotate_conf:
+                open(logrotate_path, 'w').write(logrotate_conf)
+
+            # XXX: We are using a private zc.buildout.easy_install
+            # function below.  It would be better if self.egg had a
+            # method to install scripts.  All recipe options and
+            # relative path information would be available to the egg
+            # instance and the recipe would have no need to call
+            # zc.buildout.easy_install.scripts directly.  Since that
+            # requires changes to zc.recipe.egg/zc.buildout we are
+            # fixing our immediate need to generate correct relative
+            # paths by using the private API.
+            # This should be done "right" in the future.
+            if self.egg._relative_paths:
+                arg_paths = (
+                    os.path.join(app_loc, 'debugzope'),
+                    zope_conf_path,
+                    zdaemon_conf_path,
+                    )
+                spath, x = zc.buildout.easy_install._relative_path_and_setup(
+                    os.path.join(options['bin-directory'], 'ctl'),
+                    arg_paths,
+                    self.egg._relative_paths,
+                    )
+                rpath = spath.split(',\n  ')
+                debugzope_loc, zope_conf_path, zdaemon_conf_path = rpath
+                arguments = ('['
+                             '\n        %s,'
+                             '\n        %s,'
+                             '\n        %r, %s,'
+                             '\n        ]+sys.argv[1:]'
+                             '\n        '
+                             % (debugzope_loc,
+                                zope_conf_path,
+                                '-C', zdaemon_conf_path,
+                                )
+                             )
+            else:
+                arguments = ('['
+                             '\n        %r,'
+                             '\n        %r,'
+                             '\n        %r, %r,'
+                             '\n        ]+sys.argv[1:]'
+                             '\n        '
+                             % (os.path.join(app_loc, 'debugzope'),
+                                zope_conf_path,
+                                '-C', zdaemon_conf_path,
+                                )
+                             )
+
+            if WIN:
+                zc.buildout.easy_install.scripts(
+                    [(rc, 'zc.zope3recipes.winctl', 'main')],
+                    ws, options['executable'], options['bin-directory'],
+                    extra_paths=[this_loc],
+                    arguments=arguments,
+                    relative_paths=self.egg._relative_paths,
+                    )
+            else:
+                zc.buildout.easy_install.scripts(
+                    [(rc, 'zc.zope3recipes.ctl', 'main')],
+                    ws, options['executable'], options['bin-directory'],
+                    extra_paths=[this_loc],
+                    arguments=arguments,
+                    relative_paths=self.egg._relative_paths,
+                    )
+
+            return creating
+
+        except:
+            for f in creating:
+                if os.path.isdir(f):
+                    shutil.rmtree(f)
+                elif os.path.exists(f):
+                    os.remove(f)
+            raise
+
+
+    update = install
+
+def access_log(path):
+    return ZConfig.schemaless.Section(
+        'accesslog', '',
+        sections=[ZConfig.schemaless.Section('logfile', '', dict(path=[path]))]
+        )
+
+def event_log(path, *data):
+    return ZConfig.schemaless.Section(
+        'eventlog', '', None,
+        [ZConfig.schemaless.Section(
+             'logfile',
+             '',
+             dict(path=[path], formatter=['zope.exceptions.log.Formatter'])),
+         ])
+
+def event_log2(path, *data):
+    return ZConfig.schemaless.Section(
+        'eventlog', '', None,
+        [ZConfig.schemaless.Section(
+             'logfile',
+             '',
+             dict(path=[path])),
+         ])
+
+
+logrotate_template = """%(logfile)s {
+  rotate 5
+  weekly
+  postrotate
+    %(rc)s reopen_transcript
+  endscript
+}
+"""
+
+
+ftesting_base = """
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   i18n_domain="zope"
+   >
+  <include package="zope.app" />
+  <include package="zope.app" file="ftesting.zcml" />
+  <include package="zope.app.securitypolicy" file="meta.zcml" />
+  <include package="zope.app.securitypolicy" />
+  <securityPolicy
+    component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+  <role id="zope.Anonymous" title="Everybody"
+                 description="All users have this role implicitly" />
+  <role id="zope.Manager" title="Site Manager" />
+  <role id="zope.Member" title="Site Member" />
+  <grant permission="zope.View"
+                  role="zope.Anonymous" />
+  <grant permission="zope.app.dublincore.view"
+                  role="zope.Anonymous" />
+  <grantAll role="zope.Manager" />
+  <include package="zope.app.securitypolicy.tests"
+           file="functional.zcml" />
+  <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User"
+      />
+  <unauthenticatedGroup
+    id="zope.Anybody"
+    title="Unauthenticated Users"
+    />
+  <authenticatedGroup
+    id="zope.Authenticated"
+    title="Authenticated Users"
+    />
+  <everybodyGroup
+    id="zope.Everybody"
+    title="All Users"
+    />
+  <principal
+      id="zope.mgr"
+      title="Manager"
+      login="mgr"
+      password="mgrpw" />
+  <principal
+      id="zope.globalmgr"
+      title="Manager"
+      login="globalmgr"
+      password="globalmgrpw" />
+  <grant role="zope.Manager" principal="zope.globalmgr" />
+</configure>
+"""



More information about the checkins mailing list