Re: Interfaces vs ZCA concepts

Tres Seaver <[email protected]>
Newsgroups gmane.comp.web.zope.devel
Message-ID <[email protected]>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin Aspeli wrote:
> Tres Seaver wrote:
>> Martin Aspeli wrote: 
>>> 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>)

The "Could not adapt" traceback tells you that it isnt The ZCA doing
that:  it is the C code inside zope.interface.  One might argue that a
better exception would be LookupError:  we haven't "violted the
contract" here.

>>    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. :)

The interface machinery catches whatever the adapter hook raises and
returns a TypeError instead.

>> 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!)
>>
>> 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

I can't see anything compelling about making that transform mechanical.
 As noted above, it is already *wrong* to be relying on a specific
exception type here anyway.

> 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.

Why would we bend over backward to keep obviously broken code seeming to
work?

> 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.

Given that the behavior isn't part of any API to date, I'm suggesting
that we *document* the behavior ahead of time (for new code), without
any regard for BBB.  We could document the existing __call__ behavior as
well, if needed.

In either case, I think TypeError (or maybe LookupError) is the *right*
choice:  we don't want to "hide" zope.component's API functions and then
turn around and require folks to import zope.component just to catch its
local exception types.



Tres.
- --
===================================================================
Tres Seaver          +1 540-429-0999          [email protected]
Palladion Software   "Excellence by Design"    http://palladion.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkspU4EACgkQ+gerLs4ltQ7koQCgpoHUw8vQZfAQcJec9zWAdKhU
V3kAoIliRpCfujwFSCIs4Gi6z+BIwq0N
=2FUT
-----END PGP SIGNATURE-----

_______________________________________________
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.