summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-09-27 20:30:07 (GMT)
committerGuido van Rossum <guido@python.org>2001-09-27 20:30:07 (GMT)
commit2ed6bf87c9ce5d2e8a0eb33f7aa6503196205a0c (patch)
treecb597e3c84bf6d845c849e5d715a011922337704
parent33f4d6d1db5dd915cce811bd6f7a963d4dbe8db2 (diff)
downloadcpython-2ed6bf87c9ce5d2e8a0eb33f7aa6503196205a0c.zip
cpython-2ed6bf87c9ce5d2e8a0eb33f7aa6503196205a0c.tar.gz
cpython-2ed6bf87c9ce5d2e8a0eb33f7aa6503196205a0c.tar.bz2
Merge branch changes (coercion, rich comparisons) into trunk.
-rw-r--r--Objects/complexobject.c6
-rw-r--r--Objects/object.c8
-rw-r--r--Objects/stringobject.c6
-rw-r--r--Objects/typeobject.c97
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);