[Zope-CMF] back-porting a GenericSetup fix to the 1.4 branch
Rob Miller
ra at burningman.com
Tue Sep 16 17:28:58 EDT 2008
Rob Miller wrote:
> hi all,
>
> currently, on the 1.4 branch of GenericSetup, there is what i consider to be a
> bug in the component registry import code. the issue is that when you re-run
> the import step, even if you are not in purge mode, then any utilities that
> are registered with the given site manager will be replaced with brand new
> instances. since local utilities are persistent objects, and often store
> important information within themselves, this seems to me a big enough issue
> to warrant a bug-fix on the 1.4 branch.
>
> this appears to have been resolved on the trunk, as part of a bigger set of
> component registry improvements. i've backported the changes (with minor
> adjustments to account for other version-related differences) to a local 1.4
> checkout, and have added a regression test that demonstrates the problem and
> verifies the fix.
>
> if somebody feels strongly that this is too much of a functionality change for
> a maintenance branch, please respond here on-list... otherwise, i'll commit
> this to the 1.4 branch some time in the next day or so.
whoops, forgot the patch:
Index: Products/GenericSetup/tests/test_components.py
===================================================================
--- Products/GenericSetup/tests/test_components.py (revision 91193)
+++ Products/GenericSetup/tests/test_components.py (working copy)
@@ -26,13 +26,17 @@
from Products.Five.component import enableSite
from Products.Five.component.interfaces import IObjectManagerSite
from zope.app.component.hooks import setSite, clearSite, setHooks
+from zope.app.component.hooks import getSite
+from zope.component import getMultiAdapter
from zope.component import getSiteManager
from zope.component import queryUtility
from zope.component.globalregistry import base
from zope.interface import implements
from zope.interface import Interface
+from Products.GenericSetup.interfaces import IBody
from Products.GenericSetup.testing import BodyAdapterTestCase
+from Products.GenericSetup.testing import DummySetupEnviron
from Products.GenericSetup.testing import ExportImportZCMLLayer
try:
@@ -180,6 +184,30 @@
self._obj = sm
self._BODY = _COMPONENTS_BODY
+ def test_no_overwrite(self):
+ # make sure we don't overwrite an existing tool when it
+ # already exists and has the same factory
+ context = DummySetupEnviron()
+ context._should_purge = False
+ importer = getMultiAdapter((self._obj, context), IBody)
+ importer.body = self._BODY # <-- triggers the import :(
+
+ util = queryUtility(IDummyInterface)
+ value = 'bar'
+ util.foo = value
+
+ # re-retrieve to make sure it's the same object
+ util = queryUtility(IDummyInterface)
+ self.assertEquals(getattr(util, 'foo', None), value)
+
+ context = DummySetupEnviron()
+ context._should_purge = False
+ importer = getMultiAdapter((self._obj, context), IBody)
+ importer.body = self._BODY # <-- triggers the import :(
+
+ util = queryUtility(IDummyInterface)
+ self.assertEquals(getattr(util, 'foo', None), value)
+
def tearDown(self):
clearSite()
Index: Products/GenericSetup/components.py
===================================================================
--- Products/GenericSetup/components.py (revision 91193)
+++ Products/GenericSetup/components.py (working copy)
@@ -127,6 +127,8 @@
def _initUtilities(self, node):
site = self._getSite()
+ current_utilities = self.context.registeredUtilities()
+
for child in node.childNodes:
if child.nodeName != 'utility':
continue
@@ -163,7 +165,16 @@
elif component:
self.context.registerUtility(component, provided, name)
elif factory is not None:
- self.context.registerUtility(factory(), provided, name)
+ current = [ utility for utility in current_utilities
+ if utility.provided==provided and
+ utility.name==name ]
+ assert len(current) <=1
+
+ new_utility = factory()
+ if current and type(current[0].component) == type(new_utility):
+ continue
+
+ self.context.registerUtility(new_utility, provided, name)
else:
self._logger.warning("Invalid utility registration for "
"interface %s" % provided)
More information about the Zope-CMF
mailing list