Skip to content

Commit

Permalink
- Fix empty __bases__ on LocalSiteManager objects loaded from old dat…
Browse files Browse the repository at this point in the history
…abases,

  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.
  • Loading branch information
mgedmin committed Jul 15, 2009
1 parent 45759fb commit 620bad1
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 2 deletions.
10 changes: 10 additions & 0 deletions CHANGES.txt
Expand Up @@ -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)
------------------

Expand Down
2 changes: 1 addition & 1 deletion src/zope/app/component/back35.py
Expand Up @@ -889,7 +889,7 @@ def append(self, value):
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:
Expand Down
6 changes: 6 additions & 0 deletions src/zope/app/component/site.py
Expand Up @@ -192,6 +192,12 @@ def __init__(self, site):
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()
Expand Down
49 changes: 48 additions & 1 deletion src/zope/app/component/tests/test_registration.py
Expand Up @@ -63,6 +63,7 @@ def tearDown(test):

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

Expand Down Expand Up @@ -137,6 +138,13 @@ def test_old_databases_backward_compat():
>>> 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()])
Expand Down Expand Up @@ -343,7 +351,46 @@ def test_old_databases_backward_compat():
>>> all.remove(sm3['default']['4'])
>>> all.remove(sm3['default']['5'])
>>> len(all)
2
3
Cleanup:
>>> db.close()
"""


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:
Expand Down

0 comments on commit 620bad1

Please sign in to comment.