I see -- so when this function returns NULL, the exception state is
undefined? This needs a clear comment...

Wouldn't it lead to cleaner code all around to change this function so it
guarantees that there is never any pending exception, and rename it
`PyArray_GetAttrString_NoExc`? (With a comment noting that it can be much
faster than PyObject_GetAttrString in cases where the attribute usually
doesn't exist?)


On Fri, Jun 7, 2013 at 7:13 PM, Mark Weissman <notifications@github.com>wrote:

> In numpy/core/src/multiarray/common.c:
>
> > +    if (tp == &PyList_Type || tp == &PyTuple_Type || v == Py_None) {
> > +        return (PyObject *)NULL;
> > +    }
> > +    else if (tp->tp_getattr != NULL) {
> > +        return (*tp->tp_getattr)(v, name);
> > +    }
> > +    else if (tp->tp_getattro != NULL) {
> > +        PyObject *w, *res;
> > +#if defined(NPY_PY3K)
> > +        w = PyUnicode_InternFromString(name);
> > +#else
> > +        w = PyString_InternFromString(name);
> > +#endif
> > +        if (w == NULL)
> > +            return (PyObject *)NULL;
> > +        res = (*tp->tp_getattro)(v, w);
>
> The existing code calls PyObject_GetAttrString which also throws theses
> exceptions.
> The existing code handles these. I haven't changed anything there.
>
> In common.c there was one place where I HasAttr was called and a
> PyErr_Clear was added to
> handle this.
>
> What this code does is try to avoid raised exceptions where its easy by
> skipping the call to tp->tp_getattr
> for None, tuple, list, and avoiding the exception directly raised in
> PyObject_GetAttrString.
>
> tp_getattro can still raise exceptions which are handled the old way.
>
> —
> Reply to this email directly or view it on GitHub<https://github.com/numpy/numpy/pull/3410/files#r4593885>
> .
>