[Zope-dev] Interfaces vs ZCA concepts
Martin Aspeli
optilude+lists at gmail.com
Wed Dec 16 00:00:05 EST 2009
Tres Seaver wrote:
>>> +1 to TypeError: nobody really cares about the type of the error: code
>>> that wants to be robust about a failure uses the 'query' methods. As
>>> long as the message is informative enough (which ComponentLookupError
>>> isn't, really) we should be fine. If we made CLE derive from TypeError,
>>> we could even still be satisfying the contract.
>> zope.component raises TypeError if you can't adapt. It raises
>> ComponentLookupError it can't find a utility.
>
> Not so: see $ZSVN/zope.component/trunk/src/zope/component/registry.py:
I'm pretty sure you get a TypeError when Zope can't adapt. I'm not sure
where it's thrown from, though.
Stupid example:
>>> from plone.portlets.interfaces import IPortletType
>>> class X(object): pass
...
>>> x = ()
>>> IPortletType(x)
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: ('Could not adapt', (), <InterfaceClass
plone.portlets.interfaces.IPortletType>)
> class Components:
> ...
> def getUtility(self, provided, name=u''):
> utility = self.utilities.lookup((), provided, name)
> if utility is None:
> raise ComponentLookupError(provided, name)
> return utility
> ...
> def getAdapter(self, object, interface, name=u''):
> adapter = self.adapters.queryAdapter(object, interface, name)
> if adapter is None:
> raise ComponentLookupError(object, interface, name)
> return adapter
getAdapter() is different, though:
>>> from zope.component import getAdapter
>>> getAdapter(x, IPortletType)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File
"/Users/optilude/.buildout/eggs/zope.component-3.7.1-py2.6.egg/zope/component/_api.py",
line 98, in getAdapter
raise ComponentLookupError(object, interface, name)
ComponentLookupError: ((), <InterfaceClass
plone.portlets.interfaces.IPortletType>, u'')
> which matches the contract spelled out in the docstrings for IComponent.
> That class raises TypeError only for invalid values passed to the
> various registration functions.
Something else is raising TypeError then. :)
> At any rate, we are talking about errors raised from zope.itnerface
> APIs, which nowhere mention or use CLE::
Ok.
> $ svn info . | grep URL
> URL: svn+ssh://svn.zope.org/repos/main/zope.interface/trunk
> $ svn up
> At revision 106615.
> $ find . -name "*.py" | xargs grep ComponentLookupError
> $
>
> Nobody calling an interface today has any *defined* behavior to expect
> in the case of failure (in fact, '__call__' is not even part of IInterface!)
>
>> Let's keep exceptions the same. People do catch specific errors, so
>> those who've done 'except TypeError' now aren't going to be happy if we
>> change that to something else when they try to move to use the "new" API.
>
> Please point to existing code which calls 'IFoo.utility(name="bar")' and
> catches a CLE. Since this is a new API we are talkign about, there
> can't be any BBB concerns.
True, but we're also going to ask people to change their use of
getUtility(IFoo) to IFoo.utility and ditto for adaption. If I have
existing code that looks like this:
try:
foo = IFoo(bar)
except TypeError:
pass
I would like to be able to move that "mechanically" to:
try:
foo = IFoo.adapt(bar)
except TypeError:
pass
If I have to change the exception type in any of the scenarios (utility
lookup would be similar) then that would be another change to detect,
and possibly a harder one to spot in less contrived code.
> Any code today which wants a utility is calling 'getUtilty' (if it
> *knows* the utility must be registered) or 'queryUtility' (if it thinks
> it might not be). Less facetiously than my first challenge: please
> point to actual code in the wild which looks like::
>
> try:
> foo = getUtilty(IFoo, name='bar')
> except ComponentLookupError:
> # do something
>
> instead of::
>
> foo = queryUtility(IFoo, name='bar')
> if foo is None:
> # do something
>
> I will argue that any code doing the first, outside of maybe tests of
> the ZCA itself is plain broken.
Perhaps, but I'm pretty sure people have done this. They may also have
done it in tests.
I'm not religious about it, but I think that if we're only changing the
API, it'd be preferable not to change the exceptions we throw unless
semantics also change.
Martin
--
Author of `Professional Plone Development`, a book for developers who
want to work with Plone. See http://martinaspeli.net/plone-book
More information about the Zope-Dev
mailing list