[Zope-Checkins] SVN: Zope/trunk/lib/python/ Delay registration of python packages until a moment when a ZODB connection is available http://www.zope.org/Collectors/Zope/2293

Wichert Akkerman wichert at wiggy.net
Sun Jun 17 14:16:24 EDT 2007


Log message for revision 76740:
  Delay registration of python packages until a moment when a ZODB connection is available http://www.zope.org/Collectors/Zope/2293

Changed:
  U   Zope/trunk/lib/python/OFS/Application.py
  U   Zope/trunk/lib/python/OFS/ObjectManager.py
  U   Zope/trunk/lib/python/OFS/tests/testObjectManager.py
  U   Zope/trunk/lib/python/Products/Five/fiveconfigure.py
  U   Zope/trunk/lib/python/Products/Five/tests/test_registerpackage.py
  U   Zope/trunk/lib/python/Testing/ZopeTestCase/ZopeLite.py

-=-
Modified: Zope/trunk/lib/python/OFS/Application.py
===================================================================
--- Zope/trunk/lib/python/OFS/Application.py	2007-06-17 18:10:22 UTC (rev 76739)
+++ Zope/trunk/lib/python/OFS/Application.py	2007-06-17 18:16:23 UTC (rev 76740)
@@ -633,6 +633,24 @@
         install_product(app, product_dir, product_name, meta_types,
                         folder_permissions, raise_exc=debug_mode)
 
+    # Delayed install of products-as-packages
+    for module_, init_func in getattr(Products, '_packages_to_initialize', []):
+        try:
+            product = App.Product.initializeProduct(module_, 
+                                                    module_.__name__, 
+                                                    module_.__path__[0],
+                                                    app)
+
+            product.package_name = module_.__name__
+
+            if init_func is not None:
+                newContext = ProductContext(product, app, module_)
+                init_func(newContext)
+        finally:
+            transaction.commit()
+    if hasattr(Products, '_packages_to_initialize'):
+        del Products._packages_to_initialize
+
     Products.meta_types=Products.meta_types+tuple(meta_types)
     InitializeClass(Folder.Folder)
 

Modified: Zope/trunk/lib/python/OFS/ObjectManager.py
===================================================================
--- Zope/trunk/lib/python/OFS/ObjectManager.py	2007-06-17 18:10:22 UTC (rev 76739)
+++ Zope/trunk/lib/python/OFS/ObjectManager.py	2007-06-17 18:16:23 UTC (rev 76740)
@@ -705,6 +705,7 @@
                 out=out+((k,stat),)
         return marshal.dumps(out)
 
+    security.declareProtected(access_contents_information, 'manage_hasId')
     def manage_hasId(self, REQUEST):
         """ check if the folder has an object with REQUEST['id'] """
 

Modified: Zope/trunk/lib/python/OFS/tests/testObjectManager.py
===================================================================
--- Zope/trunk/lib/python/OFS/tests/testObjectManager.py	2007-06-17 18:10:22 UTC (rev 76739)
+++ Zope/trunk/lib/python/OFS/tests/testObjectManager.py	2007-06-17 18:16:23 UTC (rev 76740)
@@ -411,6 +411,16 @@
             self.failUnless(filename.endswith('.zexp') or
                             filename.endswith('.xml'))
 
+    def test_hasId(self):
+        om = self._makeOne()
+        request={'id' : 'test'}
+        self.assertRaises(KeyError, om.manage_hasId, request)
+
+        si = SimpleItem('test')
+        om._setObject('test', si)
+        om.manage_hasId(request)
+
+
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTest( unittest.makeSuite( ObjectManagerTests ) )

Modified: Zope/trunk/lib/python/Products/Five/fiveconfigure.py
===================================================================
--- Zope/trunk/lib/python/Products/Five/fiveconfigure.py	2007-06-17 18:10:22 UTC (rev 76739)
+++ Zope/trunk/lib/python/Products/Five/fiveconfigure.py	2007-06-17 18:16:23 UTC (rev 76740)
@@ -201,35 +201,25 @@
 def _registerPackage(module_, init_func=None):
     """Registers the given python package as a Zope 2 style product
     """
-
+    
     if not hasattr(module_, '__path__'):
         raise ValueError("Must be a package and the " \
                          "package must be filesystem based")
     
-    app = Zope2.app()
-    try:
-        product = initializeProduct(module_, 
-                                    module_.__name__, 
-                                    module_.__path__[0],
-                                    app)
+    registered_packages = getattr(Products, '_registered_packages', None)
+    if registered_packages is None:
+        registered_packages = Products._registered_packages = []
+    registered_packages.append(module_)
+    
+    # Delay the actual setup until the usual product loading time in
+    # OFS.Application. Otherwise, we may get database write errors in
+    # ZEO, when there's no connection with which to write an entry to
+    # Control_Panel. We would also get multiple calls to initialize().
+    to_initialize = getattr(Products, '_packages_to_initialize', None)
+    if to_initialize is None:
+        to_initialize = Products._packages_to_initialize = []
+    to_initialize.append((module_, init_func,))
 
-        product.package_name = module_.__name__
-
-        if init_func is not None:
-            newContext = ProductContext(product, app, module_)
-            init_func(newContext)
-
-        registered_packages = getattr(Products, '_registered_packages', None)
-        if registered_packages is None:
-            registered_packages = Products._registered_packages = []
-        registered_packages.append(module_)
-    finally:
-        try:
-            import transaction
-            transaction.commit()
-        finally:
-            app._p_jar.close()
-
 def registerPackage(_context, package, initialize=None):
     """ZCML directive function for registering a python package product
     """

Modified: Zope/trunk/lib/python/Products/Five/tests/test_registerpackage.py
===================================================================
--- Zope/trunk/lib/python/Products/Five/tests/test_registerpackage.py	2007-06-17 18:10:22 UTC (rev 76739)
+++ Zope/trunk/lib/python/Products/Five/tests/test_registerpackage.py	2007-06-17 18:16:23 UTC (rev 76740)
@@ -49,15 +49,21 @@
       ...       />
       ... </configure>'''
       >>> zcml.load_string(configure_zcml)
+      
+    We need to load the product as well. This would normally happen during 
+    Zope startup, but in the test, we're already too late.
+    
+      >>> import Zope2
+      >>> from OFS.Application import install_products
+      
+      >>> app = Zope2.app()
+      >>> install_products(app)
       pythonproduct2 initialized
-
       
     Test to see if the pythonproduct2 python package actually gets setup
     as a zope2 product in the Control Panel.
 
       >>> product_listing = []
-      >>> import Zope2
-      >>> app = Zope2.app()
       >>> try:
       ...    product_listing = app.Control_Panel.Products.objectIds()
       ... finally:

Modified: Zope/trunk/lib/python/Testing/ZopeTestCase/ZopeLite.py
===================================================================
--- Zope/trunk/lib/python/Testing/ZopeTestCase/ZopeLite.py	2007-06-17 18:10:22 UTC (rev 76739)
+++ Zope/trunk/lib/python/Testing/ZopeTestCase/ZopeLite.py	2007-06-17 18:16:23 UTC (rev 76740)
@@ -26,6 +26,7 @@
 """
 
 import os, sys, time
+import transaction
 
 # Allow code to tell it is run by the test framework
 os.environ['ZOPETESTCASE'] = '1'
@@ -143,26 +144,51 @@
     '''Checks if a product can be found along Products.__path__'''
     return name in [n[1] for n in get_products()]
 
-def installProduct(name, quiet=0):
+def installProduct(name, quiet=0, package=False):
     '''Installs a Zope product.'''
     start = time.time()
     meta_types = []
     if _patched and not _installedProducts.has_key(name):
-        for priority, product_name, index, product_dir in get_products():
-            if product_name == name:
-                if not quiet: _print('Installing %s ... ' % product_name)
-                # We want to fail immediately if a product throws an exception
-                # during install, so we set the raise_exc flag.
-                install_product(_theApp, product_dir, product_name, meta_types,
-                                get_folder_permissions(), raise_exc=1)
-                _installedProducts[product_name] = 1
-                Products.meta_types = Products.meta_types + tuple(meta_types)
-                Globals.InitializeClass(Folder)
-                if not quiet: _print('done (%.3fs)\n' % (time.time() - start))
-                break
+        if package:
+            # Processing of products-as-packages can be simpler; also check
+            # whether this has been registered with <five:registerPackage />
+            # and has not been loaded.
+            for module_, init_func in getattr(Products, '_packages_to_initialize', []):
+                if module_.__name__ == name:
+                    if not quiet: _print('Installing %s ... ' % name)
+                    try:
+                        product = App.Product.initializeProduct(module_, 
+                                                                module_.__name__, 
+                                                                module_.__path__[0],
+                                                                _theApp)
+
+                        product.package_name = module_.__name__
+
+                        if init_func is not None:
+                            newContext = App.ProductContext.ProductContext(product, app, module_)
+                            init_func(newContext)
+                    finally:
+                        transaction.commit()
+                    
+                    Globals.InitializeClass(Folder)
+                    if not quiet: _print('done (%.3fs)\n' % (time.time() - start))
+                    break
         else:
-            if name != 'SomeProduct':   # Ignore the skeleton tests :-P
-                if not quiet: _print('Installing %s ... NOT FOUND\n' % name)
+            for priority, product_name, index, product_dir in get_products():
+                if product_name == name:
+                    if not quiet: _print('Installing %s ... ' % product_name)
+                    # We want to fail immediately if a product throws an exception
+                    # during install, so we set the raise_exc flag.
+                    install_product(_theApp, product_dir, product_name, meta_types,
+                                    get_folder_permissions(), raise_exc=1)
+                    _installedProducts[product_name] = 1
+                    Products.meta_types = Products.meta_types + tuple(meta_types)
+                    Globals.InitializeClass(Folder)
+                    if not quiet: _print('done (%.3fs)\n' % (time.time() - start))
+                    break
+            else:
+                if name != 'SomeProduct':   # Ignore the skeleton tests :-P
+                    if not quiet: _print('Installing %s ... NOT FOUND\n' % name)
 
 def _load_control_panel():
     # Loading the Control_Panel of an existing ZODB may take



More information about the Zope-Checkins mailing list