-----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 tseaver@palladion.com 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-----