Slightly revised version of patch #1538956:

Replace UnicodeDecodeErrors raised during == and !=
compares of Unicode and other objects with a new
UnicodeWarning.

All other comparisons continue to raise exceptions.
Exceptions other than UnicodeDecodeErrors are also left
untouched.
This commit is contained in:
Marc-André Lemburg 2006-08-14 10:55:19 +00:00
parent e6dd31c50b
commit 040f76b79c
11 changed files with 170 additions and 36 deletions

View file

@ -5405,6 +5405,82 @@ onError:
return -1;
}
PyObject *PyUnicode_RichCompare(PyObject *left,
PyObject *right,
int op)
{
int result;
result = PyUnicode_Compare(left, right);
if (result == -1 && PyErr_Occurred())
goto onError;
/* Convert the return value to a Boolean */
switch (op) {
case Py_EQ:
result = (result == 0);
break;
case Py_NE:
result = (result != 0);
break;
case Py_LE:
result = (result <= 0);
break;
case Py_GE:
result = (result >= 0);
break;
case Py_LT:
result = (result == -1);
break;
case Py_GT:
result = (result == 1);
break;
}
return PyBool_FromLong(result);
onError:
/* Standard case
Type errors mean that PyUnicode_FromObject() could not convert
one of the arguments (usually the right hand side) to Unicode,
ie. we can't handle the comparison request. However, it is
possible that the other object knows a comparison method, which
is why we return Py_NotImplemented to give the other object a
chance.
*/
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
PyErr_Clear();
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
if (op != Py_EQ && op != Py_NE)
return NULL;
/* Equality comparison.
This is a special case: we silence any PyExc_UnicodeDecodeError
and instead turn it into a PyErr_UnicodeWarning.
*/
if (!PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))
return NULL;
PyErr_Clear();
if (PyErr_Warn(PyExc_UnicodeWarning,
(op == Py_EQ) ?
"Unicode equal comparison "
"failed to convert both arguments to Unicode - "
"interpreting them as being unequal" :
"Unicode unequal comparison "
"failed to convert both arguments to Unicode - "
"interpreting them as being unequal"
) < 0)
return NULL;
result = (op == Py_NE);
return PyBool_FromLong(result);
}
int PyUnicode_Contains(PyObject *container,
PyObject *element)
{
@ -6985,11 +7061,14 @@ static PySequenceMethods unicode_as_sequence = {
PyUnicode_Contains, /* sq_contains */
};
#define HASINDEX(o) PyType_HasFeature((o)->ob_type, Py_TPFLAGS_HAVE_INDEX)
static PyObject*
unicode_subscript(PyUnicodeObject* self, PyObject* item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
PyNumberMethods *nb = item->ob_type->tp_as_number;
if (nb != NULL && HASINDEX(item) && nb->nb_index != NULL) {
Py_ssize_t i = nb->nb_index(item);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
@ -7859,7 +7938,7 @@ PyTypeObject PyUnicode_Type = {
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc) unicode_compare, /* tp_compare */
0, /* tp_compare */
unicode_repr, /* tp_repr */
&unicode_as_number, /* tp_as_number */
&unicode_as_sequence, /* tp_as_sequence */
@ -7875,7 +7954,7 @@ PyTypeObject PyUnicode_Type = {
unicode_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
PyUnicode_RichCompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */