On Mon, 10 Apr 2000 bwarsaw@python.org wrote:
...
... + rtn = PyMember_Get((char *)im, instancemethod_memberlist, name); + if (rtn == NULL) { + PyErr_Clear(); + rtn = PyObject_GetAttrString(im->im_func, name); + if (rtn == NULL) + PyErr_SetString(PyExc_AttributeError, name);
GS> Why do you mask this second error with the AttributeError? GS> Seems that you should just leave whatever is there (typically GS> an AttributeError, but maybe not!).
Good point here, but...
+ rtn = PyMember_Get((char *)op, func_memberlist, name); + if (rtn == NULL) { + PyErr_Clear(); + rtn = PyDict_GetItemString(op->func_dict, name); + if (rtn == NULL) + PyErr_SetString(PyExc_AttributeError, name);
GS> Again, with the masking...
...here I don't want the KeyError to leak through the getattr() call.
Ah! Subtle difference in the code there :-) I agree with you, on remapping the second one. I don't think the first needs to be remapped, however.
If you do "print func.non_existent_attr" wouldn't you want an AttributeError instead of a KeyError? Maybe it should explicitly test for KeyError rather than masking any error coming back from PyDict_GetItemString()? Or better yet (based on your suggestion below), it should do a PyMapping_HasKey() test, raise an AttributeError if not, then just return PyMapping_GetItemString().
Seems that you could just do the PyMapping_GetItemString() and remap the error *if* it occurs. Presumably, the exception is the infrequent case and can stand to be a bit slower. Cheers, -g -- Greg Stein, http://www.lyra.org/