deferredimport breaks some standalone usages of zope.component

Bug #98401 reported by Gary Poster
2
Affects Status Importance Assigned to Milestone
Zope 3
Fix Released
Medium
Gary Poster

Bug Description

when zope.component is used by itself (i.e., without any other Zope code than its own dependencies having been imported), then the following fails.

>>> import zope.component
>>> import zope.interface
>>> class IFoo(interface.Interface):
... pass
...
>>> class Bar(object):
... pass
...
>>> class BarToFooAdapter(object):
... zope.interface.implements(IFoo)
... zope.component.adapts(Bar)
... def __init__(self, obj):
... self.bar = obj
...
>>> zope.component.provideAdapter(BarToFooAdapter)
>>> bar = Bar() # implements IBar
>>> IFoo(bar)
Traceback (most recent call last):
...
TypeError: ('Could not adapt', <Bar instance at ...>, <InterfaceClass IFoo>)

However, if you then access any of the deferred imports in zope/component/__init__.py that come from zope/component/_api.py, the adapter hook registration in _api.py is called so that zope.component is now set upcorrectly with zope.interface, and the adaptation will work.

For instance:

>>> ignore = zope.component.getAdapter
>>> IFoo(bar)
<BarToFooAdapter instance at ...>

A solution to this that keeps the deferred import mechanism in place is not obvious to me, but hopefully it will be to someone else.

Tags: core issue
Revision history for this message
Stephan Richter (srichter) wrote :

Gary, did you register an adapter hook, so that calling an interface will work? I do not think this is a deferred import bug.

Revision history for this message
Gary Poster (gary) wrote :

> However, if you then access any of the deferred imports in
> zope/component/__init__.py that come from zope/component/_api.py, the
> adapter hook registration in _api.py is called so that zope.component is
> now set up correctly with zope.interface, and the adaptation will work.

I agree that this does not indicate that something needs to change in the deferredimport code, unless the basic approach changes in some way I can't see.

The fact that you can have such different behavior (interface adaptation working or not working) depending on whether you access an attribute in the zope.component module is the bug (or the unpleasant and surprising fragility?). The interaction of deferredimport and the hook registration in _api.py causes the problem.

Here are a few solutions.

- move getSiteManager and the adapter hook and the adapter hook registration back in __init__.py

- move just the adapter hook and its registration to another module that is imported directly within __init__.py and that itself imports zope.component, so it is automagically regsitered on import as currently intended, and when it accesses zope.component.getSiteManager in the hook the deferredimport works as expected.

- remove the automagical adapter hook registration and require explicit registration for clients of zope.component who want to use the interface syntax.

I actually don't mind the automagic in this case, but can see arguments either way. Option 2 seems kludgy but it's the best I see there. The other tricky variants to the approach that I can imagine possibly working don't seem any better.

Revision history for this message
Gary Poster (gary) wrote :

Status: Pending => Accepted

 Supporters added: poster

After talking with Jim, here's the plan. For now, we'll continue the automagic behavior. I'll try to fix it so that this case works, probably by tweaks to make accessing `provideAdapter` have the side effect. Long term, we will contemplate an explicit registration approach. If I'm able to fix this problem, I'll close this issue and reopen one requesting the explicit registration approach at a later day.

Revision history for this message
Gary Poster (gary) wrote :

Status: Accepted => Resolved

Test and fix in rev 69342 (trunk) and rev 69346 (3.3 branch). New bug mentioned in previous comment is http://www.zope.org/Collectors/Zope3-dev/685 .

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.