A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://mail.python.org/pipermail/python-dev/2005-December/059221.html below:

[Python-Dev] NotImplemented reaching top-level

[Python-Dev] NotImplemented reaching top-levelArmin Rigo arigo at tunes.org
Wed Dec 28 23:14:30 CET 2005
Hi Marc,

On Wed, Dec 28, 2005 at 09:56:43PM +0100, M.-A. Lemburg wrote:
> >>>>> d += 1.2
> >>>>> d
> >> NotImplemented
> 
> The PEP documenting the coercion logic has complete tables
> for what should happen:

Well, '+=' does not invoke coercion at all, with new-style classes like
Decimal.

> 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.

Indeed.  The bug was caused by this delegation, which (prior to my
patch) would also return a Py_NotImplemented that would leak through
abstract.c.  My patch is to remove this unnecessary delegation by not
defining sq_concat/sq_repeat for user-defined classes, and restoring the
original expectation that the sq_concat/sq_repeat slots should not
return Py_NotImplemented.  How does this relate to coercion?

> 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.

Indeed, however:

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

This last statement also returns Py_NotImplemented.  So it's expected of
this function to be able to return Py_NotImplemented, isn't it?  The
type slots like nb_add can return Py_NotImplemented; the code that
converts it to a TypeError is in the caller, which is abstract.c.


A bientot,

Armin
More information about the Python-Dev mailing list

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4