From: Steven Bethard Date: Tue, 18 Mar 2008 17:26:10 +0000 (+0000) Subject: Add py3k warnings for object, type, cell and dict comparisons. This should resolve... X-Git-Tag: v2.6a2~263 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ae42f33cdfb68be2fc71be0fb67ec025f90160e8;p=python Add py3k warnings for object, type, cell and dict comparisons. This should resolve issue2342 and partly resolve issue2373. --- diff --git a/Lib/test/test_py3kwarn.py b/Lib/test/test_py3kwarn.py new file mode 100644 index 0000000000..61de7a22bd --- /dev/null +++ b/Lib/test/test_py3kwarn.py @@ -0,0 +1,60 @@ +import unittest +from test.test_support import catch_warning, TestSkipped, run_unittest +import warnings + +# TODO: This is a hack to raise TestSkipped if -3 is not enabled. Instead +# of relying on callable to have a warning, we should expose the -3 flag +# to Python code somehow +with catch_warning() as w: + callable(int) + if w.message is None: + raise TestSkipped('%s must be run with the -3 flag' % __name__) + +class TestPy3KWarnings(unittest.TestCase): + + def test_type_inequality_comparisons(self): + expected = 'type inequality comparisons not supported in 3.x.' + with catch_warning() as w: + self.assertWarning(int < str, w, expected) + with catch_warning() as w: + self.assertWarning(type < object, w, expected) + + def test_object_inequality_comparisons(self): + expected = 'comparing unequal types not supported in 3.x.' + with catch_warning() as w: + self.assertWarning(str < [], w, expected) + with catch_warning() as w: + self.assertWarning(object() < (1, 2), w, expected) + + def test_dict_inequality_comparisons(self): + expected = 'dict inequality comparisons not supported in 3.x.' + with catch_warning() as w: + self.assertWarning({} < {2:3}, w, expected) + with catch_warning() as w: + self.assertWarning({} <= {}, w, expected) + with catch_warning() as w: + self.assertWarning({} > {2:3}, w, expected) + with catch_warning() as w: + self.assertWarning({2:3} >= {}, w, expected) + + def test_cell_inequality_comparisons(self): + expected = 'cell comparisons not supported in 3.x.' + def f(x): + def g(): + return x + return g + cell0, = f(0).func_closure + cell1, = f(1).func_closure + with catch_warning() as w: + self.assertWarning(cell0 == cell1, w, expected) + with catch_warning() as w: + self.assertWarning(cell0 < cell1, w, expected) + + def assertWarning(self, _, warning, expected_message): + self.assertEqual(str(warning.message), expected_message) + +def test_main(): + run_unittest(TestPy3KWarnings) + +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_undocumented_details.py b/Lib/test/test_undocumented_details.py new file mode 100644 index 0000000000..ca66c19f65 --- /dev/null +++ b/Lib/test/test_undocumented_details.py @@ -0,0 +1,39 @@ +from test.test_support import run_unittest, have_unicode +import unittest +import sys + +class TestImplementationComparisons(unittest.TestCase): + + def test_type_comparisons(self): + self.assertTrue(str < int or str > int) + self.assertTrue(int <= str or int >= str) + self.assertTrue(cmp(int, str) != 0) + self.assertTrue(int is int) + self.assertTrue(str == str) + self.assertTrue(int != str) + + def test_cell_comparisons(self): + def f(x): + if x: + y = 1 + def g(): + return x + def h(): + return y + return g, h + g, h = f(0) + g_cell, = g.func_closure + h_cell, = h.func_closure + self.assertTrue(h_cell < g_cell) + self.assertTrue(g_cell >= h_cell) + self.assertEqual(cmp(g_cell, h_cell), 1) + self.assertTrue(g_cell is g_cell) + self.assertTrue(g_cell == g_cell) + self.assertTrue(h_cell == h_cell) + self.assertTrue(g_cell != h_cell) + +def test_main(): + run_unittest(TestImplementationComparisons) + +if __name__ == '__main__': + test_main() diff --git a/Objects/cellobject.c b/Objects/cellobject.c index b72d43be67..37cde41da1 100644 --- a/Objects/cellobject.c +++ b/Objects/cellobject.c @@ -54,6 +54,12 @@ cell_dealloc(PyCellObject *op) static int cell_compare(PyCellObject *a, PyCellObject *b) { + /* Py3K warning for comparisons */ + if (Py_Py3kWarningFlag && PyErr_Warn(PyExc_DeprecationWarning, + "cell comparisons not supported in 3.x.") < 0) { + return NULL; + } + if (a->ob_ref == NULL) { if (b->ob_ref == NULL) return 0; diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 124678544a..1ca28303c7 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1776,8 +1776,14 @@ dict_richcompare(PyObject *v, PyObject *w, int op) return NULL; res = (cmp == (op == Py_EQ)) ? Py_True : Py_False; } - else + else { + /* Py3K warning if comparison isn't == or != */ + if (Py_Py3kWarningFlag && PyErr_Warn(PyExc_DeprecationWarning, + "dict inequality comparisons not supported in 3.x.") < 0) { + return NULL; + } res = Py_NotImplemented; + } Py_INCREF(res); return res; } diff --git a/Objects/object.c b/Objects/object.c index 698ba47601..a10ac7ce19 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -863,8 +863,18 @@ try_3way_to_rich_compare(PyObject *v, PyObject *w, int op) int c; c = try_3way_compare(v, w); - if (c >= 2) + if (c >= 2) { + + /* Py3K warning if types are not equal and comparison isn't == or != */ + if (Py_Py3kWarningFlag && + v->ob_type != w->ob_type && op != Py_EQ && op != Py_NE && + PyErr_Warn(PyExc_DeprecationWarning, + "comparing unequal types not supported in 3.x.") < 0) { + return NULL; + } + c = default_3way_compare(v, w); + } if (c <= -2) return NULL; return convert_3way_to_object(op, c); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 7db6dac7ca..82ced39b30 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -593,6 +593,48 @@ type_compare(PyObject *v, PyObject *w) return (vv < ww) ? -1 : (vv > ww) ? 1 : 0; } +static PyObject* +type_richcompare(PyObject *v, PyObject *w, int op) +{ + PyObject *result; + Py_uintptr_t vv, ww; + int c; + + /* Make sure both arguments are types. */ + if (!PyType_Check(v) || !PyType_Check(w)) { + result = Py_NotImplemented; + goto out; + } + + /* Py3K warning if comparison isn't == or != */ + if (Py_Py3kWarningFlag && op != Py_EQ && op != Py_NE && + PyErr_Warn(PyExc_DeprecationWarning, + "type inequality comparisons not supported in 3.x.") < 0) { + return NULL; + } + + /* Compare addresses */ + vv = (Py_uintptr_t)v; + ww = (Py_uintptr_t)w; + switch (op) { + case Py_LT: c = vv < ww; break; + case Py_LE: c = vv <= ww; break; + case Py_EQ: c = vv == ww; break; + case Py_NE: c = vv != ww; break; + case Py_GT: c = vv > ww; break; + case Py_GE: c = vv >= ww; break; + default: + result = Py_NotImplemented; + goto out; + } + result = c ? Py_True : Py_False; + + /* incref and return */ + out: + Py_INCREF(result); + return result; +} + static PyObject * type_repr(PyTypeObject *type) { @@ -2666,7 +2708,7 @@ PyTypeObject PyType_Type = { type_doc, /* tp_doc */ (traverseproc)type_traverse, /* tp_traverse */ (inquiry)type_clear, /* tp_clear */ - 0, /* tp_richcompare */ + type_richcompare, /* tp_richcompare */ offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */