/* Return: NULL for exception; some object not equal to NotImplemented if it is implemented (this latter object may not be a Boolean). */ PyObject * PyObject_RichCompare(PyObject *v, PyObject *w, int op) { PyObject *res; assert(Py_LT <= op && op <= Py_GE); if (Py_EnterRecursiveCall(" in cmp")) return NULL; /* If the types are equal, and not old-style instances, try to get out cheap (don't bother with coercions etc.). */ if (v->ob_type == w->ob_type && !PyInstance_Check(v)) { cmpfunc fcmp; richcmpfunc frich = RICHCOMPARE(v->ob_type); /* If the type has richcmp, try it first. try_rich_compare tries it two-sided, which is not needed since we've a single type only. */ if (frich != NULL) { res = (*frich)(v, w, op); if (res != Py_NotImplemented) goto Done; Py_DECREF(res); } /* No richcmp, or this particular richmp not implemented. Try 3-way cmp. */ fcmp = v->ob_type->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(v, w); c = adjust_tp_compare(c); if (c == -2) { res = NULL; goto Done; } res = convert_3way_to_object(op, c); goto Done; } } /* Fast path not taken, or couldn't deliver a useful result. */ res = do_richcmp(v, w, op); Done: Py_LeaveRecursiveCall(); return res; }
/* Return: NULL for exception; some object not equal to NotImplemented if it is implemented (this latter object may not be a Boolean). */ PyObject * PyObject_RichCompare(PyObject *v, PyObject *w, int op) { PyObject *res; assert(Py_LT <= op && op <= Py_GE); compare_nesting++; if (compare_nesting > NESTING_LIMIT && (v->ob_type->tp_as_mapping || (v->ob_type->tp_as_sequence && !PyString_Check(v) && !PyTuple_Check(v)))) { /* try to detect circular data structures */ PyObject *token = check_recursion(v, w, op); if (token == NULL) { res = NULL; goto Done; } else if (token == Py_None) { /* already comparing these objects with this operator. assume they're equal until shown otherwise */ if (op == Py_EQ) res = Py_True; else if (op == Py_NE) res = Py_False; else { PyErr_SetString(PyExc_ValueError, "can't order recursive values"); res = NULL; } Py_XINCREF(res); } else { res = do_richcmp(v, w, op); delete_token(token); } goto Done; } /* No nesting extremism. If the types are equal, and not old-style instances, try to get out cheap (don't bother with coercions etc.). */ if (v->ob_type == w->ob_type && !PyInstance_Check(v)) { cmpfunc fcmp; richcmpfunc frich = RICHCOMPARE(v->ob_type); /* If the type has richcmp, try it first. try_rich_compare tries it two-sided, which is not needed since we've a single type only. */ if (frich != NULL) { res = (*frich)(v, w, op); if (res != Py_NotImplemented) goto Done; Py_DECREF(res); } /* No richcmp, or this particular richmp not implemented. Try 3-way cmp. */ fcmp = v->ob_type->tp_compare; if (fcmp != NULL) { int c = (*fcmp)(v, w); if (c < 0 && PyErr_Occurred()) { res = NULL; goto Done; } res = convert_3way_to_object(op, c); goto Done; } } /* Fast path not taken, or couldn't deliver a useful result. */ res = do_richcmp(v, w, op); Done: compare_nesting--; return res; }