Commit d46ab020 authored by Stefan H. Holek's avatar Stefan H. Holek

Forward port packages-as-products refactoring from 2.10 branch.

parents 51aae426 cf0a8834
...@@ -633,21 +633,9 @@ def install_products(app): ...@@ -633,21 +633,9 @@ def install_products(app):
install_product(app, product_dir, product_name, meta_types, install_product(app, product_dir, product_name, meta_types,
folder_permissions, raise_exc=debug_mode) folder_permissions, raise_exc=debug_mode)
# Delayed install of products-as-packages # Delayed install of packages-as-products
for module_, init_func in getattr(Products, '_packages_to_initialize', []): for module, init_func in getattr(Products, '_packages_to_initialize', []):
try: install_package(app, module, init_func, raise_exc=debug_mode)
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'): if hasattr(Products, '_packages_to_initialize'):
del Products._packages_to_initialize del Products._packages_to_initialize
...@@ -855,6 +843,34 @@ def install_product(app, product_dir, product_name, meta_types, ...@@ -855,6 +843,34 @@ def install_product(app, product_dir, product_name, meta_types,
if raise_exc: if raise_exc:
raise 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): def install_standards(app):
# Check to see if we've already done this before # Check to see if we've already done this before
# Don't do it twice (Casey) # Don't do it twice (Casey)
......
...@@ -26,7 +26,6 @@ $Id$ ...@@ -26,7 +26,6 @@ $Id$
""" """
import os, sys, time import os, sys, time
import transaction
# Allow code to tell it is run by the test framework # Allow code to tell it is run by the test framework
os.environ['ZOPETESTCASE'] = '1' os.environ['ZOPETESTCASE'] = '1'
...@@ -133,62 +132,60 @@ if not Zope2._began_startup: ...@@ -133,62 +132,60 @@ if not Zope2._began_startup:
# Allow test authors to install Zope products into the test environment. Note # Allow test authors to install Zope products into the test environment. Note
# that installProduct() must be called at module level -- never from tests. # 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 from OFS.Folder import Folder
import Products import Products
_theApp = Zope2.app() _theApp = Zope2.app()
_installedProducts = {} _installedProducts = {}
_installedPackages = {}
def hasProduct(name): def hasProduct(name):
'''Checks if a product can be found along Products.__path__''' '''Checks if a product can be found along Products.__path__'''
return name in [n[1] for n in get_products()] 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.''' '''Installs a Zope product.'''
start = time.time() start = time.time()
meta_types = [] meta_types = []
if _patched and not _installedProducts.has_key(name): if _patched and not _installedProducts.has_key(name):
if package: for priority, product_name, index, product_dir in get_products():
# Processing of products-as-packages can be simpler; also check if product_name == name:
# whether this has been registered with <five:registerPackage /> if not quiet: _print('Installing %s ... ' % product_name)
# and has not been loaded. # We want to fail immediately if a product throws an exception
for module_, init_func in getattr(Products, '_packages_to_initialize', []): # during install, so we set the raise_exc flag.
if module_.__name__ == name: install_product(_theApp, product_dir, product_name, meta_types,
if not quiet: _print('Installing %s ... ' % name) get_folder_permissions(), raise_exc=1)
try: _installedProducts[product_name] = 1
product = App.Product.initializeProduct(module_, Products.meta_types = Products.meta_types + tuple(meta_types)
module_.__name__, Globals.InitializeClass(Folder)
module_.__path__[0], if not quiet: _print('done (%.3fs)\n' % (time.time() - start))
_theApp) break
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: else:
for priority, product_name, index, product_dir in get_products(): if name != 'SomeProduct': # Ignore the skeleton tests :-P
if product_name == name: if not quiet: _print('Installing %s ... NOT FOUND\n' % name)
if not quiet: _print('Installing %s ... ' % product_name)
# We want to fail immediately if a product throws an exception def hasPackage(name):
# during install, so we set the raise_exc flag. '''Checks if a package has been registered with five:registerPackage.'''
install_product(_theApp, product_dir, product_name, meta_types, return name in [m.__name__ for m in getattr(Products, '_registered_packages', [])]
get_folder_permissions(), raise_exc=1)
_installedProducts[product_name] = 1 def installPackage(name, quiet=0):
Products.meta_types = Products.meta_types + tuple(meta_types) '''Installs a registered Python package like a Zope product.'''
Globals.InitializeClass(Folder) start = time.time()
if not quiet: _print('done (%.3fs)\n' % (time.time() - start)) if _patched and not _installedPackages.has_key(name):
break for module, init_func in getattr(Products, '_packages_to_initialize', []):
else: if module.__name__ == name:
if name != 'SomeProduct': # Ignore the skeleton tests :-P if not quiet: _print('Installing %s ... ' % module.__name__)
if not quiet: _print('Installing %s ... NOT FOUND\n' % 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:
if not quiet: _print('Installing %s ... NOT FOUND\n' % name)
def _load_control_panel(): def _load_control_panel():
# Loading the Control_Panel of an existing ZODB may take # Loading the Control_Panel of an existing ZODB may take
...@@ -219,6 +216,7 @@ DB = Zope2.DB ...@@ -219,6 +216,7 @@ DB = Zope2.DB
configure = Zope2.configure configure = Zope2.configure
def startup(): pass def startup(): pass
Zope = Zope2 Zope = Zope2
active = _patched
# ZODB sandbox factory # ZODB sandbox factory
from ZODB.DemoStorage import DemoStorage from ZODB.DemoStorage import DemoStorage
......
...@@ -20,6 +20,8 @@ import utils ...@@ -20,6 +20,8 @@ import utils
from ZopeLite import hasProduct from ZopeLite import hasProduct
from ZopeLite import installProduct from ZopeLite import installProduct
from ZopeLite import hasPackage
from ZopeLite import installPackage
from ZopeLite import _print from ZopeLite import _print
from ZopeTestCase import folder_name from ZopeTestCase import folder_name
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
publish_module(). Thanks to Andreas Zeidler. publish_module(). Thanks to Andreas Zeidler.
- Fixed doctestsuite factory to copy layers from test_class to the suite. - Fixed doctestsuite factory to copy layers from test_class to the suite.
Thanks to Whit Morris. Thanks to Whit Morris.
- Added hasPackage and installPackage functions for dealing with "products"
registered via five:registerPackage.
0.9.8 (Zope 2.8 edition) 0.9.8 (Zope 2.8 edition)
- Renamed 'doctest' package to 'zopedoctest' because of name-shadowing - Renamed 'doctest' package to 'zopedoctest' because of name-shadowing
......
def initialize(context):
print 'testpackage.initialize called'
##############################################################################
#
# 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()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment