[Zope-Checkins] CVS: Zope/lib/python/OFS - Application.py:1.191.2.7
Chris McDonough
chrism at zopemafia.com
Sat Dec 20 13:11:12 EST 2003
Update of /cvs-repository/Zope/lib/python/OFS
In directory cvs.zope.org:/tmp/cvs-serv8966
Modified Files:
Tag: Zope-2_7-branch
Application.py
Log Message:
Overhaul how the Application object is initialized (replace long function with a somewhat structured recipe). Include tests for initializer functionality.
Backport a small change from the HEAD (assign to
Folder.Folder.__ac_permissions__ instead of Folder.Folder.__dict__['__ac_permissions__'] for parity between 2.7 branch and HEAD.
=== Zope/lib/python/OFS/Application.py 1.191.2.6 => 1.191.2.7 ===
--- Zope/lib/python/OFS/Application.py:1.191.2.6 Thu Dec 11 14:45:02 2003
+++ Zope/lib/python/OFS/Application.py Sat Dec 20 13:10:41 2003
@@ -33,6 +33,7 @@
from HelpSys.HelpSys import HelpSys
from Acquisition import aq_base
from App.Product import doInstall
+from App.config import getConfiguration
class Application(Globals.ApplicationDefaultPermissions,
ZDOM.Root, Folder.Folder,
@@ -65,6 +66,8 @@
# Set the universal default method to index_html
_object_manager_browser_default_id = 'index_html'
+ _initializer_registry = None
+
def title_and_id(self): return self.title
def title_or_id(self): return self.title
@@ -240,6 +243,19 @@
return 1
return 0
+ _setInitializerRegistry__roles__ = ()
+ def _setInitializerFlag(self, flag):
+ if self._initializer_registry is None:
+ self._initializer_registry = {}
+ self._initializer_registry[flag] = 1
+
+ _getInitializerRegistry__roles__ = ()
+ def _getInitializerFlag(self, flag):
+ reg = self._initializer_registry
+ if reg is None:
+ reg = {}
+ return reg.get(flag)
+
class Expired(Globals.Persistent):
icon='p_/broken'
@@ -258,225 +274,317 @@
__inform_commit__=__save__
def initialize(app):
- # Initialize the application
+ initializer = AppInitializer(app)
+ initializer.initialize()
- # The following items marked b/c are backward compatibility hacks
- # which make sure that expected system objects are added to the
- # bobobase. This is required because the bobobase in use may pre-
- # date the introduction of certain system objects such as those
- # which provide Lever support.
+class AppInitializer:
+ """ Initialze an Application object (called at startup) """
- # b/c: Ensure that Control Panel exists.
- if not hasattr(app, 'Control_Panel'):
- cpl=ApplicationManager()
- cpl._init()
- app._setObject('Control_Panel', cpl)
- get_transaction().note('Added Control_Panel')
- get_transaction().commit()
+ def __init__(self, app):
+ self.app = (app,)
+
+ def getApp(self):
+ # this is probably necessary, but avoid acquisition anyway
+ return self.app[0]
- # b/c: Ensure that a ProductFolder exists.
- if not hasattr(aq_base(app.Control_Panel), 'Products'):
- app.Control_Panel.Products=App.Product.ProductFolder()
- get_transaction().note('Added Control_Panel.Products')
+ def commit(self, note):
+ get_transaction().note(note)
get_transaction().commit()
+
+ def initialize(self):
+ app = self.getApp()
+ # make sure to preserve relative ordering of calls below.
+ self.install_cp_and_products()
+ self.install_tempfolder_and_sdc()
+ self.install_session_data_manager()
+ self.install_browser_id_manager()
+ self.install_required_roles()
+ self.install_zglobals()
+ self.install_inituser()
+ self.install_errorlog()
+ self.install_products()
+ self.install_standards()
+ self.check_zglobals()
+
+ def install_cp_and_products(self):
+ app = self.getApp()
+
+ # Ensure that Control Panel exists.
+ if not hasattr(app, 'Control_Panel'):
+ cpl=ApplicationManager()
+ cpl._init()
+ app._setObject('Control_Panel', cpl)
+ self.commit('Added Control_Panel')
+
+ # b/c: Ensure that a ProductFolder exists.
+ if not hasattr(aq_base(app.Control_Panel), 'Products'):
+ app.Control_Panel.Products=App.Product.ProductFolder()
+ self.commit('Added Control_Panel.Products')
+
+ def install_tempfolder_and_sdc(self):
+ app = self.getApp()
+ from Products.ZODBMountPoint.MountedObject import manage_addMounts,\
+ MountedObject
+ from Products.ZODBMountPoint.MountedObject import getConfiguration as \
+ getDBTabConfiguration
+
+ dbtab_config = getDBTabConfiguration()
+
+ tf = getattr(app, 'temp_folder', None)
+
+ if getattr(tf, 'meta_type', None) == MountedObject.meta_type:
+ # tf is a MountPoint object. This means that the temp_folder
+ # couldn't be mounted properly (the meta_type would have been
+ # the meta type of the container class otherwise). The
+ # MountPoint object writes a message to zLOG so we don't
+ # need to.
+ return
+
+ if tf is None:
+ # do nothing if we've already installed one
+ if not app._getInitializerFlag('temp_folder'):
+ if dbtab_config is None:
+ # DefaultConfiguration, do nothing
+ return
+ mount_paths = [ x[0] for x in dbtab_config.listMountPaths() ]
+ if not '/temp_folder' in mount_paths:
+ # we won't be able to create the mount point properly
+ LOG('Zope Default Object Creation', ERROR,
+ ('Could not initialze a Temporary Folder because '
+ 'a database was not configured to be mounted at '
+ 'the /temp_folder mount point'))
+ return
+ try:
+ manage_addMounts(app, ('/temp_folder',))
+ app._setInitializerFlag('temp_folder')
+ self.commit('Added temp_folder')
+ tf = app.temp_folder
+ except:
+ LOG('Zope Default Object Creation', ERROR,
+ ('Could not add a /temp_folder mount point due to an '
+ 'error.'),
+ error=sys.exc_info())
+ return
+
+ # Ensure that there is a transient object container in the temp folder
+ config = getConfiguration()
+
+ if not hasattr(aq_base(tf), 'session_data'):
+ from Products.Transience.Transience import TransientObjectContainer
+ addnotify = getattr(config, 'session_add_notify_script_path', None)
+ delnotify = getattr(config, 'session_delete_notify_script_path',
+ None)
+ default_limit = 1000
+ limit = (getattr(config, 'maximum_number_of_session_objects', None)
+ or default_limit)
+ timeout_spec = getattr(config, 'session_timeout_minutes', None)
+
+ if addnotify and app.unrestrictedTraverse(addnotify, None) is None:
+ LOG('Zope Default Object Creation', WARNING,
+ ('failed to use nonexistent "%s" script as '
+ 'session-add-notify-script-path' % addnotify))
+ addnotify=None
+
+ if delnotify and app.unrestrictedTraverse(delnotify, None) is None:
+ LOG('Zope Default Object Creation', WARNING,
+ ('failed to use nonexistent "%s" script as '
+ 'session-delete-notify-script-path' % delnotify))
+ delnotify=None
+
+ toc = TransientObjectContainer(
+ 'session_data', 'Session Data Container',
+ addNotification = addnotify,
+ delNotification = delnotify,
+ limit=limit)
+
+ if timeout_spec:
+ toc = TransientObjectContainer('session_data',
+ 'Session Data Container',
+ timeout_mins = timeout_spec,
+ addNotification = addnotify,
+ delNotification = delnotify,
+ limit=limit)
+
+ tf._setObject('session_data', toc)
+ tf_reserved = getattr(tf, '_reserved_names', ())
+ if 'session_data' not in tf_reserved:
+ tf._reserved_names = tf_reserved + ('session_data',)
+ self.commit('Added session_data to temp_folder')
+ return tf # return the tempfolder object for test purposes
+
+ def install_browser_id_manager(self):
+ app = self.getApp()
+ if app._getInitializerFlag('browser_id_manager'):
+ # do nothing if we've already installed one
+ return
+ # Ensure that a browser ID manager exists
+ if not hasattr(app, 'browser_id_manager'):
+ from Products.Sessions.BrowserIdManager import BrowserIdManager
+ bid = BrowserIdManager('browser_id_manager', 'Browser Id Manager')
+ app._setObject('browser_id_manager', bid)
+ app._setInitializerFlag('browser_id_manager')
+ self.commit('Added browser_id_manager')
+
+ def install_session_data_manager(self):
+ app = self.getApp()
+ if app._getInitializerFlag('session_data_manager'):
+ # do nothing if we've already installed one
+ return
+ # Ensure that a session data manager exists
+ if not hasattr(app, 'session_data_manager'):
+ from Products.Sessions.SessionDataManager import SessionDataManager
+ sdm = SessionDataManager('session_data_manager',
+ title='Session Data Manager',
+ path='/temp_folder/session_data',
+ requestName='SESSION')
+ app._setObject('session_data_manager', sdm)
+ app._setInitializerFlag('session_data_manager')
+ self.commit('Added session_data_manager')
+
+ def install_required_roles(self):
+ app = self.getApp()
+
+ # Ensure that Owner role exists.
+ if hasattr(app, '__ac_roles__') and not ('Owner' in app.__ac_roles__):
+ app.__ac_roles__=app.__ac_roles__ + ('Owner',)
+ self.commit('Added Owner role')
+
+ # ensure the Authenticated role exists.
+ if hasattr(app, '__ac_roles__'):
+ if not 'Authenticated' in app.__ac_roles__:
+ app.__ac_roles__=app.__ac_roles__ + ('Authenticated',)
+ self.commit('Added Authenticated role')
+
+ def install_zglobals(self):
+ app = self.getApp()
+
+ # Make sure we have ZGlobals
+ root=app._p_jar.root()
+ if not root.has_key('ZGlobals'):
+ from BTrees.OOBTree import OOBTree
+ root['ZGlobals'] = OOBTree()
+ self.commit('Added ZGlobals')
+
+ def install_inituser(self):
+ app = self.getApp()
+
+ # Install the initial user.
+ if hasattr(app, 'acl_users'):
+ users = app.acl_users
+ if hasattr(users, '_createInitialUser'):
+ app.acl_users._createInitialUser()
+ self.commit('Created initial user')
+
+ def install_errorlog(self):
+ app = self.getApp()
+ if app._getInitializerFlag('error_log'):
+ # do nothing if we've already installed one
+ return
+
+ # Install an error_log
+ if not hasattr(app, 'error_log'):
+ from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog
+ error_log = SiteErrorLog()
+ app._setObject('error_log', error_log)
+ app._setInitializerFlag('error_log')
+ self.commit('Added site error_log at /error_log')
+
+ def check_zglobals(self):
+ if not doInstall():
+ return
+
+ app = self.getApp()
+
+ # Check for dangling pointers (broken zclass dependencies) in the
+ # global class registry. If found, rebuild the registry. Note that
+ # if the check finds problems but fails to successfully rebuild the
+ # registry we abort the transaction so that we don't leave it in an
+ # indeterminate state.
- # Ensure that a temp folder exists
- if not hasattr(app, 'temp_folder'):
- from Products.ZODBMountPoint.MountedObject import manage_addMounts
+ did_fixups=0
+ bad_things=0
try:
- manage_addMounts(app, ('/temp_folder',))
- get_transaction().note('Added temp_folder')
- get_transaction().commit()
+ if app.checkGlobalRegistry():
+ LOG('Zope', INFO,
+ 'Beginning attempt to rebuild the global ZClass registry.')
+ app.fixupZClassDependencies(rebuild=1)
+ did_fixups=1
+ LOG('Zope', INFO,
+ 'The global ZClass registry has successfully been rebuilt.')
+ get_transaction().note('Rebuilt global product registry')
+ get_transaction().commit()
except:
- LOG('Zope Default Object Creation', ERROR,
- 'Could not add a /temp_folder mount point due to an error.',
+ bad_things=1
+ LOG('Zope', ERROR, 'The attempt to rebuild the registry failed.',
error=sys.exc_info())
+ get_transaction().abort()
- # Ensure that there is a transient container in the temp folder
- tf = getattr(app, 'temp_folder', None)
- if tf is not None and not hasattr(aq_base(tf), 'session_data'):
- env_has = os.environ.get
- from Products.Transience.Transience import TransientObjectContainer
- addnotify = env_has('ZSESSION_ADD_NOTIFY', None)
- delnotify = env_has('ZSESSION_DEL_NOTIFY', None)
- default_limit = 1000
- limit = env_has('ZSESSION_OBJECT_LIMIT', default_limit)
- try:
- limit=int(limit)
- if limit != default_limit:
- LOG('Zope Default Object Creation', INFO,
- ('using ZSESSION_OBJECT_LIMIT-specified max objects '
- 'value of %s' % limit))
- except ValueError:
- LOG('Zope Default Object Creation', WARNING,
- ('Noninteger value %s specified for ZSESSION_OBJECT_LIMIT, '
- 'defaulting to %s' % (limit, default_limit)))
- limit = default_limit
- if addnotify and app.unrestrictedTraverse(addnotify, None) is None:
- LOG('Zope Default Object Creation', WARNING,
- ('failed to use nonexistent "%s" script as '
- 'ZSESSION_ADD_NOTIFY' % addnotify))
- addnotify=None
- elif addnotify:
- LOG('Zope Default Object Creation', INFO,
- 'using %s as add notification script' % addnotify)
- if delnotify and app.unrestrictedTraverse(delnotify, None) is None:
- LOG('Zope Default Object Creation', WARNING,
- ('failed to use nonexistent "%s" script as '
- 'ZSESSION_DEL_NOTIFY' % delnotify))
- delnotify=None
- elif delnotify:
- LOG('Zope Default Object Creation', INFO,
- 'using %s as delete notification script' % delnotify)
-
- toc = TransientObjectContainer('session_data',
- 'Session Data Container', addNotification = addnotify,
- delNotification = delnotify, limit=limit)
- timeout_spec = env_has('ZSESSION_TIMEOUT_MINS', '')
- if timeout_spec:
- try:
- timeout_spec = int(timeout_spec)
- except ValueError:
- LOG('Zope Default Object Creation', WARNING,
- ('"%s" is an illegal value for ZSESSION_TIMEOUT_MINS, '
- 'using default timeout instead.' % timeout_spec))
- else:
- LOG('Zope Default Object Creation', INFO,
- ('using ZSESSION_TIMEOUT_MINS-specified session timeout '
- 'value of %s' % timeout_spec))
- toc = TransientObjectContainer('session_data',
- 'Session Data Container', timeout_mins = timeout_spec,
- addNotification=addnotify, delNotification = delnotify,
- limit=limit)
- tf._setObject('session_data', toc)
- tf_reserved = getattr(tf, '_reserved_names', ())
- if 'session_data' not in tf_reserved:
- tf._reserved_names = tf_reserved + ('session_data',)
- get_transaction().note('Added session_data to temp_folder')
- get_transaction().commit()
- del toc
- del addnotify
- del delnotify
- del timeout_spec
- del env_has
-
- del tf
-
- # Ensure that a browser ID manager exists
- if not hasattr(app, 'browser_id_manager'):
- from Products.Sessions.BrowserIdManager import BrowserIdManager
- bid = BrowserIdManager('browser_id_manager', 'Browser Id Manager')
- app._setObject('browser_id_manager', bid)
- get_transaction().note('Added browser_id_manager')
- get_transaction().commit()
- del bid
+ # Now we need to see if any (disk-based) products were installed
+ # during intialization. If so (and the registry has no errors),
+ # there may still be zclasses dependent on a base class in the
+ # newly installed product that were previously broken and need to
+ # be fixed up. If any really Bad Things happened (dangling pointers
+ # were found in the registry but it couldn't be rebuilt), we don't
+ # try to do anything to avoid making the problem worse.
+ if (not did_fixups) and (not bad_things):
+
+ # App.Product.initializeProduct will set this if a disk-based
+ # product was added or updated and we are not a ZEO client.
+ if getattr(Globals, '__disk_product_installed__', None):
+ try:
+ LOG('Zope', INFO,
+ ('New disk product detected, determining if we need '
+ 'to fix up any ZClasses.'))
+ if app.fixupZClassDependencies():
+ LOG('Zope',INFO,
+ 'Repaired broken ZClass dependencies.')
+ self.commit('Repaired broked ZClass dependencies')
+ except:
+ LOG('Zope', ERROR,
+ ('Attempt to fixup ZClass dependencies after '
+ 'detecting an updated disk-based product failed.'),
+ error=sys.exc_info())
+ get_transaction().abort()
- # Ensure that a session data manager exists
- if not hasattr(app, 'session_data_manager'):
- from Products.Sessions.SessionDataManager import SessionDataManager
- sdm = SessionDataManager('session_data_manager',
- title='Session Data Manager',
- path='/temp_folder/session_data',
- requestName='SESSION')
- app._setObject('session_data_manager', sdm)
- get_transaction().note('Added session_data_manager')
- get_transaction().commit()
- del sdm
+ def install_products(self):
+ app = self.getApp()
+ # this defers to a function for b/c reasons
+ return install_products(app)
+
+ def install_standards(self):
+ app = self.getApp()
+ # this defers to a function for b/c reasons
+ return install_standards(app)
- # b/c: Ensure that Owner role exists.
- if hasattr(app, '__ac_roles__') and not ('Owner' in app.__ac_roles__):
- app.__ac_roles__=app.__ac_roles__ + ('Owner',)
- get_transaction().note('Added Owner role')
- get_transaction().commit()
+def install_products(app):
+ # Install a list of products into the basic folder class, so
+ # that all folders know about top-level objects, aka products
- # ensure the Authenticated role exists.
- if hasattr(app, '__ac_roles__'):
- if not 'Authenticated' in app.__ac_roles__:
- app.__ac_roles__=app.__ac_roles__ + ('Authenticated',)
- get_transaction().note('Added Authenticated role')
- get_transaction().commit()
-
- # Make sure we have Globals
- root = app._p_jar.root()
- if not root.has_key('ZGlobals'):
- from BTrees.OOBTree import OOBTree
- root['ZGlobals'] = OOBTree()
- get_transaction().note('Added Globals')
- get_transaction().commit()
+ folder_permissions = get_folder_permissions()
+ meta_types=[]
+ done={}
- # Install the initial user.
- if hasattr(app, 'acl_users'):
- users = app.acl_users
- if hasattr(users, '_createInitialUser'):
- app.acl_users._createInitialUser()
- get_transaction().note('Created initial user')
- get_transaction().commit()
-
- # Install an error_log
- if not hasattr(app, 'error_log'):
- from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog
- error_log = SiteErrorLog()
- app._setObject('error_log', error_log)
- get_transaction().note('Added site error_log at /error_log')
- get_transaction().commit()
+ debug_mode = App.config.getConfiguration().debug_mode
+
+ get_transaction().note('Prior to product installs')
+ get_transaction().commit()
- install_products(app)
- install_standards(app)
+ products = get_products()
- # Note that the code from here on only runs if we are not a ZEO
- # client, or if we are a ZEO client and we've specified by way
- # of env variable that we want to force products to load.
- if not doInstall():
- return
-
- # Check for dangling pointers (broken zclass dependencies) in the
- # global class registry. If found, rebuild the registry. Note that
- # if the check finds problems but fails to successfully rebuild the
- # registry we abort the transaction so that we don't leave it in an
- # indeterminate state.
+ for priority, product_name, index, product_dir in products:
+ # For each product, we will import it and try to call the
+ # intialize() method in the product __init__ module. If
+ # the method doesnt exist, we put the old-style information
+ # together and do a default initialization.
+ if done.has_key(product_name):
+ continue
+ done[product_name]=1
+ install_product(app, product_dir, product_name, meta_types,
+ folder_permissions, raise_exc=debug_mode)
+
+ Products.meta_types=Products.meta_types+tuple(meta_types)
+ Globals.default__class_init__(Folder.Folder)
- did_fixups=0
- bad_things=0
- try:
- if app.checkGlobalRegistry():
- LOG('Zope', INFO,
- 'Beginning attempt to rebuild the global ZClass registry.')
- app.fixupZClassDependencies(rebuild=1)
- did_fixups=1
- LOG('Zope', INFO,
- 'The global ZClass registry has successfully been rebuilt.')
- get_transaction().note('Rebuilt global product registry')
- get_transaction().commit()
- except:
- bad_things=1
- LOG('Zope', ERROR, 'The attempt to rebuild the registry failed.',
- error=sys.exc_info())
- get_transaction().abort()
-
- # Now we need to see if any (disk-based) products were installed
- # during intialization. If so (and the registry has no errors),
- # there may still be zclasses dependent on a base class in the
- # newly installed product that were previously broken and need to
- # be fixed up. If any really Bad Things happened (dangling pointers
- # were found in the registry but it couldn't be rebuilt), we don't
- # try to do anything to avoid making the problem worse.
- if (not did_fixups) and (not bad_things):
-
- # App.Product.initializeProduct will set this if a disk-based
- # product was added or updated and we are not a ZEO client.
- if getattr(Globals, '__disk_product_installed__', 0):
- try:
- LOG('Zope', INFO, 'New disk product detected, determining '\
- 'if we need to fix up any ZClasses.')
- if app.fixupZClassDependencies():
- LOG('Zope', INFO, 'Repaired broken ZClass dependencies.')
- get_transaction().commit()
- except:
- LOG('Zope', ERROR,
- 'Attempt to fixup ZClass dependencies after detecting ' \
- 'an updated disk-based product failed.',
- error=sys.exc_info())
- get_transaction().abort()
def get_products():
""" Return a list of tuples in the form:
@@ -555,36 +663,6 @@
exc = None
-def install_products(app):
- # Install a list of products into the basic folder class, so
- # that all folders know about top-level objects, aka products
-
- folder_permissions = get_folder_permissions()
- meta_types=[]
- done={}
-
- debug_mode = App.config.getConfiguration().debug_mode
-
- get_transaction().note('Prior to product installs')
- get_transaction().commit()
-
- products = get_products()
-
- for priority, product_name, index, product_dir in products:
- # For each product, we will import it and try to call the
- # intialize() method in the product __init__ module. If
- # the method doesnt exist, we put the old-style information
- # together and do a default initialization.
- if done.has_key(product_name):
- continue
- done[product_name]=1
- install_product(app, product_dir, product_name, meta_types,
- folder_permissions, raise_exc=debug_mode)
-
- Products.meta_types=Products.meta_types+tuple(meta_types)
- Globals.default__class_init__(Folder.Folder)
-
-
def get_folder_permissions():
folder_permissions={}
for p in Folder.Folder.__ac_permissions__:
@@ -687,7 +765,7 @@
for permission, names in new_permissions:
folder_permissions[permission]=names
new_permissions.sort()
- Folder.Folder.__dict__['__ac_permissions__']=tuple(
+ Folder.Folder.__ac_permissions__=tuple(
list(Folder.Folder.__ac_permissions__)+new_permissions)
if not doInstall():
More information about the Zope-Checkins
mailing list