Hi Armin,

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

True, it doesn't invoke coercion in the sense that a coercion
method is called, but the mechanism described in the PEP is
still used via PyNumber_InPlaceAdd().

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

The Py_NotImplemented singleton was introduced in the coercion
proposal to mean "there is no implementation to execute the requested
operation on the given combination of types".

At the time we also considered using an exception for this, but
it turned out that this caused too much of a slow-down. Hence the use
of a special singleton which could be tested for by a simple
pointer comparison.

Originally, the singleton was only needed for mixed-type operations.
It seems that its use has spread to other areas as well and
can now also refer to missing same-type operator implementations.

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

You're right - silly me.

Regards,
-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source  (#1, Dec 29 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 ! ::::
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to