Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2ed6bf8

Browse files
committed
Merge branch changes (coercion, rich comparisons) into trunk.
1 parent 33f4d6d commit 2ed6bf8

4 files changed

Lines changed: 106 additions & 11 deletions

File tree

Objects/complexobject.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,8 @@ complex_richcompare(PyObject *v, PyObject *w, int op)
560560
Py_INCREF(Py_NotImplemented);
561561
return Py_NotImplemented;
562562
}
563-
/* May sure both arguments use complex comparison.
564-
This implies PyComplex_Check(a) && PyComplex_Check(b). */
565-
if (v->ob_type->tp_richcompare != complex_richcompare ||
566-
w->ob_type->tp_richcompare != complex_richcompare) {
563+
/* Make sure both arguments are complex. */
564+
if (!(PyComplex_Check(v) && PyComplex_Check(w))) {
567565
Py_DECREF(v);
568566
Py_DECREF(w);
569567
Py_INCREF(Py_NotImplemented);

Objects/object.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,14 @@ try_rich_compare(PyObject *v, PyObject *w, int op)
365365
richcmpfunc f;
366366
PyObject *res;
367367

368+
if (v->ob_type != w->ob_type &&
369+
PyType_IsSubtype(w->ob_type, v->ob_type) &&
370+
(f = RICHCOMPARE(w->ob_type)) != NULL) {
371+
res = (*f)(w, v, swapped_op[op]);
372+
if (res != Py_NotImplemented)
373+
return res;
374+
Py_DECREF(res);
375+
}
368376
if ((f = RICHCOMPARE(v->ob_type)) != NULL) {
369377
res = (*f)(v, w, op);
370378
if (res != Py_NotImplemented)

Objects/stringobject.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -824,10 +824,8 @@ string_richcompare(PyStringObject *a, PyStringObject *b, int op)
824824
int min_len;
825825
PyObject *result;
826826

827-
/* May sure both arguments use string comparison.
828-
This implies PyString_Check(a) && PyString_Check(b). */
829-
if (a->ob_type->tp_richcompare != (richcmpfunc)string_richcompare ||
830-
b->ob_type->tp_richcompare != (richcmpfunc)string_richcompare) {
827+
/* Make sure both arguments are strings. */
828+
if (!(PyString_Check(a) && PyString_Check(b))) {
831829
result = Py_NotImplemented;
832830
goto out;
833831
}

Objects/typeobject.c

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,6 +1837,40 @@ BINARY(rshift, "x>>y");
18371837
BINARY(and, "x&y");
18381838
BINARY(xor, "x^y");
18391839
BINARY(or, "x|y");
1840+
1841+
static PyObject *
1842+
wrap_coercefunc(PyObject *self, PyObject *args, void *wrapped)
1843+
{
1844+
coercion func = (coercion)wrapped;
1845+
PyObject *other, *res;
1846+
int ok;
1847+
1848+
if (!PyArg_ParseTuple(args, "O", &other))
1849+
return NULL;
1850+
ok = func(&self, &other);
1851+
if (ok < 0)
1852+
return NULL;
1853+
if (ok > 0) {
1854+
Py_INCREF(Py_NotImplemented);
1855+
return Py_NotImplemented;
1856+
}
1857+
res = PyTuple_New(2);
1858+
if (res == NULL) {
1859+
Py_DECREF(self);
1860+
Py_DECREF(other);
1861+
return NULL;
1862+
}
1863+
PyTuple_SET_ITEM(res, 0, self);
1864+
PyTuple_SET_ITEM(res, 1, other);
1865+
return res;
1866+
}
1867+
1868+
static struct wrapperbase tab_coerce[] = {
1869+
{"__coerce__", (wrapperfunc)wrap_coercefunc,
1870+
"x.__coerce__(y) <==> coerce(x, y)"},
1871+
{0}
1872+
};
1873+
18401874
BINARY(floordiv, "x//y");
18411875
BINARY(truediv, "x/y # true division");
18421876

@@ -2573,7 +2607,7 @@ add_operators(PyTypeObject *type)
25732607
ADD(nb->nb_and, tab_and);
25742608
ADD(nb->nb_xor, tab_xor);
25752609
ADD(nb->nb_or, tab_or);
2576-
/* We don't support coerce() -- see above comment */
2610+
ADD(nb->nb_coerce, tab_coerce);
25772611
ADD(nb->nb_int, tab_int);
25782612
ADD(nb->nb_long, tab_long);
25792613
ADD(nb->nb_float, tab_float);
@@ -2840,7 +2874,64 @@ SLOT1BIN(slot_nb_rshift, nb_rshift, "__rshift__", "__rrshift__")
28402874
SLOT1BIN(slot_nb_and, nb_and, "__and__", "__rand__")
28412875
SLOT1BIN(slot_nb_xor, nb_xor, "__xor__", "__rxor__")
28422876
SLOT1BIN(slot_nb_or, nb_or, "__or__", "__ror__")
2843-
/* Not coerce() */
2877+
2878+
static int
2879+
slot_nb_coerce(PyObject **a, PyObject **b)
2880+
{
2881+
static PyObject *coerce_str;
2882+
PyObject *self = *a, *other = *b;
2883+
2884+
if (self->ob_type->tp_as_number != NULL &&
2885+
self->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
2886+
PyObject *r;
2887+
r = call_maybe(
2888+
self, "__coerce__", &coerce_str, "(O)", other);
2889+
if (r == NULL)
2890+
return -1;
2891+
if (r == Py_NotImplemented) {
2892+
Py_DECREF(r);
2893+
return 1;
2894+
}
2895+
if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
2896+
PyErr_SetString(PyExc_TypeError,
2897+
"__coerce__ didn't return a 2-tuple");
2898+
Py_DECREF(r);
2899+
return -1;
2900+
}
2901+
*a = PyTuple_GET_ITEM(r, 0);
2902+
Py_INCREF(*a);
2903+
*b = PyTuple_GET_ITEM(r, 1);
2904+
Py_INCREF(*b);
2905+
Py_DECREF(r);
2906+
return 0;
2907+
}
2908+
if (other->ob_type->tp_as_number != NULL &&
2909+
other->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
2910+
PyObject *r;
2911+
r = call_maybe(
2912+
other, "__coerce__", &coerce_str, "(O)", self);
2913+
if (r == NULL)
2914+
return -1;
2915+
if (r == Py_NotImplemented) {
2916+
Py_DECREF(r);
2917+
return 1;
2918+
}
2919+
if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
2920+
PyErr_SetString(PyExc_TypeError,
2921+
"__coerce__ didn't return a 2-tuple");
2922+
Py_DECREF(r);
2923+
return -1;
2924+
}
2925+
*a = PyTuple_GET_ITEM(r, 1);
2926+
Py_INCREF(*a);
2927+
*b = PyTuple_GET_ITEM(r, 0);
2928+
Py_INCREF(*b);
2929+
Py_DECREF(r);
2930+
return 0;
2931+
}
2932+
return 1;
2933+
}
2934+
28442935
SLOT0(slot_nb_int, "__int__")
28452936
SLOT0(slot_nb_long, "__long__")
28462937
SLOT0(slot_nb_float, "__float__")
@@ -3336,7 +3427,7 @@ override_slots(PyTypeObject *type, PyObject *dict)
33363427
NBSLOT("__and__", nb_and, slot_nb_and);
33373428
NBSLOT("__xor__", nb_xor, slot_nb_xor);
33383429
NBSLOT("__or__", nb_or, slot_nb_or);
3339-
/* Not coerce() */
3430+
NBSLOT("__coerce__", nb_coerce, slot_nb_coerce);
33403431
NBSLOT("__int__", nb_int, slot_nb_int);
33413432
NBSLOT("__long__", nb_long, slot_nb_long);
33423433
NBSLOT("__float__", nb_float, slot_nb_float);

0 commit comments

Comments
 (0)