[Checkins] SVN: zope.app.component/tags/3.4.x/ - Fix empty __bases__ on LocalSiteManager objects loaded from old databases,
Marius Gedminas
marius at pov.lt
Wed Jul 15 14:46:00 EDT 2009
Log message for revision 101931:
- Fix empty __bases__ on LocalSiteManager objects loaded from old databases,
which causes queryNextUtility to never see global utilites and therefore
broke minor things like the whole authentication framework.
- Fix KeyError: 'base' on startup in zope/app/component/back35.py after
an inept attempt to fix the above error.
I would strongly appreciate some review of this code, since I don't know much
about the internals of local site registries.
Changed:
U zope.app.component/tags/3.4.x/CHANGES.txt
U zope.app.component/tags/3.4.x/src/zope/app/component/back35.py
U zope.app.component/tags/3.4.x/src/zope/app/component/site.py
U zope.app.component/tags/3.4.x/src/zope/app/component/tests/test_registration.py
-=-
Modified: zope.app.component/tags/3.4.x/CHANGES.txt
===================================================================
--- zope.app.component/tags/3.4.x/CHANGES.txt 2009-07-15 18:34:35 UTC (rev 101930)
+++ zope.app.component/tags/3.4.x/CHANGES.txt 2009-07-15 18:45:59 UTC (rev 101931)
@@ -2,6 +2,16 @@
CHANGES
=======
+3.4.2 (unreleased)
+------------------
+
+- Fix empty __bases__ on LocalSiteManager objects loaded from old databases,
+ which causes queryNextUtility to never see global utilites and therefore
+ broke minor things like the whole authentication framework.
+- Fix KeyError: 'base' on startup in zope/app/component/back35.py after
+ an inept attempt to fix the above error.
+
+
3.4.1 (2007-10-31)
------------------
Modified: zope.app.component/tags/3.4.x/src/zope/app/component/back35.py
===================================================================
--- zope.app.component/tags/3.4.x/src/zope/app/component/back35.py 2009-07-15 18:34:35 UTC (rev 101930)
+++ zope.app.component/tags/3.4.x/src/zope/app/component/back35.py 2009-07-15 18:45:59 UTC (rev 101931)
@@ -889,7 +889,7 @@
class _LocalAdapterRegistryGeneration3SupportMixin(object):
def __setstate__(self, state):
- if '_registrations' in state:
+ if '_registrations' in state and '__bases__' not in state:
# convert data to generation 3 data structure:
next = state.get('next')
if next is None:
Modified: zope.app.component/tags/3.4.x/src/zope/app/component/site.py
===================================================================
--- zope.app.component/tags/3.4.x/src/zope/app/component/site.py 2009-07-15 18:34:35 UTC (rev 101930)
+++ zope.app.component/tags/3.4.x/src/zope/app/component/site.py 2009-07-15 18:45:59 UTC (rev 101931)
@@ -192,6 +192,12 @@
zope.event.notify(ObjectCreatedEvent(folder))
self['default'] = folder
+ def __setstate__(self, state):
+ if not state.get('__bases__'):
+ next = zope.component.getGlobalSiteManager()
+ state['__bases__'] = (next, )
+ super(LocalSiteManager, self).__setstate__(state)
+
def _init_registries(self):
self.adapters = _LocalAdapterRegistry()
self.utilities = _LocalAdapterRegistry()
Modified: zope.app.component/tags/3.4.x/src/zope/app/component/tests/test_registration.py
===================================================================
--- zope.app.component/tags/3.4.x/src/zope/app/component/tests/test_registration.py 2009-07-15 18:34:35 UTC (rev 101930)
+++ zope.app.component/tags/3.4.x/src/zope/app/component/tests/test_registration.py 2009-07-15 18:45:59 UTC (rev 101931)
@@ -63,6 +63,7 @@
def setUp(test):
placelesssetup.setUp(test)
+ zope.component.provideUtility(Foo(), provides=IFoo, name='globalfoo')
test.globs['showwarning'] = warnings.showwarning
warnings.showwarning = lambda *a, **k: None
@@ -137,6 +138,13 @@
>>> sm3.getUtility(IFoo, '5') is sm3['default']['5']
True
+The bases are loaded correctly and therefore we can look up global utilities
+
+ >>> sm1.queryUtility(IFoo, 'globalfoo') is not None
+ True
+ >>> zope.app.component.queryNextUtility(sm1, IFoo, 'globalfoo') is not None
+ True
+
and we get registration info:
>>> sorted([r.name for r in sm2.registeredUtilities()])
@@ -343,7 +351,7 @@
>>> all.remove(sm3['default']['4'])
>>> all.remove(sm3['default']['5'])
>>> len(all)
- 2
+ 3
Cleanup:
@@ -352,6 +360,45 @@
"""
+def test_old_databases_backward_compat_shoot_self_in_foot():
+ """
+
+ >>> fs = oldfs()
+ >>> demo = DemoStorage(base=fs)
+ >>> db = DB(demo)
+ >>> tm = transaction.TransactionManager()
+ >>> root = db.open(transaction_manager=tm).root()
+ >>> _ = tm.begin()
+
+When I did this in production, in a vain attempt to fix the queryNextUtility
+problem:
+
+ >>> sm1 = root['Application'].getSiteManager()
+ >>> sm1.__bases__ = (zope.component.getGlobalSiteManager(), )
+ >>> tm.commit()
+
+I started getting KeyError: 'base' in _LocalAdapterRegistryGeneration3SupportMixin
+__setstate__ which didn't expect the registry to be pickled without someone
+carefully removing the _registrations attribute it left in place.
+
+ >>> tm2 = transaction.TransactionManager()
+ >>> root2 = db.open(transaction_manager=tm2).root()
+ >>> _ = tm2.begin()
+ >>> sm1 = root2['Application'].getSiteManager()
+ >>> len(sm1.__bases__)
+ 1
+ >>> sm1.queryUtility(IFoo, 'globalfoo') is not None
+ True
+ >>> zope.app.component.queryNextUtility(sm1, IFoo, 'globalfoo') is not None
+ True
+
+Cleanup:
+
+ >>> db.close()
+
+"""
+
+
class GlobalRegistry:
pass
More information about the Checkins
mailing list