Miscellaneous code fiddling:
- SLOT1BINFULL() macro: changed this to check for __rop__ overriding __op__, like binary_op1() in abstract.c -- the latter only calls the slot function once if both types use the same slot function, so the slot function must make both calls -- which it already did for the __op__, __rop__ order, but not yet for the __rop__, __op__ order when B.__class__ is a subclass of A.__class__. - slot_sq_contains(), slot_nb_nonzero(): use lookup_maybe() rather than lookup_method() which sets an exception which we then clear. - slot_nb_coerce(): don't give up when left argument's __coerce__ returns NotImplemented, but give the right argument a chance.
This commit is contained in:
parent
89c4264792
commit
55f2099b2f
|
@ -2693,9 +2693,21 @@ static PyObject * \
|
||||||
FUNCNAME(PyObject *self, PyObject *other) \
|
FUNCNAME(PyObject *self, PyObject *other) \
|
||||||
{ \
|
{ \
|
||||||
static PyObject *cache_str, *rcache_str; \
|
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 && \
|
if (self->ob_type->tp_as_number != NULL && \
|
||||||
self->ob_type->tp_as_number->SLOTNAME == TESTFUNC) { \
|
self->ob_type->tp_as_number->SLOTNAME == TESTFUNC) { \
|
||||||
PyObject *r; \
|
PyObject *r; \
|
||||||
|
if (do_other && \
|
||||||
|
PyType_IsSubtype(other->ob_type, self->ob_type)) { \
|
||||||
|
r = call_maybe( \
|
||||||
|
other, ROPSTR, &rcache_str, "(O)", self); \
|
||||||
|
if (r != Py_NotImplemented) \
|
||||||
|
return r; \
|
||||||
|
Py_DECREF(r); \
|
||||||
|
do_other = 0; \
|
||||||
|
} \
|
||||||
r = call_maybe( \
|
r = call_maybe( \
|
||||||
self, OPSTR, &cache_str, "(O)", other); \
|
self, OPSTR, &cache_str, "(O)", other); \
|
||||||
if (r != Py_NotImplemented || \
|
if (r != Py_NotImplemented || \
|
||||||
|
@ -2703,8 +2715,7 @@ FUNCNAME(PyObject *self, PyObject *other) \
|
||||||
return r; \
|
return r; \
|
||||||
Py_DECREF(r); \
|
Py_DECREF(r); \
|
||||||
} \
|
} \
|
||||||
if (other->ob_type->tp_as_number != NULL && \
|
if (do_other) { \
|
||||||
other->ob_type->tp_as_number->SLOTNAME == TESTFUNC) { \
|
|
||||||
return call_maybe( \
|
return call_maybe( \
|
||||||
other, ROPSTR, &rcache_str, "(O)", self); \
|
other, ROPSTR, &rcache_str, "(O)", self); \
|
||||||
} \
|
} \
|
||||||
|
@ -2785,7 +2796,7 @@ slot_sq_contains(PyObject *self, PyObject *value)
|
||||||
PyObject *func, *res, *args;
|
PyObject *func, *res, *args;
|
||||||
static PyObject *contains_str;
|
static PyObject *contains_str;
|
||||||
|
|
||||||
func = lookup_method(self, "__contains__", &contains_str);
|
func = lookup_maybe(self, "__contains__", &contains_str);
|
||||||
|
|
||||||
if (func != NULL) {
|
if (func != NULL) {
|
||||||
args = Py_BuildValue("(O)", value);
|
args = Py_BuildValue("(O)", value);
|
||||||
|
@ -2800,8 +2811,9 @@ slot_sq_contains(PyObject *self, PyObject *value)
|
||||||
return -1;
|
return -1;
|
||||||
return PyObject_IsTrue(res);
|
return PyObject_IsTrue(res);
|
||||||
}
|
}
|
||||||
|
else if (PyErr_Occurred())
|
||||||
|
return -1;
|
||||||
else {
|
else {
|
||||||
PyErr_Clear();
|
|
||||||
return _PySequence_IterSearch(self, value,
|
return _PySequence_IterSearch(self, value,
|
||||||
PY_ITERSEARCH_CONTAINS);
|
PY_ITERSEARCH_CONTAINS);
|
||||||
}
|
}
|
||||||
|
@ -2866,23 +2878,23 @@ slot_nb_nonzero(PyObject *self)
|
||||||
PyObject *func, *res;
|
PyObject *func, *res;
|
||||||
static PyObject *nonzero_str, *len_str;
|
static PyObject *nonzero_str, *len_str;
|
||||||
|
|
||||||
func = lookup_method(self, "__nonzero__", &nonzero_str);
|
func = lookup_maybe(self, "__nonzero__", &nonzero_str);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
PyErr_Clear();
|
if (PyErr_Occurred())
|
||||||
func = lookup_method(self, "__len__", &len_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (func != NULL) {
|
|
||||||
res = PyObject_CallObject(func, NULL);
|
|
||||||
Py_DECREF(func);
|
|
||||||
if (res == NULL)
|
|
||||||
return -1;
|
return -1;
|
||||||
return PyObject_IsTrue(res);
|
func = lookup_maybe(self, "__len__", &len_str);
|
||||||
}
|
if (func == NULL) {
|
||||||
else {
|
if (PyErr_Occurred())
|
||||||
PyErr_Clear();
|
return -1;
|
||||||
return 1;
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
res = PyObject_CallObject(func, NULL);
|
||||||
|
Py_DECREF(func);
|
||||||
|
if (res == NULL)
|
||||||
|
return -1;
|
||||||
|
return PyObject_IsTrue(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
SLOT0(slot_nb_invert, "__invert__")
|
SLOT0(slot_nb_invert, "__invert__")
|
||||||
|
@ -2907,20 +2919,21 @@ slot_nb_coerce(PyObject **a, PyObject **b)
|
||||||
return -1;
|
return -1;
|
||||||
if (r == Py_NotImplemented) {
|
if (r == Py_NotImplemented) {
|
||||||
Py_DECREF(r);
|
Py_DECREF(r);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
|
else {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"__coerce__ didn't return a 2-tuple");
|
"__coerce__ didn't return a 2-tuple");
|
||||||
|
Py_DECREF(r);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*a = PyTuple_GET_ITEM(r, 0);
|
||||||
|
Py_INCREF(*a);
|
||||||
|
*b = PyTuple_GET_ITEM(r, 1);
|
||||||
|
Py_INCREF(*b);
|
||||||
Py_DECREF(r);
|
Py_DECREF(r);
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
*a = PyTuple_GET_ITEM(r, 0);
|
|
||||||
Py_INCREF(*a);
|
|
||||||
*b = PyTuple_GET_ITEM(r, 1);
|
|
||||||
Py_INCREF(*b);
|
|
||||||
Py_DECREF(r);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if (other->ob_type->tp_as_number != NULL &&
|
if (other->ob_type->tp_as_number != NULL &&
|
||||||
other->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
|
other->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
|
||||||
|
|
Loading…
Reference in New Issue