[Zope-Checkins] SVN: Products.Five/branches/1.5/ If Zope supports it delay initialization of packages until a later moment when a ZODB connection is available. This fixes http://www.zope.org/Collectors/Zope/2293

Wichert Akkerman wichert at wiggy.net
Sun Jun 17 15:05:59 EDT 2007


Log message for revision 76744:
  If Zope supports it delay initialization of packages until a later moment when a ZODB connection is available. This fixes http://www.zope.org/Collectors/Zope/2293

Changed:
  U   Products.Five/branches/1.5/fiveconfigure.py
  U   Products.Five/branches/1.5/tests/test_registerpackage.py

-=-
Modified: Products.Five/branches/1.5/fiveconfigure.py
===================================================================
--- Products.Five/branches/1.5/fiveconfigure.py	2007-06-17 19:04:57 UTC (rev 76743)
+++ Products.Five/branches/1.5/fiveconfigure.py	2007-06-17 19:05:59 UTC (rev 76744)
@@ -201,34 +201,47 @@
 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 on versions of Zope that support this. 
+    # 
+    # Without this processing, 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().
+    # 
+    # For older versions of Zope not aware of this variable, initialize
+    # immediately as before
+    to_initialize = getattr(Products, '_packages_to_initialize', None)
+    if to_initialize is None:
+        app = Zope2.app()
+        try:
+            product = initializeProduct(module_, 
+                                        module_.__name__, 
+                                        module_.__path__[0],
+                                        app)
 
-        product.package_name = module_.__name__
+            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()
+            if init_func is not None:
+                newContext = ProductContext(product, app, module_)
+                init_func(newContext)
         finally:
-            app._p_jar.close()
+            try:
+                import transaction
+                transaction.commit()
+            finally:
+                app._p_jar.close()
+    else:
+        to_initialize.append((module_, init_func,))
 
 def registerPackage(_context, package, initialize=None):
     """ZCML directive function for registering a python package product

Modified: Products.Five/branches/1.5/tests/test_registerpackage.py
===================================================================
--- Products.Five/branches/1.5/tests/test_registerpackage.py	2007-06-17 19:04:57 UTC (rev 76743)
+++ Products.Five/branches/1.5/tests/test_registerpackage.py	2007-06-17 19:05:59 UTC (rev 76744)
@@ -49,15 +49,28 @@
       ...       />
       ... </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
-
       
+    NOTE: In version 1.5.3 and earlier, the call to initialize() used to 
+    happen during ZCML processing. That's bad, because it attempts to do
+    a ZODB write before sufficient context is available, at least when using
+    ZEO. If you run this test on Zope 2.10.3 or below, you may see doctest
+    failures indicating that the product was loaded immediately after the
+    call to zcml.load_string() above. That's the BBB code kicking in.
+      
     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:



More information about the Zope-Checkins mailing list