Skip to content

Commit f9b3972

Browse files
author
steven.bethard
committed
Add py3k warnings for code and method inequality comparisons. This should resolve issue 2373. The codeobject.c and methodobject.c changes are both just backports of the Python 3 code.
git-svn-id: http://svn.python.org/projects/python/trunk@61570 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent b8afef6 commit f9b3972

3 files changed

Lines changed: 131 additions & 2 deletions

File tree

Lib/test/test_py3kwarn.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,35 @@ def g():
5050
with catch_warning() as w:
5151
self.assertWarning(cell0 < cell1, w, expected)
5252

53+
def test_code_inequality_comparisons(self):
54+
expected = 'code inequality comparisons not supported in 3.x.'
55+
def f(x):
56+
pass
57+
def g(x):
58+
pass
59+
with catch_warning() as w:
60+
self.assertWarning(f.func_code < g.func_code, w, expected)
61+
with catch_warning() as w:
62+
self.assertWarning(f.func_code <= g.func_code, w, expected)
63+
with catch_warning() as w:
64+
self.assertWarning(f.func_code >= g.func_code, w, expected)
65+
with catch_warning() as w:
66+
self.assertWarning(f.func_code > g.func_code, w, expected)
67+
68+
def test_builtin_function_or_method_comparisons(self):
69+
expected = ('builtin_function_or_method '
70+
'inequality comparisons not supported in 3.x.')
71+
func = eval
72+
meth = {}.get
73+
with catch_warning() as w:
74+
self.assertWarning(func < meth, w, expected)
75+
with catch_warning() as w:
76+
self.assertWarning(func > meth, w, expected)
77+
with catch_warning() as w:
78+
self.assertWarning(meth <= func, w, expected)
79+
with catch_warning() as w:
80+
self.assertWarning(meth >= func, w, expected)
81+
5382
def assertWarning(self, _, warning, expected_message):
5483
self.assertEqual(str(warning.message), expected_message)
5584

Objects/codeobject.c

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,72 @@ code_compare(PyCodeObject *co, PyCodeObject *cp)
327327
return 0;
328328
}
329329

330+
static PyObject *
331+
code_richcompare(PyObject *self, PyObject *other, int op)
332+
{
333+
PyCodeObject *co, *cp;
334+
int eq;
335+
PyObject *res;
336+
337+
if ((op != Py_EQ && op != Py_NE) ||
338+
!PyCode_Check(self) ||
339+
!PyCode_Check(other)) {
340+
341+
/* Py3K warning if types are not equal and comparison isn't == or != */
342+
if (Py_Py3kWarningFlag && PyErr_Warn(PyExc_DeprecationWarning,
343+
"code inequality comparisons not supported in 3.x.") < 0) {
344+
return NULL;
345+
}
346+
347+
Py_INCREF(Py_NotImplemented);
348+
return Py_NotImplemented;
349+
}
350+
351+
co = (PyCodeObject *)self;
352+
cp = (PyCodeObject *)other;
353+
354+
eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ);
355+
if (eq <= 0) goto unequal;
356+
eq = co->co_argcount == cp->co_argcount;
357+
if (!eq) goto unequal;
358+
eq = co->co_nlocals == cp->co_nlocals;
359+
if (!eq) goto unequal;
360+
eq = co->co_flags == cp->co_flags;
361+
if (!eq) goto unequal;
362+
eq = co->co_firstlineno == cp->co_firstlineno;
363+
if (!eq) goto unequal;
364+
eq = PyObject_RichCompareBool(co->co_code, cp->co_code, Py_EQ);
365+
if (eq <= 0) goto unequal;
366+
eq = PyObject_RichCompareBool(co->co_consts, cp->co_consts, Py_EQ);
367+
if (eq <= 0) goto unequal;
368+
eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ);
369+
if (eq <= 0) goto unequal;
370+
eq = PyObject_RichCompareBool(co->co_varnames, cp->co_varnames, Py_EQ);
371+
if (eq <= 0) goto unequal;
372+
eq = PyObject_RichCompareBool(co->co_freevars, cp->co_freevars, Py_EQ);
373+
if (eq <= 0) goto unequal;
374+
eq = PyObject_RichCompareBool(co->co_cellvars, cp->co_cellvars, Py_EQ);
375+
if (eq <= 0) goto unequal;
376+
377+
if (op == Py_EQ)
378+
res = Py_True;
379+
else
380+
res = Py_False;
381+
goto done;
382+
383+
unequal:
384+
if (eq < 0)
385+
return NULL;
386+
if (op == Py_NE)
387+
res = Py_True;
388+
else
389+
res = Py_False;
390+
391+
done:
392+
Py_INCREF(res);
393+
return res;
394+
}
395+
330396
static long
331397
code_hash(PyCodeObject *co)
332398
{
@@ -377,7 +443,7 @@ PyTypeObject PyCode_Type = {
377443
code_doc, /* tp_doc */
378444
0, /* tp_traverse */
379445
0, /* tp_clear */
380-
0, /* tp_richcompare */
446+
code_richcompare, /* tp_richcompare */
381447
0, /* tp_weaklistoffset */
382448
0, /* tp_iter */
383449
0, /* tp_iternext */

Objects/methodobject.c

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,40 @@ meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
223223
return 1;
224224
}
225225

226+
static PyObject *
227+
meth_richcompare(PyObject *self, PyObject *other, int op)
228+
{
229+
PyCFunctionObject *a, *b;
230+
PyObject *res;
231+
int eq;
232+
233+
if ((op != Py_EQ && op != Py_NE) ||
234+
!PyCFunction_Check(self) ||
235+
!PyCFunction_Check(other))
236+
{
237+
/* Py3K warning if types are not equal and comparison isn't == or != */
238+
if (Py_Py3kWarningFlag && PyErr_Warn(PyExc_DeprecationWarning,
239+
"builtin_function_or_method "
240+
"inequality comparisons not supported in 3.x.") < 0) {
241+
return NULL;
242+
}
243+
244+
Py_INCREF(Py_NotImplemented);
245+
return Py_NotImplemented;
246+
}
247+
a = (PyCFunctionObject *)self;
248+
b = (PyCFunctionObject *)other;
249+
eq = a->m_self == b->m_self;
250+
if (eq)
251+
eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
252+
if (op == Py_EQ)
253+
res = eq ? Py_True : Py_False;
254+
else
255+
res = eq ? Py_False : Py_True;
256+
Py_INCREF(res);
257+
return res;
258+
}
259+
226260
static long
227261
meth_hash(PyCFunctionObject *a)
228262
{
@@ -268,7 +302,7 @@ PyTypeObject PyCFunction_Type = {
268302
0, /* tp_doc */
269303
(traverseproc)meth_traverse, /* tp_traverse */
270304
0, /* tp_clear */
271-
0, /* tp_richcompare */
305+
meth_richcompare, /* tp_richcompare */
272306
0, /* tp_weaklistoffset */
273307
0, /* tp_iter */
274308
0, /* tp_iternext */

0 commit comments

Comments
 (0)