Metadata-Version: 1.0
Name: zc.zope3recipes
Version: 0.5.3
Summary: ZC Buildout recipe for defining Zope 3 applications
Home-page: http://svn.zope.org/zc.zope3recipes
Author: Jim Fulton
Author-email: jim@zope.com
License: ZPL 2.1
Description: **************************************
        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, no Windows support at this time.
        
        .. contents::
        
        Releases
        ********
        
        ==================
        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.
        
        Detailed Documentation
        **********************
        
        =============
        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')
        ... ''')
        
        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 zc.zope3recipes.debugzope
        <BLANKLINE>
        if __name__ == '__main__':
        zc.zope3recipes.debugzope.debug()
        
        
        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 zc.zope3recipes.debugzope
        <BLANKLINE>
        if __name__ == '__main__':
        zc.zope3recipes.debugzope.debug()
        
        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()
        
        
        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>
        
        
        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.
        
        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')
        
        >>> 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-run
        ...
        ... [database]
        ... recipe = zc.recipe.filestorage
        ...
        ... [myapp-run]
        ... etc-directory = %(root)s/etc/myapp-run
        ... rc-directory = %(root)s/etc/init.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-run, 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 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>
        
        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-run
        ...
        ... [instance2]
        ... recipe = zc.zope3recipes:instance
        ... extends = instance
        ... address = 8082
        ...
        ... [database]
        ... recipe = zc.recipe.filestorage
        ...
        ... [myapp-run]
        ... etc-directory = %(root)s/etc/myapp-run
        ... rc-directory = %(root)s/etc/init.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'
        Updating database.
        Updating myapp.
        Updating 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>
        
        Download
        **********************
        
Keywords: zope3 buildout
Platform: UNKNOWN
Classifier: Framework :: Buildout
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Zope Public License
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Libraries :: Python Modules
