diff options
author | Guido van Rossum <guido@python.org> | 2001-09-27 20:30:07 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-09-27 20:30:07 (GMT) |
commit | 2ed6bf87c9ce5d2e8a0eb33f7aa6503196205a0c (patch) | |
tree | cb597e3c84bf6d845c849e5d715a011922337704 | |
parent | 33f4d6d1db5dd915cce811bd6f7a963d4dbe8db2 (diff) | |
download | cpython-2ed6bf87c9ce5d2e8a0eb33f7aa6503196205a0c.zip cpython-2ed6bf87c9ce5d2e8a0eb33f7aa6503196205a0c.tar.gz cpython-2ed6bf87c9ce5d2e8a0eb33f7aa6503196205a0c.tar.bz2 |
Merge branch changes (coercion, rich comparisons) into trunk.
-rw-r--r-- | Objects/complexobject.c | 6 | ||||
-rw-r--r-- | Objects/object.c | 8 | ||||
-rw-r--r-- | Objects/stringobject.c | 6 | ||||
-rw-r--r-- | Objects/typeobject.c | 97 |
4 files changed, 106 insertions, 11 deletions
diff --git a/Objects/complexobject.c b/Objects/complexobject.c index 32f2b24..ee0ede4 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -560,10 +560,8 @@ complex_richcompare(PyObject *v, PyObject *w, int op) Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } - /* May sure both arguments use complex comparison. - This implies PyComplex_Check(a) && PyComplex_Check(b). */ - if (v->ob_type->tp_richcompare != complex_richcompare || - w->ob_type->tp_richcompare != complex_richcompare) { + /* Make sure both arguments are complex. */ + if (!(PyComplex_Check(v) && PyComplex_Check(w))) { Py_DECREF(v); Py_DECREF(w); Py_INCREF(Py_NotImplemented); diff --git a/Objects/object.c b/Objects/object.c index 6d7a5e9..88fa340 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -365,6 +365,14 @@ try_rich_compare(PyObject *v, PyObject *w, int op) richcmpfunc f; PyObject *res; + if (v->ob_type != w->ob_type && + PyType_IsSubtype(w->ob_type, v->ob_type) && + (f = RICHCOMPARE(w->ob_type)) != NULL) { + res = (*f)(w, v, swapped_op[op]); + if (res != Py_NotImplemented) + return res; + Py_DECREF(res); + } if ((f = RICHCOMPARE(v->ob_type)) != NULL) { res = (*f)(v, w, op); if (res != Py_NotImplemented) diff --git a/Objects/stringobject.c b/Objects/stringobject.c index e29be5a..cfa5f53 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -824,10 +824,8 @@ string_richcompare(PyStringObject *a, PyStringObject *b, int op) int min_len; PyObject *result; - /* May sure both arguments use string comparison. - This implies PyString_Check(a) && PyString_Check(b). */ - if (a->ob_type->tp_richcompare != (richcmpfunc)string_richcompare || - b->ob_type->tp_richcompare != (richcmpfunc)string_richcompare) { + /* Make sure both arguments are strings. */ + if (!(PyString_Check(a) && PyString_Check(b))) { result = Py_NotImplemented; goto out; } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0e6099c..ac201d5 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1837,6 +1837,40 @@ BINARY(rshift, "x>>y"); BINARY(and, "x&y"); BINARY(xor, "x^y"); BINARY(or, "x|y"); + +static PyObject * +wrap_coercefunc(PyObject *self, PyObject *args, void *wrapped) +{ + coercion func = (coercion)wrapped; + PyObject *other, *res; + int ok; + + if (!PyArg_ParseTuple(args, "O", &other)) + return NULL; + ok = func(&self, &other); + if (ok < 0) + return NULL; + if (ok > 0) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + res = PyTuple_New(2); + if (res == NULL) { + Py_DECREF(self); + Py_DECREF(other); + return NULL; + } + PyTuple_SET_ITEM(res, 0, self); + PyTuple_SET_ITEM(res, 1, other); + return res; +} + +static struct wrapperbase tab_coerce[] = { + {"__coerce__", (wrapperfunc)wrap_coercefunc, + "x.__coerce__(y) <==> coerce(x, y)"}, + {0} +}; + BINARY(floordiv, "x//y"); BINARY(truediv, "x/y # true division"); @@ -2573,7 +2607,7 @@ add_operators(PyTypeObject *type) ADD(nb->nb_and, tab_and); ADD(nb->nb_xor, tab_xor); ADD(nb->nb_or, tab_or); - /* We don't support coerce() -- see above comment */ + ADD(nb->nb_coerce, tab_coerce); ADD(nb->nb_int, tab_int); ADD(nb->nb_long, tab_long); ADD(nb->nb_float, tab_float); @@ -2840,7 +2874,64 @@ SLOT1BIN(slot_nb_rshift, nb_rshift, "__rshift__", "__rrshift__") SLOT1BIN(slot_nb_and, nb_and, "__and__", "__rand__") SLOT1BIN(slot_nb_xor, nb_xor, "__xor__", "__rxor__") SLOT1BIN(slot_nb_or, nb_or, "__or__", "__ror__") -/* Not coerce() */ + +static int +slot_nb_coerce(PyObject **a, PyObject **b) +{ + static PyObject *coerce_str; + PyObject *self = *a, *other = *b; + + if (self->ob_type->tp_as_number != NULL && + self->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) { + PyObject *r; + r = call_maybe( + self, "__coerce__", &coerce_str, "(O)", other); + if (r == NULL) + return -1; + if (r == Py_NotImplemented) { + Py_DECREF(r); + return 1; + } + if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) { + PyErr_SetString(PyExc_TypeError, + "__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); + return 0; + } + if (other->ob_type->tp_as_number != NULL && + other->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) { + PyObject *r; + r = call_maybe( + other, "__coerce__", &coerce_str, "(O)", self); + if (r == NULL) + return -1; + if (r == Py_NotImplemented) { + Py_DECREF(r); + return 1; + } + if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) { + PyErr_SetString(PyExc_TypeError, + "__coerce__ didn't return a 2-tuple"); + Py_DECREF(r); + return -1; + } + *a = PyTuple_GET_ITEM(r, 1); + Py_INCREF(*a); + *b = PyTuple_GET_ITEM(r, 0); + Py_INCREF(*b); + Py_DECREF(r); + return 0; + } + return 1; +} + SLOT0(slot_nb_int, "__int__") SLOT0(slot_nb_long, "__long__") SLOT0(slot_nb_float, "__float__") @@ -3336,7 +3427,7 @@ override_slots(PyTypeObject *type, PyObject *dict) NBSLOT("__and__", nb_and, slot_nb_and); NBSLOT("__xor__", nb_xor, slot_nb_xor); NBSLOT("__or__", nb_or, slot_nb_or); - /* Not coerce() */ + NBSLOT("__coerce__", nb_coerce, slot_nb_coerce); NBSLOT("__int__", nb_int, slot_nb_int); NBSLOT("__long__", nb_long, slot_nb_long); NBSLOT("__float__", nb_float, slot_nb_float); |