Issue #1717, stage 2: remove uses of tp_compare in Modules and most
Objects.
This commit is contained in:
parent
776e7014e9
commit
211c625829
|
@ -3885,7 +3885,7 @@ order (MRO) for bases """
|
|||
# Testing method-wrapper objects...
|
||||
# <type 'method-wrapper'> did not support any reflection before 2.5
|
||||
|
||||
return # XXX should methods really support __eq__?
|
||||
# XXX should methods really support __eq__?
|
||||
|
||||
l = []
|
||||
self.assertEqual(l.__add__, l.__add__)
|
||||
|
|
|
@ -224,10 +224,41 @@ class FunctionDocstringTest(FuncAttrsTest):
|
|||
del self.b.__doc__
|
||||
self.assertEqual(self.b.__doc__, None)
|
||||
|
||||
def cell(value):
|
||||
"""Create a cell containing the given value."""
|
||||
def f():
|
||||
print(a)
|
||||
a = value
|
||||
return f.__closure__[0]
|
||||
|
||||
def empty_cell(empty=True):
|
||||
"""Create an empty cell."""
|
||||
def f():
|
||||
print(a)
|
||||
# the intent of the following line is simply "if False:"; it's
|
||||
# spelt this way to avoid the danger that a future optimization
|
||||
# might simply remove an "if False:" code block.
|
||||
if not empty:
|
||||
a = 1729
|
||||
return f.__closure__[0]
|
||||
|
||||
class CellTest(unittest.TestCase):
|
||||
def test_comparison(self):
|
||||
# These tests are here simply to exercise the comparison code;
|
||||
# their presence should not be interpreted as providing any
|
||||
# guarantees about the semantics (or even existence) of cell
|
||||
# comparisons in future versions of CPython.
|
||||
self.assert_(cell(2) < cell(3))
|
||||
self.assert_(empty_cell() < cell('saturday'))
|
||||
self.assert_(empty_cell() == empty_cell())
|
||||
self.assert_(cell(-36) == cell(-36.0))
|
||||
self.assert_(cell(True) > empty_cell())
|
||||
|
||||
|
||||
def test_main():
|
||||
support.run_unittest(FunctionPropertiesTest, ImplicitReferencesTest,
|
||||
ArbitraryFunctionAttrTest, FunctionDictsTest,
|
||||
FunctionDocstringTest)
|
||||
FunctionDocstringTest, CellTest)
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_main()
|
||||
|
|
|
@ -2,6 +2,7 @@ import parser
|
|||
import os
|
||||
import unittest
|
||||
import sys
|
||||
import operator
|
||||
from test import support
|
||||
|
||||
#
|
||||
|
@ -496,12 +497,81 @@ class ParserStackLimitTestCase(unittest.TestCase):
|
|||
file=sys.stderr)
|
||||
self.assertRaises(MemoryError, parser.expr, e)
|
||||
|
||||
class STObjectTestCase(unittest.TestCase):
|
||||
"""Test operations on ST objects themselves"""
|
||||
|
||||
def test_comparisons(self):
|
||||
# ST objects should support order and equality comparisons
|
||||
st1 = parser.expr('2 + 3')
|
||||
st2 = parser.suite('x = 2; y = x + 3')
|
||||
st3 = parser.expr('list(x**3 for x in range(20))')
|
||||
st1_copy = parser.expr('2 + 3')
|
||||
st2_copy = parser.suite('x = 2; y = x + 3')
|
||||
st3_copy = parser.expr('list(x**3 for x in range(20))')
|
||||
|
||||
# exercise fast path for object identity
|
||||
self.assertEquals(st1 == st1, True)
|
||||
self.assertEquals(st2 == st2, True)
|
||||
self.assertEquals(st3 == st3, True)
|
||||
# slow path equality
|
||||
self.assertEqual(st1, st1_copy)
|
||||
self.assertEqual(st2, st2_copy)
|
||||
self.assertEqual(st3, st3_copy)
|
||||
self.assertEquals(st1 == st2, False)
|
||||
self.assertEquals(st1 == st3, False)
|
||||
self.assertEquals(st2 == st3, False)
|
||||
self.assertEquals(st1 != st1, False)
|
||||
self.assertEquals(st2 != st2, False)
|
||||
self.assertEquals(st3 != st3, False)
|
||||
self.assertEquals(st1 != st1_copy, False)
|
||||
self.assertEquals(st2 != st2_copy, False)
|
||||
self.assertEquals(st3 != st3_copy, False)
|
||||
self.assertEquals(st2 != st1, True)
|
||||
self.assertEquals(st1 != st3, True)
|
||||
self.assertEquals(st3 != st2, True)
|
||||
# we don't particularly care what the ordering is; just that
|
||||
# it's usable and self-consistent
|
||||
self.assertEquals(st1 < st2, not (st2 <= st1))
|
||||
self.assertEquals(st1 < st3, not (st3 <= st1))
|
||||
self.assertEquals(st2 < st3, not (st3 <= st2))
|
||||
self.assertEquals(st1 < st2, st2 > st1)
|
||||
self.assertEquals(st1 < st3, st3 > st1)
|
||||
self.assertEquals(st2 < st3, st3 > st2)
|
||||
self.assertEquals(st1 <= st2, st2 >= st1)
|
||||
self.assertEquals(st3 <= st1, st1 >= st3)
|
||||
self.assertEquals(st2 <= st3, st3 >= st2)
|
||||
# transitivity
|
||||
bottom = min(st1, st2, st3)
|
||||
top = max(st1, st2, st3)
|
||||
mid = sorted([st1, st2, st3])[1]
|
||||
self.assert_(bottom < mid)
|
||||
self.assert_(bottom < top)
|
||||
self.assert_(mid < top)
|
||||
self.assert_(bottom <= mid)
|
||||
self.assert_(bottom <= top)
|
||||
self.assert_(mid <= top)
|
||||
self.assert_(bottom <= bottom)
|
||||
self.assert_(mid <= mid)
|
||||
self.assert_(top <= top)
|
||||
# interaction with other types
|
||||
self.assertEquals(st1 == 1588.602459, False)
|
||||
self.assertEquals('spanish armada' != st2, True)
|
||||
self.assertRaises(TypeError, operator.ge, st3, None)
|
||||
self.assertRaises(TypeError, operator.le, False, st1)
|
||||
self.assertRaises(TypeError, operator.lt, st1, 1815)
|
||||
self.assertRaises(TypeError, operator.gt, b'waterloo', st2)
|
||||
|
||||
|
||||
# XXX tests for pickling and unpickling of ST objects should go here
|
||||
|
||||
|
||||
def test_main():
|
||||
support.run_unittest(
|
||||
RoundtripLegalSyntaxTestCase,
|
||||
IllegalSyntaxTestCase,
|
||||
CompileTestCase,
|
||||
ParserStackLimitTestCase,
|
||||
STObjectTestCase,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -443,7 +443,7 @@ static PyTypeObject Dialect_Type = {
|
|||
(printfunc)0, /* tp_print */
|
||||
(getattrfunc)0, /* tp_getattr */
|
||||
(setattrfunc)0, /* tp_setattr */
|
||||
(cmpfunc)0, /* tp_compare */
|
||||
0, /* tp_compare */
|
||||
(reprfunc)0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
|
@ -864,7 +864,7 @@ static PyTypeObject Reader_Type = {
|
|||
(printfunc)0, /*tp_print*/
|
||||
(getattrfunc)0, /*tp_getattr*/
|
||||
(setattrfunc)0, /*tp_setattr*/
|
||||
(cmpfunc)0, /*tp_compare*/
|
||||
0, /*tp_compare*/
|
||||
(reprfunc)0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
|
@ -1286,7 +1286,7 @@ static PyTypeObject Writer_Type = {
|
|||
(printfunc)0, /*tp_print*/
|
||||
(getattrfunc)0, /*tp_getattr*/
|
||||
(setattrfunc)0, /*tp_setattr*/
|
||||
(cmpfunc)0, /*tp_compare*/
|
||||
0, /*tp_compare*/
|
||||
(reprfunc)0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
|
|
|
@ -761,7 +761,7 @@ element_find(ElementObject* self, PyObject* args)
|
|||
for (i = 0; i < self->extra->length; i++) {
|
||||
PyObject* item = self->extra->children[i];
|
||||
if (Element_CheckExact(item) &&
|
||||
PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) {
|
||||
PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) {
|
||||
Py_INCREF(item);
|
||||
return item;
|
||||
}
|
||||
|
@ -792,7 +792,8 @@ element_findtext(ElementObject* self, PyObject* args)
|
|||
|
||||
for (i = 0; i < self->extra->length; i++) {
|
||||
ElementObject* item = (ElementObject*) self->extra->children[i];
|
||||
if (Element_CheckExact(item) && !PyObject_Compare(item->tag, tag)) {
|
||||
if (Element_CheckExact(item) && (PyObject_RichCompareBool(item->tag, tag, Py_EQ) == 1)) {
|
||||
|
||||
PyObject* text = element_get_text(item);
|
||||
if (text == Py_None)
|
||||
return PyBytes_FromString("");
|
||||
|
@ -830,7 +831,7 @@ element_findall(ElementObject* self, PyObject* args)
|
|||
for (i = 0; i < self->extra->length; i++) {
|
||||
PyObject* item = self->extra->children[i];
|
||||
if (Element_CheckExact(item) &&
|
||||
PyObject_Compare(((ElementObject*)item)->tag, tag) == 0) {
|
||||
PyObject_RichCompareBool(((ElementObject*)item)->tag, tag, Py_EQ) == 1) {
|
||||
if (PyList_Append(out, item) < 0) {
|
||||
Py_DECREF(out);
|
||||
return NULL;
|
||||
|
@ -1102,7 +1103,7 @@ element_remove(ElementObject* self, PyObject* args)
|
|||
for (i = 0; i < self->extra->length; i++) {
|
||||
if (self->extra->children[i] == element)
|
||||
break;
|
||||
if (PyObject_Compare(self->extra->children[i], element) == 0)
|
||||
if (PyObject_RichCompareBool(self->extra->children[i], element, Py_EQ) == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -272,7 +272,9 @@ PyLocale_strcoll(PyObject* self, PyObject* args)
|
|||
|
||||
#ifdef HAVE_WCSXFRM
|
||||
PyDoc_STRVAR(strxfrm__doc__,
|
||||
"string -> string. Returns a string that behaves for cmp locale-aware.");
|
||||
"strxfrm(string) -> string.\n\
|
||||
\n\
|
||||
Return a string that can be used as a key for locale-aware comparisons.");
|
||||
|
||||
static PyObject*
|
||||
PyLocale_strxfrm(PyObject* self, PyObject* args)
|
||||
|
|
|
@ -715,7 +715,7 @@ whichmodule(PyObject *global, PyObject *global_name)
|
|||
i = 0;
|
||||
module_name = NULL;
|
||||
while ((j = PyDict_Next(modules_dict, &i, &module_name, &module))) {
|
||||
if (PyObject_Compare(module_name, main_str) == 0)
|
||||
if (PyObject_RichCompareBool(module_name, main_str, Py_EQ) == 1)
|
||||
continue;
|
||||
|
||||
obj = PyObject_GetAttr(module, global_name);
|
||||
|
|
|
@ -788,15 +788,59 @@ PyTclObject_repr(PyTclObject *self)
|
|||
self->value->typePtr->name, self->value);
|
||||
}
|
||||
|
||||
static int
|
||||
PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
|
||||
#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
|
||||
|
||||
static PyObject *
|
||||
PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
|
||||
{
|
||||
int res;
|
||||
res = strcmp(Tcl_GetString(self->value),
|
||||
Tcl_GetString(other->value));
|
||||
if (res < 0) return -1;
|
||||
if (res > 0) return 1;
|
||||
return 0;
|
||||
int result;
|
||||
PyObject *v;
|
||||
|
||||
/* neither argument should be NULL, unless something's gone wrong */
|
||||
if (self == NULL || other == NULL) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* both arguments should be instances of PyTclObject */
|
||||
if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
|
||||
v = Py_NotImplemented;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (self == other)
|
||||
/* fast path when self and other are identical */
|
||||
result = 0;
|
||||
else
|
||||
result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
|
||||
Tcl_GetString(((PyTclObject *)other)->value));
|
||||
/* Convert return value to a Boolean */
|
||||
switch (op) {
|
||||
case Py_EQ:
|
||||
v = TEST_COND(result == 0);
|
||||
break;
|
||||
case Py_NE:
|
||||
v = TEST_COND(result != 0);
|
||||
break;
|
||||
case Py_LE:
|
||||
v = TEST_COND(result <= 0);
|
||||
break;
|
||||
case Py_GE:
|
||||
v = TEST_COND(result >= 0);
|
||||
break;
|
||||
case Py_LT:
|
||||
v = TEST_COND(result < 0);
|
||||
break;
|
||||
case Py_GT:
|
||||
v = TEST_COND(result > 0);
|
||||
break;
|
||||
default:
|
||||
PyErr_BadArgument();
|
||||
return NULL;
|
||||
}
|
||||
finished:
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
|
||||
|
@ -818,45 +862,45 @@ static PyGetSetDef PyTclObject_getsetlist[] = {
|
|||
static PyTypeObject PyTclObject_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"_tkinter.Tcl_Obj", /*tp_name*/
|
||||
sizeof(PyTclObject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
sizeof(PyTclObject), /*tp_basicsize*/
|
||||
0, /*tp_itemsize*/
|
||||
/* methods */
|
||||
(destructor)PyTclObject_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
(cmpfunc)PyTclObject_cmp, /*tp_compare*/
|
||||
(destructor)PyTclObject_dealloc,/*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_compare*/
|
||||
(reprfunc)PyTclObject_repr, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
(reprfunc)PyTclObject_str, /*tp_str*/
|
||||
PyObject_GenericGetAttr,/*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
0, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
0, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
PyTclObject_getsetlist, /*tp_getset*/
|
||||
0, /*tp_base*/
|
||||
0, /*tp_dict*/
|
||||
0, /*tp_descr_get*/
|
||||
0, /*tp_descr_set*/
|
||||
0, /*tp_dictoffset*/
|
||||
0, /*tp_init*/
|
||||
0, /*tp_alloc*/
|
||||
0, /*tp_new*/
|
||||
0, /*tp_free*/
|
||||
0, /*tp_is_gc*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
(reprfunc)PyTclObject_str, /*tp_str*/
|
||||
PyObject_GenericGetAttr, /*tp_getattro*/
|
||||
0, /*tp_setattro*/
|
||||
0, /*tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||
0, /*tp_doc*/
|
||||
0, /*tp_traverse*/
|
||||
0, /*tp_clear*/
|
||||
PyTclObject_richcompare, /*tp_richcompare*/
|
||||
0, /*tp_weaklistoffset*/
|
||||
0, /*tp_iter*/
|
||||
0, /*tp_iternext*/
|
||||
0, /*tp_methods*/
|
||||
0, /*tp_members*/
|
||||
PyTclObject_getsetlist, /*tp_getset*/
|
||||
0, /*tp_base*/
|
||||
0, /*tp_dict*/
|
||||
0, /*tp_descr_get*/
|
||||
0, /*tp_descr_set*/
|
||||
0, /*tp_dictoffset*/
|
||||
0, /*tp_init*/
|
||||
0, /*tp_alloc*/
|
||||
0, /*tp_new*/
|
||||
0, /*tp_free*/
|
||||
0, /*tp_is_gc*/
|
||||
};
|
||||
|
||||
static Tcl_Obj*
|
||||
|
|
|
@ -169,7 +169,7 @@ typedef struct {
|
|||
|
||||
|
||||
static void parser_free(PyST_Object *st);
|
||||
static int parser_compare(PyST_Object *left, PyST_Object *right);
|
||||
static PyObject* parser_richcompare(PyObject *left, PyObject *right, int op);
|
||||
static PyObject* parser_compilest(PyST_Object *, PyObject *, PyObject *);
|
||||
static PyObject* parser_isexpr(PyST_Object *, PyObject *, PyObject *);
|
||||
static PyObject* parser_issuite(PyST_Object *, PyObject *, PyObject *);
|
||||
|
@ -203,7 +203,7 @@ PyTypeObject PyST_Type = {
|
|||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
(cmpfunc)parser_compare, /* tp_compare */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
|
@ -223,7 +223,7 @@ PyTypeObject PyST_Type = {
|
|||
"Intermediate representation of a Python parse tree.",
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
parser_richcompare, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
|
@ -231,6 +231,9 @@ PyTypeObject PyST_Type = {
|
|||
}; /* PyST_Type */
|
||||
|
||||
|
||||
/* PyST_Type isn't subclassable, so just check ob_type */
|
||||
#define PyST_Object_Check(v) ((v)->ob_type == &PyST_Type)
|
||||
|
||||
static int
|
||||
parser_compare_nodes(node *left, node *right)
|
||||
{
|
||||
|
@ -260,27 +263,70 @@ parser_compare_nodes(node *left, node *right)
|
|||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* int parser_compare(PyST_Object* left, PyST_Object* right)
|
||||
/* parser_richcompare(PyObject* left, PyObject* right, int op)
|
||||
*
|
||||
* Comparison function used by the Python operators ==, !=, <, >, <=, >=
|
||||
* This really just wraps a call to parser_compare_nodes() with some easy
|
||||
* checks and protection code.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
parser_compare(PyST_Object *left, PyST_Object *right)
|
||||
|
||||
#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
|
||||
|
||||
static PyObject *
|
||||
parser_richcompare(PyObject *left, PyObject *right, int op)
|
||||
{
|
||||
int result;
|
||||
PyObject *v;
|
||||
|
||||
/* neither argument should be NULL, unless something's gone wrong */
|
||||
if (left == NULL || right == NULL) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* both arguments should be instances of PyST_Object */
|
||||
if (!PyST_Object_Check(left) || !PyST_Object_Check(right)) {
|
||||
v = Py_NotImplemented;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (left == right)
|
||||
return (0);
|
||||
/* if arguments are identical, they're equal */
|
||||
result = 0;
|
||||
else
|
||||
result = parser_compare_nodes(((PyST_Object *)left)->st_node,
|
||||
((PyST_Object *)right)->st_node);
|
||||
|
||||
if ((left == 0) || (right == 0))
|
||||
return (-1);
|
||||
|
||||
return (parser_compare_nodes(left->st_node, right->st_node));
|
||||
/* Convert return value to a Boolean */
|
||||
switch (op) {
|
||||
case Py_EQ:
|
||||
v = TEST_COND(result == 0);
|
||||
break;
|
||||
case Py_NE:
|
||||
v = TEST_COND(result != 0);
|
||||
break;
|
||||
case Py_LE:
|
||||
v = TEST_COND(result <= 0);
|
||||
break;
|
||||
case Py_GE:
|
||||
v = TEST_COND(result >= 0);
|
||||
break;
|
||||
case Py_LT:
|
||||
v = TEST_COND(result < 0);
|
||||
break;
|
||||
case Py_GT:
|
||||
v = TEST_COND(result > 0);
|
||||
break;
|
||||
default:
|
||||
PyErr_BadArgument();
|
||||
return NULL;
|
||||
}
|
||||
finished:
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/* parser_newstobject(node* st)
|
||||
*
|
||||
* Allocates a new Python object representing an ST. This is simply the
|
||||
|
|
|
@ -1622,7 +1622,7 @@ static PyTypeObject Xmlparsetype = {
|
|||
(printfunc)0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
(setattrfunc)xmlparse_setattr, /*tp_setattr*/
|
||||
(cmpfunc)0, /*tp_compare*/
|
||||
0, /*tp_compare*/
|
||||
(reprfunc)0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
|
|
|
@ -51,16 +51,56 @@ cell_dealloc(PyCellObject *op)
|
|||
PyObject_GC_Del(op);
|
||||
}
|
||||
|
||||
static int
|
||||
cell_compare(PyCellObject *a, PyCellObject *b)
|
||||
#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
|
||||
|
||||
static PyObject *
|
||||
cell_richcompare(PyObject *a, PyObject *b, int op)
|
||||
{
|
||||
if (a->ob_ref == NULL) {
|
||||
if (b->ob_ref == NULL)
|
||||
return 0;
|
||||
return -1;
|
||||
} else if (b->ob_ref == NULL)
|
||||
return 1;
|
||||
return PyObject_Compare(a->ob_ref, b->ob_ref);
|
||||
int result;
|
||||
PyObject *v;
|
||||
|
||||
/* neither argument should be NULL, unless something's gone wrong */
|
||||
assert(a != NULL && b != NULL);
|
||||
|
||||
/* both arguments should be instances of PyCellObject */
|
||||
if (!PyCell_Check(a) || !PyCell_Check(b)) {
|
||||
v = Py_NotImplemented;
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* compare cells by contents; empty cells come before anything else */
|
||||
a = ((PyCellObject *)a)->ob_ref;
|
||||
b = ((PyCellObject *)b)->ob_ref;
|
||||
if (a != NULL && b != NULL)
|
||||
return PyObject_RichCompare(a, b, op);
|
||||
|
||||
result = (b == NULL) - (a == NULL);
|
||||
switch (op) {
|
||||
case Py_EQ:
|
||||
v = TEST_COND(result == 0);
|
||||
break;
|
||||
case Py_NE:
|
||||
v = TEST_COND(result != 0);
|
||||
break;
|
||||
case Py_LE:
|
||||
v = TEST_COND(result <= 0);
|
||||
break;
|
||||
case Py_GE:
|
||||
v = TEST_COND(result >= 0);
|
||||
break;
|
||||
case Py_LT:
|
||||
v = TEST_COND(result < 0);
|
||||
break;
|
||||
case Py_GT:
|
||||
v = TEST_COND(result > 0);
|
||||
break;
|
||||
default:
|
||||
PyErr_BadArgument();
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -114,7 +154,7 @@ PyTypeObject PyCell_Type = {
|
|||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
(cmpfunc)cell_compare, /* tp_compare */
|
||||
0, /* tp_compare */
|
||||
(reprfunc)cell_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
|
@ -129,7 +169,7 @@ PyTypeObject PyCell_Type = {
|
|||
0, /* tp_doc */
|
||||
(traverseproc)cell_traverse, /* tp_traverse */
|
||||
(inquiry)cell_clear, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
cell_richcompare, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
|
|
|
@ -774,12 +774,6 @@ proxy_traverse(PyObject *self, visitproc visit, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
proxy_compare(proxyobject *v, PyObject *w)
|
||||
{
|
||||
return PyObject_Compare(v->dict, w);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
proxy_richcompare(proxyobject *v, PyObject *w, int op)
|
||||
{
|
||||
|
@ -796,7 +790,7 @@ PyTypeObject PyDictProxy_Type = {
|
|||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
(cmpfunc)proxy_compare, /* tp_compare */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
&proxy_as_sequence, /* tp_as_sequence */
|
||||
|
@ -844,12 +838,17 @@ PyDictProxy_New(PyObject *dict)
|
|||
/* This has no reason to be in this file except that adding new files is a
|
||||
bit of a pain */
|
||||
|
||||
/* forward */
|
||||
static PyTypeObject wrappertype;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyWrapperDescrObject *descr;
|
||||
PyObject *self;
|
||||
} wrapperobject;
|
||||
|
||||
#define Wrapper_Check(v) (Py_TYPE(v) == &wrappertype)
|
||||
|
||||
static void
|
||||
wrapper_dealloc(wrapperobject *wp)
|
||||
{
|
||||
|
@ -861,13 +860,60 @@ wrapper_dealloc(wrapperobject *wp)
|
|||
Py_TRASHCAN_SAFE_END(wp)
|
||||
}
|
||||
|
||||
static int
|
||||
wrapper_compare(wrapperobject *a, wrapperobject *b)
|
||||
#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
|
||||
|
||||
static PyObject *
|
||||
wrapper_richcompare(PyObject *a, PyObject *b, int op)
|
||||
{
|
||||
if (a->descr == b->descr)
|
||||
return PyObject_Compare(a->self, b->self);
|
||||
else
|
||||
return (a->descr < b->descr) ? -1 : 1;
|
||||
int result;
|
||||
PyObject *v;
|
||||
PyWrapperDescrObject *a_descr, *b_descr;
|
||||
|
||||
assert(a != NULL && b != NULL);
|
||||
|
||||
/* both arguments should be wrapperobjects */
|
||||
if (!Wrapper_Check(a) || !Wrapper_Check(b)) {
|
||||
v = Py_NotImplemented;
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* compare by descriptor address; if the descriptors are the same,
|
||||
compare by the objects they're bound to */
|
||||
a_descr = ((wrapperobject *)a)->descr;
|
||||
b_descr = ((wrapperobject *)b)->descr;
|
||||
if (a_descr == b_descr) {
|
||||
a = ((wrapperobject *)a)->self;
|
||||
b = ((wrapperobject *)b)->self;
|
||||
return PyObject_RichCompare(a, b, op);
|
||||
}
|
||||
|
||||
result = a_descr - b_descr;
|
||||
switch (op) {
|
||||
case Py_EQ:
|
||||
v = TEST_COND(result == 0);
|
||||
break;
|
||||
case Py_NE:
|
||||
v = TEST_COND(result != 0);
|
||||
break;
|
||||
case Py_LE:
|
||||
v = TEST_COND(result <= 0);
|
||||
break;
|
||||
case Py_GE:
|
||||
v = TEST_COND(result >= 0);
|
||||
break;
|
||||
case Py_LT:
|
||||
v = TEST_COND(result < 0);
|
||||
break;
|
||||
case Py_GT:
|
||||
v = TEST_COND(result > 0);
|
||||
break;
|
||||
default:
|
||||
PyErr_BadArgument();
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
static long
|
||||
|
@ -977,7 +1023,7 @@ static PyTypeObject wrappertype = {
|
|||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
(cmpfunc)wrapper_compare, /* tp_compare */
|
||||
0, /* tp_compare */
|
||||
(reprfunc)wrapper_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
|
@ -992,7 +1038,7 @@ static PyTypeObject wrappertype = {
|
|||
0, /* tp_doc */
|
||||
wrapper_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
wrapper_richcompare, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
|
|
|
@ -123,7 +123,7 @@ range_length_obj(rangeobject *r)
|
|||
Algorithm is equal to that of get_len_of_range(), but it operates
|
||||
on PyObjects (which are assumed to be PyLong or PyInt objects).
|
||||
---------------------------------------------------------------*/
|
||||
int cmp_result, cmp_call;
|
||||
int cmp_result;
|
||||
PyObject *lo, *hi;
|
||||
PyObject *step = NULL;
|
||||
PyObject *diff = NULL;
|
||||
|
@ -134,13 +134,12 @@ range_length_obj(rangeobject *r)
|
|||
PyObject *zero = PyLong_FromLong(0);
|
||||
if (zero == NULL)
|
||||
return NULL;
|
||||
cmp_call = PyObject_Cmp(r->step, zero, &cmp_result);
|
||||
cmp_result = PyObject_RichCompareBool(r->step, zero, Py_GT);
|
||||
Py_DECREF(zero);
|
||||
if (cmp_call == -1)
|
||||
if (cmp_result == -1)
|
||||
return NULL;
|
||||
|
||||
assert(cmp_result != 0);
|
||||
if (cmp_result > 0) {
|
||||
if (cmp_result == 1) {
|
||||
lo = r->start;
|
||||
hi = r->stop;
|
||||
step = r->step;
|
||||
|
@ -154,7 +153,7 @@ range_length_obj(rangeobject *r)
|
|||
}
|
||||
|
||||
/* if (lo >= hi), return length of 0. */
|
||||
if (PyObject_Compare(lo, hi) >= 0) {
|
||||
if (PyObject_RichCompareBool(lo, hi, Py_GE) == 1) {
|
||||
Py_XDECREF(step);
|
||||
return PyLong_FromLong(0);
|
||||
}
|
||||
|
|
|
@ -1824,13 +1824,6 @@ set_richcompare(PySetObject *v, PyObject *w, int op)
|
|||
return Py_NotImplemented;
|
||||
}
|
||||
|
||||
static int
|
||||
set_nocmp(PyObject *self, PyObject *other)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "cannot compare sets using cmp()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
set_add(PySetObject *so, PyObject *key)
|
||||
{
|
||||
|
@ -2111,7 +2104,7 @@ PyTypeObject PySet_Type = {
|
|||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
set_nocmp, /* tp_compare */
|
||||
0, /* tp_compare */
|
||||
(reprfunc)set_repr, /* tp_repr */
|
||||
&set_as_number, /* tp_as_number */
|
||||
&set_as_sequence, /* tp_as_sequence */
|
||||
|
@ -2208,7 +2201,7 @@ PyTypeObject PyFrozenSet_Type = {
|
|||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
set_nocmp, /* tp_compare */
|
||||
0, /* tp_compare */
|
||||
(reprfunc)set_repr, /* tp_repr */
|
||||
&frozenset_as_number, /* tp_as_number */
|
||||
&set_as_sequence, /* tp_as_sequence */
|
||||
|
|
|
@ -326,7 +326,7 @@ PyDoc_STRVAR(PyHKEY_doc,
|
|||
"Operations:\n"
|
||||
"__bool__ - Handles with an open object return true, otherwise false.\n"
|
||||
"__int__ - Converting a handle to an integer returns the Win32 handle.\n"
|
||||
"__cmp__ - Handle objects are compared using the handle value.");
|
||||
"rich comparison - Handle objects are compared using the handle value.");
|
||||
|
||||
|
||||
PyDoc_STRVAR(PyHKEY_Close_doc,
|
||||
|
@ -485,7 +485,7 @@ PyTypeObject PyHKEY_Type =
|
|||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
PyHKEY_compareFunc, /* tp_compare */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
&PyHKEY_NumberMethods, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
|
|
Loading…
Reference in New Issue