Skip to content

Commit

Permalink
Issue python#1717, stage 2: remove uses of tp_compare in Modules and …
Browse files Browse the repository at this point in the history
…most

Objects.
  • Loading branch information
mdickinson committed Feb 1, 2009
1 parent 776e701 commit 211c625
Show file tree
Hide file tree
Showing 15 changed files with 385 additions and 113 deletions.
2 changes: 1 addition & 1 deletion Lib/test/test_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3885,7 +3885,7 @@ def test_method_wrapper(self):
# 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__)
Expand Down
33 changes: 32 additions & 1 deletion Lib/test/test_funcattrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,41 @@ def test_delete_docstring(self):
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()
70 changes: 70 additions & 0 deletions Lib/test/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import unittest
import sys
import operator
from test import support

#
Expand Down Expand Up @@ -496,12 +497,81 @@ def test_trigger_memory_error(self):
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,
)


Expand Down
6 changes: 3 additions & 3 deletions Modules/_csv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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*/
Expand Down Expand Up @@ -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*/
Expand Down
9 changes: 5 additions & 4 deletions Modules/_elementtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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("");
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 3 additions & 1 deletion Modules/_localemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion Modules/_pickle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
134 changes: 89 additions & 45 deletions Modules/_tkinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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*
Expand Down
Loading

0 comments on commit 211c625

Please sign in to comment.