[Zope-Checkins] SVN: Zope/trunk/lib/python/ Forward port packages-as-products refactoring from 2.10 branch.

Stefan H. Holek stefan at epy.co.at
Sat Jun 23 11:37:10 EDT 2007


Log message for revision 76988:
  Forward port packages-as-products refactoring from 2.10 branch.
  

Changed:
  U   Zope/trunk/lib/python/OFS/Application.py
  U   Zope/trunk/lib/python/Testing/ZopeTestCase/ZopeLite.py
  U   Zope/trunk/lib/python/Testing/ZopeTestCase/__init__.py
  U   Zope/trunk/lib/python/Testing/ZopeTestCase/doc/CHANGES.txt
  A   Zope/trunk/lib/python/Testing/ZopeTestCase/testpackage/
  A   Zope/trunk/lib/python/Testing/ZopeTestCase/zopedoctest/testPackageAsProduct.py

-=-
Modified: Zope/trunk/lib/python/OFS/Application.py
===================================================================
--- Zope/trunk/lib/python/OFS/Application.py	2007-06-23 15:02:50 UTC (rev 76987)
+++ Zope/trunk/lib/python/OFS/Application.py	2007-06-23 15:37:09 UTC (rev 76988)
@@ -633,21 +633,9 @@
         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()
+    # Delayed install of packages-as-products
+    for module, init_func in getattr(Products, '_packages_to_initialize', []):
+        install_package(app, module, init_func, raise_exc=debug_mode)
     if hasattr(Products, '_packages_to_initialize'):
         del Products._packages_to_initialize
 
@@ -855,6 +843,34 @@
             if raise_exc:
                 raise
 
+
+def install_package(app, module, init_func, raise_exc=False, log_exc=True):
+    """Installs a Python package like a product."""
+    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)
+
+        if not doInstall():
+            transaction.abort()
+        else:
+            transaction.get().note('Installed package %s' % module.__name__)
+            transaction.commit()
+
+    except:
+        if log_exc:
+            LOG.error("Couldn't install %s" % module.__name__,
+                      exc_info=True)
+        transaction.abort()
+        if raise_exc:
+            raise
+
+
 def install_standards(app):
     # Check to see if we've already done this before
     # Don't do it twice (Casey)

Modified: Zope/trunk/lib/python/Testing/ZopeTestCase/ZopeLite.py
===================================================================
--- Zope/trunk/lib/python/Testing/ZopeTestCase/ZopeLite.py	2007-06-23 15:02:50 UTC (rev 76987)
+++ Zope/trunk/lib/python/Testing/ZopeTestCase/ZopeLite.py	2007-06-23 15:37:09 UTC (rev 76988)
@@ -26,7 +26,6 @@
 """
 
 import os, sys, time
-import transaction
 
 # Allow code to tell it is run by the test framework
 os.environ['ZOPETESTCASE'] = '1'
@@ -133,62 +132,60 @@
 
 # Allow test authors to install Zope products into the test environment. Note
 # that installProduct() must be called at module level -- never from tests.
-from OFS.Application import get_folder_permissions, get_products, install_product
+from OFS.Application import get_folder_permissions, get_products
+from OFS.Application import install_product, install_package
 from OFS.Folder import Folder
 import Products
 
 _theApp = Zope2.app()
 _installedProducts = {}
+_installedPackages = {}
 
 def hasProduct(name):
     '''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, package=False):
+def installProduct(name, quiet=0):
     '''Installs a Zope product.'''
     start = time.time()
     meta_types = []
     if _patched and not _installedProducts.has_key(name):
-        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)
+        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)
 
-                        product.package_name = module_.__name__
+def hasPackage(name):
+    '''Checks if a package has been registered with five:registerPackage.'''
+    return name in [m.__name__ for m in getattr(Products, '_registered_packages', [])]
 
-                        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
+def installPackage(name, quiet=0):
+    '''Installs a registered Python package like a Zope product.'''
+    start = time.time()
+    if _patched and not _installedPackages.has_key(name):
+        for module, init_func in getattr(Products, '_packages_to_initialize', []):
+            if module.__name__ == name:
+                if not quiet: _print('Installing %s ... ' % module.__name__)
+                # We want to fail immediately if a package throws an exception
+                # during install, so we set the raise_exc flag.
+                install_package(_theApp, module, init_func, raise_exc=1)
+                _installedPackages[module.__name__] = 1
+                Products._packages_to_initialize.remove((module, init_func))
+                if not quiet: _print('done (%.3fs)\n' % (time.time() - start))
+                break
         else:
-            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)
+            if not quiet: _print('Installing %s ... NOT FOUND\n' % name)
 
 def _load_control_panel():
     # Loading the Control_Panel of an existing ZODB may take
@@ -219,6 +216,7 @@
 configure = Zope2.configure
 def startup(): pass
 Zope = Zope2
+active = _patched
 
 # ZODB sandbox factory
 from ZODB.DemoStorage import DemoStorage

Modified: Zope/trunk/lib/python/Testing/ZopeTestCase/__init__.py
===================================================================
--- Zope/trunk/lib/python/Testing/ZopeTestCase/__init__.py	2007-06-23 15:02:50 UTC (rev 76987)
+++ Zope/trunk/lib/python/Testing/ZopeTestCase/__init__.py	2007-06-23 15:37:09 UTC (rev 76988)
@@ -20,6 +20,8 @@
 
 from ZopeLite import hasProduct
 from ZopeLite import installProduct
+from ZopeLite import hasPackage
+from ZopeLite import installPackage
 from ZopeLite import _print
 
 from ZopeTestCase import folder_name

Modified: Zope/trunk/lib/python/Testing/ZopeTestCase/doc/CHANGES.txt
===================================================================
--- Zope/trunk/lib/python/Testing/ZopeTestCase/doc/CHANGES.txt	2007-06-23 15:02:50 UTC (rev 76987)
+++ Zope/trunk/lib/python/Testing/ZopeTestCase/doc/CHANGES.txt	2007-06-23 15:37:09 UTC (rev 76988)
@@ -18,6 +18,8 @@
   publish_module(). Thanks to Andreas Zeidler.
 - Fixed doctestsuite factory to copy layers from test_class to the suite.
   Thanks to Whit Morris.
+- Added hasPackage and installPackage functions for dealing with "products"
+  registered via five:registerPackage.
 
 0.9.8 (Zope 2.8 edition)
 - Renamed 'doctest' package to 'zopedoctest' because of name-shadowing

Copied: Zope/trunk/lib/python/Testing/ZopeTestCase/testpackage (from rev 76966, Zope/branches/2.10/lib/python/Testing/ZopeTestCase/testpackage)

Copied: Zope/trunk/lib/python/Testing/ZopeTestCase/zopedoctest/testPackageAsProduct.py (from rev 76966, Zope/branches/2.10/lib/python/Testing/ZopeTestCase/zopedoctest/testPackageAsProduct.py)
===================================================================
--- Zope/trunk/lib/python/Testing/ZopeTestCase/zopedoctest/testPackageAsProduct.py	                        (rev 0)
+++ Zope/trunk/lib/python/Testing/ZopeTestCase/zopedoctest/testPackageAsProduct.py	2007-06-23 15:37:09 UTC (rev 76988)
@@ -0,0 +1,122 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Tests for installPackage
+
+$Id$
+"""
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from unittest import TestSuite
+from Testing import ZopeTestCase
+from Testing.ZopeTestCase import ZopeLite
+from Testing.ZopeTestCase import ZopeDocTestSuite
+from Products.Five import zcml
+from zope.testing import cleanup
+import Products
+
+
+def testInstallPackage():
+    """
+    Test if installPackage works.
+
+      >>> from Testing import ZopeTestCase
+      >>> from Products.Five import zcml
+
+    Register testpackage
+
+      >>> ZopeTestCase.hasPackage('testpackage')
+      False
+
+      >>> config = '''
+      ... <configure
+      ...     xmlns:five="http://namespaces.zope.org/five">
+      ...   <five:registerPackage
+      ...     package="testpackage"
+      ...     initialize="testpackage.initialize"
+      ...     />
+      ... </configure>'''
+      >>> zcml.load_string(config)
+
+    The package is registered now
+
+      >>> ZopeTestCase.hasPackage('testpackage')
+      True
+
+    But not yet installed
+
+      >>> app = self._app()
+      >>> 'testpackage' in app.Control_Panel.Products.objectIds()
+      False
+
+    Install it
+
+      >>> ZopeTestCase.installPackage('testpackage', quiet=True)
+      testpackage.initialize called
+
+    Now it shows up in Control_Panel
+
+      >>> app = self._app()
+      >>> 'testpackage' in app.Control_Panel.Products.objectIds()
+      True
+
+    hasPackage still returns True
+
+      >>> ZopeTestCase.hasPackage('testpackage')
+      True
+
+    A package is only installed once, subsequent calls to installPackage
+    are ignored:
+
+      >>> ZopeTestCase.installPackage('testpackage', quiet=True)
+    """
+
+
+class TestClass(ZopeTestCase.FunctionalTestCase):
+
+    def afterSetUp(self):
+        cleanup.cleanUp()
+        zcml._initialized = False
+        zcml.load_site()
+
+        self.saved = sys.path[:]
+        sys.path.append(ZopeTestCase.__path__[0])
+
+    def afterClear(self):
+        cleanup.cleanUp()
+        sys.path[:] = self.saved
+
+        registered = getattr(Products, '_registered_packages', None)
+        if registered is not None:
+            Products._registered_packages = [m for m in registered
+                                             if m.__name__ != 'testpackage']
+
+        to_initialize = getattr(Products, '_packages_to_initialize', None)
+        if to_initialize is not None:
+            Products._packages_to_initialize = [(m, f) for (m, f) in to_initialize
+                                                if m.__name__ != 'testpackage']
+
+
+def test_suite():
+    if ZopeLite.active:
+        return TestSuite((
+            ZopeDocTestSuite(test_class=TestClass),
+        ))
+    else:
+        return TestSuite()
+
+if __name__ == '__main__':
+    framework()
+



More information about the Zope-Checkins mailing list