[Zope3-dev] Could queryAdapter() have side effects?

Martin Aspeli optilude at gmx.net
Sat Feb 10 21:23:18 EST 2007


Hi,

This is most likely just something gone wrong with my test setup, but I 
thought I'd ask just in case I've hit some obscure bug.

Basically, I have a test that uses PloneTestCase and ZopeTestCase on 
Zope 2.10, with a layer that loads site.zcml. The ZCML for my package 
registers a particular adapter. There are no local components involved 
as far as I know.

The old code did this:

     def _handleReferences( self, baseline, wc, mode, wc_ref ):

         annotations = IAnnotations( wc_ref )

         # handle forward references
         for relationship in baseline.getRelationships():
             # look for a named relation adapter first
             adapter = component.queryAdapter( baseline,
 
interfaces.ICheckinCheckoutReference,
                                               relationship )

             if adapter is None: # default

                 adapter = interfaces.ICheckinCheckoutReference( baseline )

             references = baseline.getReferenceImpl( relationship )

             mode_method = getattr( adapter, mode )
             mode_method( baseline, wc, references, annotations )

It's basically trying a named adapter if it can, and then falling back 
on the default if no named adapter was registered. In one of my tests, 
which does nothing funny with the CA at all, as far as I can tell, it 
just happens to lead to this piece of code, I got a ComponentLookupError 
for the fallback (adapter = interfaces.ICheckinCheckoutReference( 
baseline )).

Tracing it, this looked rally weird, because 
getSiteManager().getAdapters((baseline,), 
interfaces.ICheckinCheckoutReference) was returning a suitable adapter 
with name=u"".

Out of desperation, I rewrote the code like this:

     def _handleReferences( self, baseline, wc, mode, wc_ref ):

         annotations = IAnnotations( wc_ref )

         baseline_adapter = interfaces.ICheckinCheckoutReference( baseline )

         # handle forward references
         for relationship in baseline.getRelationships():
             # look for a named relation adapter first
             adapter = component.queryAdapter( baseline,
 
interfaces.ICheckinCheckoutReference,
                                               relationship )

             if adapter is None: # default
                 adapter = baseline_adapter

             references = baseline.getReferenceImpl( relationship )

             mode_method = getattr( adapter, mode )
             mode_method( baseline, wc, references, annotations )

And this works! Some investigation with pdb revealed that if I invoked 
the ICheckinCheckoutReference default adapter lookup at any point before 
the call to queryAdapter(), it would work properly, but if the 
queryAdapter() call came first, I'd get a ComponentLookupError.

I'm really stumped as to why this may be the case. There's probably 
something odd in my test setup that I've somehow worked around by 
rearranging this code, but I'd love to hear any theories on what.

In the worst case, though, it may be a bug in the CA.

The test in question is here: 
http://dev.plone.org/plone/browser/plone.app.iterate/trunk/plone/app/iterate/tests/test_iterate.py
The ZCML is here: 
http://dev.plone.org/plone/browser/plone.app.iterate/trunk/plone/app/iterate/configure.zcml
And the code above here: 
http://dev.plone.org/plone/browser/plone.app.iterate/trunk/plone/app/iterate/copier.py

Martin



More information about the Zope3-dev mailing list