[Zope3-dev] Traversal without hiding deep exceptions
Steve Alexander
steve at canonical.com
Thu Oct 14 15:18:58 EDT 2004
Recently, a software developer I work with had some difficulty debugging
a problem in out large Zope3 application.
In DefaultTraversable, from src/zope/app/traversing/adapters.py, the
traverse() method uses 'getattr' to see if 'subject' has the attribute
'name'.
def traverse(self, name, furtherPath):
subject = self._subject
__traceback_info__ = (subject, name, furtherPath)
attr = getattr(subject, name, _marker)
if attr is not _marker:
return attr
if hasattr(subject, '__getitem__'):
# Let exceptions propagate.
return subject[name]
else:
raise NotFoundError(subject, name)
The problem with this use of getattr is that the _marker will be
returned not only if 'subject' lacks an attribute called 'name', but
also if the attribute 'name' is a property (or other descriptor) that
causes code to run that contains errors and raises AttributeError.
This "hiding" of AttributeErrors is intrinsic to Python. I hope the
behavior of getattr will change in a future version of Python so that it
does not hide "deep" AttributeErrors.
But, I think we need to do better than the Python behaviour for Zope 3.
Zope 3 is all about integrating software in interesting and complex
ways. To make the process of integration workable, we need to avoid
hiding such exceptions.
There is a way around this: Some code in the interface package uses a
trick from Phillip Eby to see whether an exception was raised
"immediately" or "deeply" by examining the depth of the traceback. I've
put this code into a function:
import sys
def deep_exception():
return sys.exc_info()[2].tb_next is not None
So, the code in traverse() could read something like:
def traverse(self, name, furtherPath):
subject = self._subject
__traceback_info__ = (subject, name, furtherPath)
! try:
! return getattr(subject, name)
! except AttributeError:
! if deep_exception():
! raise
if hasattr(subject, '__getitem__'):
# Let exceptions propagate.
return subject[name]
else:
raise NotFoundError(subject, name)
--
Steve Alexander
More information about the Zope3-dev
mailing list