r658 - in zope-plonetestcase/trunk: . debian
Fabio Tranchitella
kobold at alioth.debian.org
Fri Feb 9 15:44:31 CET 2007
Author: kobold
Date: 2007-02-09 15:44:31 +0100 (Fri, 09 Feb 2007)
New Revision: 658
Added:
zope-plonetestcase/trunk/five.py
Modified:
zope-plonetestcase/trunk/CHANGES.txt
zope-plonetestcase/trunk/PloneTestCase.py
zope-plonetestcase/trunk/README.txt
zope-plonetestcase/trunk/VERSION.txt
zope-plonetestcase/trunk/debian/changelog
zope-plonetestcase/trunk/interfaces.py
zope-plonetestcase/trunk/layer.py
zope-plonetestcase/trunk/ptc.py
zope-plonetestcase/trunk/setup.py
zope-plonetestcase/trunk/testInterfaces.py
zope-plonetestcase/trunk/testMembershipTool.py
zope-plonetestcase/trunk/utils.py
Log:
New upstream release.
Modified: zope-plonetestcase/trunk/CHANGES.txt
===================================================================
--- zope-plonetestcase/trunk/CHANGES.txt 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/CHANGES.txt 2007-02-09 14:44:31 UTC (rev 658)
@@ -1,3 +1,18 @@
+0.9.0
+- Prepared for switching ZopeTestCase to Zope3 interfaces.
+- Load etc/site.zcml lazily instead of using the wrapper.
+- Import extension profiles one by one to gain better control.
+- Added a PloneTestCase.addProfile() method that allows to import
+ extension profiles into the site. This is an alternative to
+ passing the 'extension_profiles' argument to setupPloneSite().
+- Create Plone site lazily using layer.PloneSite.
+- Renamed utils.py to five.py.
+
+0.8.6
+- Starting with Plone 3.0 the portal is a component registry as well. We
+ perform the necessary registration automatically now.
+- Made sure layer cleanup resets Five.zcml to "not initialized".
+
0.8.4
- Allow to pass a base profile to the setupPloneSite function.
- Added PLONE30 constant.
Modified: zope-plonetestcase/trunk/PloneTestCase.py
===================================================================
--- zope-plonetestcase/trunk/PloneTestCase.py 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/PloneTestCase.py 2007-02-09 14:44:31 UTC (rev 658)
@@ -2,7 +2,7 @@
# PloneTestCase
#
-# $Id: PloneTestCase.py 30087 2006-09-08 10:44:04Z shh42 $
+# $Id: PloneTestCase.py 33985 2006-11-21 23:45:05Z shh42 $
from Testing.ZopeTestCase import hasProduct
from Testing.ZopeTestCase import installProduct
@@ -14,6 +14,8 @@
from setup import PLONE21
from setup import PLONE25
from setup import PLONE30
+from setup import USELAYER
+from setup import Z3INTERFACES
from setup import portal_name
from setup import portal_owner
from setup import default_policy
@@ -22,9 +24,10 @@
from setup import default_extension_profiles
from setup import default_user
from setup import default_password
-from setup import setupPloneSite
from setup import _createHomeFolder
+from setup import setupPloneSite
+
from interfaces import IPloneTestCase
from interfaces import IPloneSecurity
@@ -33,20 +36,34 @@
from AccessControl.SecurityManagement import newSecurityManager
from warnings import warn
+import utils
import setup
-import utils
class PloneTestCase(PortalTestCase):
'''Base test case for Plone testing'''
- __implements__ = (IPloneTestCase, IPloneSecurity,
- PortalTestCase.__implements__)
+ if Z3INTERFACES:
+ from zope.interface import implements
+ implements(IPloneTestCase, IPloneSecurity)
+ else:
+ __implements__ = (IPloneTestCase, IPloneSecurity,
+ PortalTestCase.__implements__)
- if setup.USELAYER:
- from layer import ZCMLLayer
- layer = ZCMLLayer
+ if USELAYER:
+ import layer
+ layer = layer.PloneSite
+ # TODO: This is a bit of an ugly hack, but I couldn't spot a nicer place
+ # to put it. Making this change in setup.SiteSetup doesn't work.
+ if PLONE30:
+ def _setup(self):
+ PortalTestCase._setup(self)
+ # Set the local component registry
+ from zope.app.component.hooks import setSite, setHooks
+ setHooks()
+ setSite(self.portal)
+
def _portal(self):
'''Returns the portal object for a test.'''
try:
@@ -101,8 +118,26 @@
user = user.__of__(uf)
newSecurityManager(None, user)
+ def addProfile(self, name):
+ '''Imports an extension profile into the site.'''
+ sm = getSecurityManager()
+ self.loginAsPortalOwner()
+ try:
+ installed = getattr(self.portal, '_installed_profiles', {})
+ if not installed.has_key(name):
+ setup = self.portal.portal_setup
+ saved = setup.getImportContextID()
+ try:
+ setup.setImportContext('profile-%s' % (name,))
+ setup.runAllImportSteps()
+ finally:
+ setup.setImportContext(saved)
+ self._refreshSkinData()
+ finally:
+ setSecurityManager(sm)
+
def addProduct(self, name):
- '''Quickinstalls a product into the Plone site.'''
+ '''Quickinstalls a product into the site.'''
sm = getSecurityManager()
self.loginAsPortalOwner()
try:
@@ -117,6 +152,7 @@
class FunctionalTestCase(Functional, PloneTestCase):
'''Base class for functional Plone tests'''
- __implements__ = (Functional.__implements__,
- PloneTestCase.__implements__)
+ if not Z3INTERFACES:
+ __implements__ = (Functional.__implements__,
+ PloneTestCase.__implements__)
Modified: zope-plonetestcase/trunk/README.txt
===================================================================
--- zope-plonetestcase/trunk/README.txt 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/README.txt 2007-02-09 14:44:31 UTC (rev 658)
@@ -1,4 +1,4 @@
-PloneTestCase 0.8.4
+PloneTestCase 0.9.0
(c) 2003-2006, Stefan H. Holek, stefan at epy.co.at
http://plone.org/products/plonetestcase
License: ZPL
@@ -43,7 +43,8 @@
- The constant 'PLONE30' which evaluates to true for Plone
versions >= 3.0.
- - The module 'utils' from the ZopeTestCase package.
+ - The module 'utils' which contains all utility functions from the
+ ZopeTestCase package.
Example PloneTestCase::
Modified: zope-plonetestcase/trunk/VERSION.txt
===================================================================
--- zope-plonetestcase/trunk/VERSION.txt 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/VERSION.txt 2007-02-09 14:44:31 UTC (rev 658)
@@ -1 +1 @@
-0.8.4
+0.9.0
Modified: zope-plonetestcase/trunk/debian/changelog
===================================================================
--- zope-plonetestcase/trunk/debian/changelog 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/debian/changelog 2007-02-09 14:44:31 UTC (rev 658)
@@ -1,3 +1,9 @@
+zope-plonetestcase (0.9.0-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Fabio Tranchitella <kobold at debian.org> Fri, 9 Feb 2007 15:44:21 +0100
+
zope-plonetestcase (0.8.4-1) unstable; urgency=low
* New upstream release.
Copied: zope-plonetestcase/trunk/five.py (from rev 631, zope-plonetestcase/branches/upstream/current/five.py)
Modified: zope-plonetestcase/trunk/interfaces.py
===================================================================
--- zope-plonetestcase/trunk/interfaces.py 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/interfaces.py 2007-02-09 14:44:31 UTC (rev 658)
@@ -2,7 +2,7 @@
# PloneTestCase interfaces
#
-# $Id: interfaces.py 21592 2006-03-30 18:06:54Z shh42 $
+# $Id: interfaces.py 33456 2006-11-12 13:55:14Z shh42 $
from Testing.ZopeTestCase.interfaces import *
@@ -24,9 +24,15 @@
class IPloneTestCase(IPortalTestCase):
+ def addProfile(name):
+ '''Imports an extension profile into the Plone site.
+ This is an alternative to passing the 'extension_profiles'
+ argument to 'setupPloneSite'.
+ '''
+
def addProduct(name):
'''Quickinstalls a product into the Plone site.
- This is an alternative to passing a 'products'
+ This is an alternative to passing the 'products'
argument to 'setupPloneSite'.
'''
Modified: zope-plonetestcase/trunk/layer.py
===================================================================
--- zope-plonetestcase/trunk/layer.py 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/layer.py 2007-02-09 14:44:31 UTC (rev 658)
@@ -1,19 +1,39 @@
#
-# Stop gap fix for abuse of ZTC.installProduct('Five')
+# Layer support
#
-# $Id: layer.py 30087 2006-09-08 10:44:04Z shh42 $
+# $Id: layer.py 33503 2006-11-13 14:52:11Z shh42 $
-import utils
+import five
+import setup
-class ZCMLLayer:
+class ZCML:
def setUp(cls):
- utils.safe_load_site()
+ '''Sets up the CA by loading etc/site.zcml.'''
+ five.safe_load_site()
setUp = classmethod(setUp)
def tearDown(cls):
- utils.cleanUp()
+ '''Cleans up the CA.'''
+ five.cleanUp()
tearDown = classmethod(tearDown)
+
+class PloneSite(ZCML):
+
+ def setUp(cls):
+ '''Sets up the Plone site(s).'''
+ setup.deferredSetup()
+ setUp = classmethod(setUp)
+
+ def tearDown(cls):
+ '''Removes the Plone site(s).'''
+ setup.cleanUp()
+ tearDown = classmethod(tearDown)
+
+
+# BBB
+ZCMLLayer = ZCML
+
Modified: zope-plonetestcase/trunk/ptc.py
===================================================================
--- zope-plonetestcase/trunk/ptc.py 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/ptc.py 2007-02-09 14:44:31 UTC (rev 658)
@@ -2,7 +2,7 @@
# PloneTestCase API
#
-# $Id: ptc.py 30087 2006-09-08 10:44:04Z shh42 $
+# $Id: ptc.py 33985 2006-11-21 23:45:05Z shh42 $
from Testing.ZopeTestCase import hasProduct
from Testing.ZopeTestCase import installProduct
@@ -13,9 +13,12 @@
from Products.PloneTestCase import utils
from Products.PloneTestCase.utils import *
+from Products.PloneTestCase import setup
from Products.PloneTestCase.setup import PLONE21
from Products.PloneTestCase.setup import PLONE25
from Products.PloneTestCase.setup import PLONE30
+from Products.PloneTestCase.setup import USELAYER
+from Products.PloneTestCase.setup import Z3INTERFACES
from Products.PloneTestCase.setup import portal_name
from Products.PloneTestCase.setup import portal_owner
from Products.PloneTestCase.setup import default_policy
Modified: zope-plonetestcase/trunk/setup.py
===================================================================
--- zope-plonetestcase/trunk/setup.py 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/setup.py 2007-02-09 14:44:31 UTC (rev 658)
@@ -2,7 +2,7 @@
# PloneTestCase setup
#
-# $Id: setup.py 30087 2006-09-08 10:44:04Z shh42 $
+# $Id: setup.py 34307 2006-12-04 04:59:06Z brcwhit $
from Testing import ZopeTestCase
@@ -37,14 +37,6 @@
ZopeTestCase.installProduct('ResourceRegistries')
ZopeTestCase.installProduct('SecureMailHost')
-# Check for Zope 2.9 or above
-try:
- import zope.testing.testrunner
-except ImportError:
- USELAYER = 0
-else:
- USELAYER = 1
-
# Check for Plone 2.5 or above
try:
from Products.CMFPlone.migrations import v2_5
@@ -58,9 +50,6 @@
ZopeTestCase.installProduct('PluginRegistry')
ZopeTestCase.installProduct('PlonePAS')
ZopeTestCase.installProduct('kupu')
- # For BBB
- if not USELAYER:
- ZopeTestCase.installProduct('Five')
# In Plone 2.5 we need the monkey-patch applied, starting
# with Plone 3.0 it is part of CMFPlone.patches.
try:
@@ -75,18 +64,41 @@
PLONE30 = 0
else:
PLONE30 = 1
+ ZopeTestCase.installProduct('CMFEditions')
+ ZopeTestCase.installProduct('CMFDiffTool')
ZopeTestCase.installProduct('MailHost', quiet=1)
ZopeTestCase.installProduct('PageTemplates', quiet=1)
ZopeTestCase.installProduct('PythonScripts', quiet=1)
ZopeTestCase.installProduct('ExternalMethod', quiet=1)
+# Check for layer support
+try:
+ import zope.testing.testrunner
+except ImportError:
+ USELAYER = 0
+else:
+ USELAYER = 1
+
+# BBB: Zope 2.8
+if PLONE25 and not USELAYER:
+ ZopeTestCase.installProduct('Five')
+
+# Check for Zope3 interfaces
+try:
+ from zope.interface.interfaces import IInterface
+except ImportError:
+ Z3INTERFACES = 0
+else:
+ from interfaces import IPloneTestCase
+ Z3INTERFACES = IInterface.providedBy(IPloneTestCase)
+
from Testing.ZopeTestCase import transaction
from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager
-from AccessControl import getSecurityManager
from Acquisition import aq_base
from time import time
+from Globals import PersistentMapping
if PLONE21:
from Products.CMFPlone.utils import _createObjectByType
@@ -100,24 +112,29 @@
default_user = ZopeTestCase.user_name
default_password = ZopeTestCase.user_password
-# Plone 2.5
default_base_profile = 'CMFPlone:plone'
default_extension_profiles = ()
+if PLONE30:
+ default_base_profile = 'Products.CMFPlone:plone'
+_deferred_setup = []
+
+
def setupPloneSite(id=portal_name, policy=default_policy, products=default_products,
- quiet=0, with_default_memberarea=1, base_profile=default_base_profile,
+ quiet=0, with_default_memberarea=1,
+ base_profile=default_base_profile,
extension_profiles=default_extension_profiles):
'''Creates a Plone site and/or quickinstalls products into it.'''
- PortalSetup(id, policy, products, quiet, with_default_memberarea,
- base_profile, extension_profiles).run()
+ if USELAYER:
+ _deferred_setup.append((id, policy, products, 1, with_default_memberarea,
+ base_profile, extension_profiles))
+ else:
+ SiteSetup(id, policy, products, quiet, with_default_memberarea,
+ base_profile, extension_profiles).run()
-if USELAYER:
- import utils
- setupPloneSite = utils.safe_load_site_wrapper(setupPloneSite)
-
-class PortalSetup:
+class SiteSetup:
'''Creates a Plone site and/or quickinstalls products into it.'''
def __init__(self, id, policy, products, quiet, with_default_memberarea,
@@ -142,9 +159,11 @@
self._login(uf, portal_owner)
self._optimize()
self._setupPloneSite()
+ self._setupRegistries()
if hasattr(aq_base(self.app), self.id):
# Log in as portal owner
self._login(uf, portal_owner)
+ self._setupProfiles()
self._setupProducts()
finally:
self._abort()
@@ -155,51 +174,73 @@
'''Creates the Plone site.'''
# Starting with Plone 2.5 site creation is based on GenericSetup
if PLONE25:
- self._setupPloneSite_genericsetup()
+ self._setupPloneSite_with_genericsetup()
else:
- self._setupPloneSite_portalgenerator()
+ self._setupPloneSite_with_portalgenerator()
- def _setupPloneSite_genericsetup(self):
- '''Creates a Plone site with GenericSetup.'''
+ def _setupPloneSite_with_genericsetup(self):
+ '''Creates the site using GenericSetup.'''
start = time()
if self.base_profile != default_base_profile:
- self._print('Adding Plone Site (%s) ... ' % self.base_profile)
+ self._print('Adding Plone Site (%s) ... ' % (self.base_profile,))
else:
self._print('Adding Plone Site ... ')
# Add Plone site
factory = self.app.manage_addProduct['CMFPlone']
factory.addPloneSite(self.id, create_userfolder=1, snapshot=0,
- profile_id=self.base_profile,
- extension_ids=self.extension_profiles)
- # Precreate default memberarea to speed up the tests
+ profile_id=self.base_profile)
+ # Pre-create default memberarea to speed up the tests
if self.with_default_memberarea:
self._setupHomeFolder()
self._commit()
self._print('done (%.3fs)\n' % (time()-start,))
- # Report applied extension profiles
- if self.extension_profiles != default_extension_profiles:
- self._print(' Applied extensions profiles: %s\n' %
- ', '.join(self.extension_profiles))
- def _setupPloneSite_portalgenerator(self):
- '''Creates a Plone site with PortalGenerator.'''
+ def _setupPloneSite_with_portalgenerator(self):
+ '''Creates the site using PortalGenerator.'''
start = time()
if self.policy != default_policy:
- self._print('Adding Plone Site (%s) ... ' % self.policy)
+ self._print('Adding Plone Site (%s) ... ' % (self.policy,))
else:
self._print('Adding Plone Site ... ')
# Add Plone site
factory = self.app.manage_addProduct['CMFPlone']
factory.manage_addSite(self.id, create_userfolder=1, custom_policy=self.policy)
- # Precreate default memberarea to speed up the tests
+ # Pre-create default memberarea to speed up the tests
if self.with_default_memberarea:
self._setupHomeFolder()
self._commit()
self._print('done (%.3fs)\n' % (time()-start,))
+ def _setupRegistries(self):
+ '''Installs persistent registries.'''
+ portal = getattr(self.app, self.id)
+ if not hasattr(portal, '_installed_profiles'):
+ portal._installed_profiles = PersistentMapping()
+ self._commit()
+
+ def _setupProfiles(self):
+ '''Imports extension profiles into the site.'''
+ portal = getattr(self.app, self.id)
+ setup = getattr(portal, 'portal_setup', None)
+ if setup is not None:
+ for profile in self.extension_profiles:
+ if not portal._installed_profiles.has_key(profile):
+ start = time()
+ self._print('Adding %s ... ' % (profile,))
+ saved = setup.getImportContextID()
+ try:
+ setup.setImportContext('profile-%s' % (profile,))
+ setup.runAllImportSteps()
+ finally:
+ setup.setImportContext(saved)
+ portal._installed_profiles[profile] = 1
+ self._commit()
+ self._print('done (%.3fs)\n' % (time()-start,))
+
def _setupProducts(self):
- '''Quickinstalls products into the Plone site.'''
- qi = self.app[self.id].portal_quickinstaller
+ '''Quickinstalls products into the site.'''
+ portal = getattr(self.app, self.id)
+ qi = portal.portal_quickinstaller
for product in self.products:
if not qi.isProductInstalled(product):
if qi.isProductInstallable(product):
@@ -212,11 +253,12 @@
self._print('Adding %s ... NOT INSTALLABLE\n' % (product,))
def _setupHomeFolder(self):
- '''Creates the default user's memberarea.'''
- _createHomeFolder(self.app[self.id], default_user, 0)
+ '''Creates the default user's member folder.'''
+ portal = getattr(self.app, self.id)
+ _createHomeFolder(portal, default_user, take_ownership=0)
def _optimize(self):
- '''Applies optimizations to the PloneGenerator.'''
+ '''Applies optimizations to the PortalGenerator.'''
_optimize()
def _app(self):
@@ -250,6 +292,35 @@
ZopeTestCase._print(msg)
+class SiteCleanup(SiteSetup):
+ '''Removes a site.'''
+
+ def __init__(self, id):
+ self.id = id
+
+ def run(self):
+ self.app = self._app()
+ try:
+ if hasattr(aq_base(self.app), self.id):
+ self.app._delObject(self.id)
+ self._commit()
+ finally:
+ self._abort()
+ self._close()
+
+
+def deferredSetup():
+ '''Called by layer to setup site(s).'''
+ for site in _deferred_setup:
+ SiteSetup(*site).run()
+
+
+def cleanUp():
+ '''Called by layer to remove site(s).'''
+ for site in _deferred_setup:
+ SiteCleanup(site[0]).run()
+
+
def _createHomeFolder(portal, member_id, take_ownership=1):
'''Creates a memberarea if it does not already exist.'''
pm = portal.portal_membership
Modified: zope-plonetestcase/trunk/testInterfaces.py
===================================================================
--- zope-plonetestcase/trunk/testInterfaces.py 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/testInterfaces.py 2007-02-09 14:44:31 UTC (rev 658)
@@ -2,17 +2,22 @@
# Interface tests
#
-# $Id: testInterfaces.py 21592 2006-03-30 18:06:54Z shh42 $
+# $Id: testInterfaces.py 32762 2006-11-04 15:49:06Z shh42 $
import os, sys
if __name__ == '__main__':
execfile(os.path.join(sys.path[0], 'framework.py'))
from Products.PloneTestCase import PloneTestCase
+from Products.PloneTestCase import setup
from Products.PloneTestCase.interfaces import *
-from Interface.Verify import verifyClass
-from Interface.Verify import verifyObject
+if setup.Z3INTERFACES:
+ from zope.interface.verify import verifyClass
+ from zope.interface.verify import verifyObject
+else:
+ from Interface.Verify import verifyClass
+ from Interface.Verify import verifyObject
class TestPloneTestCase(PloneTestCase.PloneTestCase):
Modified: zope-plonetestcase/trunk/testMembershipTool.py
===================================================================
--- zope-plonetestcase/trunk/testMembershipTool.py 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/testMembershipTool.py 2007-02-09 14:44:31 UTC (rev 658)
@@ -72,11 +72,22 @@
self.logout()
self.failUnless(self.membership.isAnonymousUser())
- def testSetPassword(self):
- self.membership.setPassword('geheim')
- member = self.membership.getMemberById(default_user)
- self.assertEqual(member.getPassword(), 'geheim')
+ if PloneTestCase.PLONE25:
+ def testSetPassword(self):
+ # PAS does not provide the password
+ self.membership.setPassword('geheim')
+ member = self.membership.getMemberById(default_user)
+ #self.assertEqual(member.getPassword(), 'geheim')
+ self.assertEqual(member.getPassword(), None)
+
+ else:
+
+ def testSetPassword(self):
+ self.membership.setPassword('geheim')
+ member = self.membership.getMemberById(default_user)
+ self.assertEqual(member.getPassword(), 'geheim')
+
def testSetPasswordIfAnonymous(self):
self.logout()
try:
Modified: zope-plonetestcase/trunk/utils.py
===================================================================
--- zope-plonetestcase/trunk/utils.py 2007-02-09 14:43:50 UTC (rev 657)
+++ zope-plonetestcase/trunk/utils.py 2007-02-09 14:44:31 UTC (rev 658)
@@ -1,47 +1,11 @@
#
-# Stop gap fix for abuse of ZTC.installProduct('Five')
+# Utility functions
#
-# $Id: utils.py 30087 2006-09-08 10:44:04Z shh42 $
+# $Id: utils.py 33992 2006-11-22 09:11:31Z shh42 $
from Testing.ZopeTestCase.utils import *
-try:
- from zope.testing.cleanup import cleanUp
-except ImportError:
- try:
- from Testing.ZopeTestCase.placeless import tearDown as cleanUp
- except ImportError:
- # Zope <= 2.7
- def cleanUp(): pass
+# BBB
+from five import safe_load_site_wrapper
-
-def setDebugMode(mode):
- """
- Allows manual setting of Five's inspection of debug mode to allow for
- zcml to fail meaningfully
- """
- import Products.Five.fiveconfigure as fc
- fc.debug_mode = mode
-
-
-def safe_load_site():
- """Load entire component architecture (w/ debug mode on)"""
- cleanUp()
- setDebugMode(1)
- import Products.Five.zcml as zcml
- zcml.load_site()
- setDebugMode(0)
-
-
-def safe_load_site_wrapper(function):
- """Wrap function with a temporary loading of entire component architecture"""
- def wrapper(*args, **kw):
- safe_load_site()
- value = function(*args, **kw)
- cleanUp()
- import Products.Five.zcml as zcml
- zcml._initialized = 0
- return value
- return wrapper
-
More information about the pkg-zope-commits
mailing list