]> granicus.if.org Git - python/commitdiff
Merge branch changes (coercion, rich comparisons) into trunk.
authorGuido van Rossum <guido@python.org>
Thu, 27 Sep 2001 20:30:07 +0000 (20:30 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 27 Sep 2001 20:30:07 +0000 (20:30 +0000)
Objects/complexobject.c
Objects/object.c
Objects/stringobject.c
Objects/typeobject.c

index 32f2b2459fe33e845f164682fdd681632a1e9d33..ee0ede4fc5bd993315e57846bb719db4494aa83c 100644 (file)
@@ -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);
index 6d7a5e9aeb02e205eb69fb621ae2aa4b0a46f673..88fa34059c82d01ee716a8ddff2c2c308fc6ceaa 100644 (file)
@@ -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)
index e29be5a07007bfc696b5783f0b57180d845def25..cfa5f536345886d37e0e681bf57df0415520fda2 100644 (file)
@@ -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;
        }
index 0e6099c5b7338b20a90da21a74f85f8b76c3c72b..ac201d58909260911c52b41acc9fbc4d4b7c0569 100644 (file)
@@ -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);