[Python-Dev] NotImplemented reaching top-level (original) (raw)

M.-A. Lemburg mal at egenix.com
Wed Dec 28 21:56:43 CET 2005


Armin Rigo wrote:

Hi Facundo,

On Sat, Dec 24, 2005 at 02:31:19PM -0300, Facundo Batista wrote:

d += 1.2 d NotImplemented The situation appears to be a mess. Some combinations of specific operators fail to convert NotImplemented to a TypeError, depending on old- or new-style-class-ness, although this is clearly a bug (e.g. in an example like yours but using -= instead of +=, we get the correct TypeError.) Obviously, we need to write some comprehensive tests about this. But now I just found out that the old, still-pending SF bug #847024 about A()*5 in new-style classes hasn't been given any attention; my theory is that nobody fully understands the convoluted code paths of abstract.c any more :-(

The PEP documenting the coercion logic has complete tables for what should happen:

http://www.python.org/peps/pep-0208.html

Looking at the code in abstract.c the above problem appears to be related to the special cases applied to += and *= in case both operands cannot deal with the type combination.

In such a case, a check is done whether the operation could be interpreted as sequence operation (concat or repeat) and then delegated to the appropriate handlers.

But then again, looking in typeobject.c, the following code could be the cause for leaking a NotImplemented singleton reference:

#define SLOT1BINFULL(FUNCNAME, TESTFUNC, SLOTNAME, OPSTR, ROPSTR)
static PyObject *
FUNCNAME(PyObject *self, PyObject *other)
{
static PyObject *cache_str, *rcache_str;
int do_other = self->ob_type != other->ob_type &&
other->ob_type->tp_as_number != NULL &&
other->ob_type->tp_as_number->SLOTNAME == TESTFUNC;
if (self->ob_type->tp_as_number != NULL &&
self->ob_type->tp_as_number->SLOTNAME == TESTFUNC) {
PyObject *r;
if (do_other &&
PyType_IsSubtype(other->ob_type, self->ob_type) &&
method_is_overloaded(self, other, ROPSTR)) {
r = call_maybe(
other, ROPSTR, &rcache_str, "(O)", self);
if (r != Py_NotImplemented)
return r;
Py_DECREF(r);
do_other = 0;
}
r = call_maybe(
self, OPSTR, &cache_str, "(O)", other);
if (r != Py_NotImplemented ||
other->ob_type == self->ob_type)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If both types are of the same type, then a NotImplemented returng value would be returned.

        return r; \
    Py_DECREF(r); \
} \
if (do_other) { \
    return call_maybe( \
        other, ROPSTR, &rcache_str, "(O)", self); \
} \
Py_INCREF(Py_NotImplemented); \
return Py_NotImplemented; \

}

Strange enough, the SLOT1BINFULL macro is not used by the inplace concat or repeat slots...

-- Marc-Andre Lemburg eGenix.com

Professional Python Services directly from the Source (#1, Dec 28 2005)

Python/Zope Consulting and Support ... http://www.egenix.com/ mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/


::: Try mxODBC.Zope.DA for Windows,Linux,Solaris,FreeBSD for free ! ::::



More information about the Python-Dev mailing list