Re: Interfaces vs ZCA concepts

Martin Aspeli <[email protected]>
Newsgroups gmane.comp.web.zope.devel
Message-ID <[email protected]>
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

_______________________________________________
Zope-Dev maillist  -  [email protected]
https://mail.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 https://mail.zope.org/mailman/listinfo/zope-announce
 https://mail.zope.org/mailman/listinfo/zope )
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.