[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/StartUp - bootstrap.py:1.1 SiteDefinition.py:1.8

Guido van Rossum guido@python.org
Thu, 12 Dec 2002 15:16:36 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/App/StartUp
In directory cvs.zope.org:/tmp/cvs-serv31869/StartUp

Modified Files:
	SiteDefinition.py 
Added Files:
	bootstrap.py 
Log Message:
Refactored the database bootstrapping code: moved this to a separate
module, and use that both from _InitDB() and from _app.py.  Added a
generic feature to set arbitrary attributes of standard services.
Added the error reporting service to the set of standard services, and
set its 'copy to zlog' flag to True.



=== Added File Zope3/lib/python/Zope/App/StartUp/bootstrap.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Bootstrap code.

This module contains code to bootstrap a Zope3 instance.  For example
it makes sure a root folder exists and creates and configures some
essential services.

$Id: bootstrap.py,v 1.1 2002/12/12 20:16:35 gvanrossum Exp $
"""
from Transaction import get_transaction

from Zope.App.Traversing import traverse, traverseName
from Zope.App.ZopePublication.ZopePublication import ZopePublication
from Zope.App.OFS.Content.Folder.RootFolder import RootFolder
from Zope.App.OFS.Services.ServiceManager.ServiceManager import ServiceManager
from Zope.App.OFS.Services.ServiceManager.ServiceConfiguration import \
     ServiceConfiguration
from Zope.App.OFS.Services.ObjectHub.ObjectHub import ObjectHub
from Zope.App.OFS.Services.LocalEventService.LocalEventService import \
     LocalEventService
from Zope.App.OFS.Services.ErrorReportingService.ErrorReportingService import \
     ErrorReportingService


def bootstrapInstance(db):
    """Bootstrap a Zope3 instance given a database object.

    This first checks if the root folder exists.  If it exists, nothing
    is changed.  If no root folder exists, one is added, and several
    essential services are added and configured.
    """
    connection = db.open()
    root = connection.root()
    root_folder = root.get(ZopePublication.root_name, None)

    if root_folder is None:
        # Bootstrap code

        root_folder = RootFolder()
        addEssentialServices(root_folder)
        root[ZopePublication.root_name] = root_folder

        get_transaction().commit()

    connection.close()


def addEssentialServices(root_folder):
    """Add essential services.

    XXX This ought to be configurable.  For now, hardcode some
    services we know we all need.
    """
    service_manager = ServiceManager()
    root_folder.setServiceManager(service_manager)
    addService(root_folder, 'Events', LocalEventService)
    addService(root_folder, 'ObjectHub', ObjectHub)
    addService(root_folder, 'ErrorReportingService', ErrorReportingService,
               copy_to_zlog=True)


def addService(root_folder, service_type, service_factory,
               initial_status='Active', **kw):
    """Add and configure a service to the root folder.

    The service is added to the default package and activated.
    This assumes the root folder already has a service manager,
    and that we add at most one service of each type.
    """
    # The code here is complicated by the fact that the registry
    # calls at the end require a fully context-wrapped
    # configuration; hence all the traverse[Name]() calls.
    package_name = ('', '++etc++Services', 'Packages', 'default')
    package = traverse(root_folder, package_name)
    name = service_type + '-1'
    service = service_factory()
    package.setObject(name, service)
    configuration_manager = traverseName(package, 'configure')
    configuration =  ServiceConfiguration(service_type,
                                          package_name + (name,))
    key = configuration_manager.setObject(None, configuration)
    configuration = traverseName(configuration_manager, key)
    configuration.status = initial_status
    # Set additional attributes on the service
    for k, v in kw.iteritems():
        setattr(service, k, v)


=== Zope3/lib/python/Zope/App/StartUp/SiteDefinition.py 1.7 => 1.8 ===
--- Zope3/lib/python/Zope/App/StartUp/SiteDefinition.py:1.7	Wed Dec 11 13:07:25 2002
+++ Zope3/lib/python/Zope/App/StartUp/SiteDefinition.py	Thu Dec 12 15:16:35 2002
@@ -24,15 +24,7 @@
 from Zope.Configuration.INonEmptyDirective import INonEmptyDirective
 from Zope.Configuration.ISubdirectiveHandler import ISubdirectiveHandler
 
-# Import classes related to initial-services
-from Zope.App.Traversing import traverse, traverseName
 from ServerTypeRegistry import getServerType
-from Zope.App.OFS.Services.ObjectHub.ObjectHub import ObjectHub
-from Zope.App.OFS.Services.LocalEventService.LocalEventService import \
-     LocalEventService
-from Zope.App.OFS.Services.ServiceManager.ServiceManager import ServiceManager
-from Zope.App.OFS.Services.ServiceManager.ServiceConfiguration import \
-     ServiceConfiguration
 
 # Import Undo-related classes 
 from Zope.ComponentArchitecture import getService
@@ -150,68 +142,11 @@
     def _initDB(self):
         """Initialize the ZODB and persistence module importer."""
 
-        connection = self._zodb.open()
-        root = connection.root()
-        app = root.get(ZopePublication.root_name, None)
-
-        if app is None:
-
-            from Zope.App.OFS.Content.Folder.RootFolder import RootFolder
-            from Transaction import get_transaction
-        
-            app = RootFolder()
-            self._addEssentialServices(app)
-            root[ZopePublication.root_name] = app
-
-            get_transaction().commit()
-
-        connection.close()
+        from Zope.App.StartUp import bootstrap
+        bootstrap.bootstrapInstance(self._zodb)
 
         imp = PersistentModuleImporter()
         imp.install()
-
-
-    def _addEssentialServices(self, root_folder):
-        """Add essential services.
-
-        XXX This ought to be configurable.  For now, hardcode an Event
-        service and an ObjectHub.  I'll refactor later.
-
-        XXX To reiterate, THIS IS AN EXAMPLE ONLY!!!  This code should
-        be generalized.  Preferably, using marker interfaces,
-        adapters, and a factory or two.  Oh, and don't forget
-        metameta.zcml. :-)
-        """
-
-        sm = ServiceManager()
-        root_folder.setServiceManager(sm)
-        self._addService(root_folder, 'Events', LocalEventService)
-        self._addService(root_folder, 'ObjectHub', ObjectHub)
-
-
-    def _addService(self, root_folder, service_type, service_factory,
-                    initial_status='Active'):
-        """Add and configure a service to the root folder.
-
-        The service is added to the default package and activated.
-        This assumes the root folder already has a service manager,
-        and that we add at most one service of each type.
-        """
-        # The code here is complicated by the fact that the registry
-        # calls at the end require a fully context-wrapped
-        # configuration; hence all the traverse[Name]() calls.
-        # XXX Could we use the factory registry instead of the 3rd arg?
-        package_name = ('', '++etc++Services', 'Packages', 'default')
-        package = traverse(root_folder, package_name)
-        name = service_type + '-1'
-        service = service_factory()
-        package.setObject(name, service)
-        configuration_manager = traverseName(package, 'configure')
-        configuration =  ServiceConfiguration(service_type,
-                                              package_name + (name,))
-        key = configuration_manager.setObject(None, configuration)
-        configuration = traverseName(configuration_manager, key)
-        configuration.status = initial_status
 
 
     def __call__(self):