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 _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins