[Zope-dev] Re: "hasattr" geddon

Shane Hathaway shane at hathawaymix.org
Sat Jul 10 04:41:07 EDT 2004


On Friday 09 July 2004 11:50 am, Casey Duncan wrote:
> On Fri, 9 Jul 2004 16:22:17 +0200
> Dieter Maurer <dieter at handshake.de> wrote:
> [..]
>
> > The "hasattr" replacement in Python's "__builtin__" could look like:
> >
> >     _marker = []
> >     def hasattr(obj, attr):
> > 	return getattr(obj, attr, _marker) is not _marker

Hmm.  I just heard about this "hasattr geddon".  hasattr is *good*.  Why are 
we fixing hasattr and bare excepts when the real problem is ZODB?  ZODB 
should *not* be sensitive to the way the application handles ConflictErrors.  
When a ConflictError (or ReadConflictError) occurs, the transaction should 
fall into an "uncommitable" state.  From this state, you can only abort the 
transaction; any attempts to write an object or commit cause another 
ConflictError.  Then, only code that can guarantee that the attempted 
transaction is complete should actually abort the transaction, and 
fortunately ZPublisher fits that role.  Today, the abort is implicit, and 
that's the mistake that has caused us to litter the code with knowledge of 
ConflictErrors.  With the "uncommitable" state, it would not matter if the 
application swallows ConflictErrors.

That said, I was surprised to discover that Python 2.3 implements hasattr this 
way (from bltinmodule.c):

        v = PyObject_GetAttr(v, name);
        if (v == NULL) {
                PyErr_Clear();
                Py_INCREF(Py_False);
                return Py_False;
        }
	Py_DECREF(v);
	Py_INCREF(Py_True);
	return Py_True;

It should not swallow all errors, especially now that descriptors make 
computed attributes quite common.  getattr() only recently started catching 
only AttributeErrors, but apparently hasattr is lagging behind.  I suggest 
the consistency between getattr and hasattr should be fixed in Python, not 
Zope.

Shane


More information about the Zope-Dev mailing list