mirror of
https://github.com/python/cpython.git
synced 2025-11-01 10:45:30 +00:00
Reimplement PySequence_Contains() and instance_contains(), so they work
safely together and don't duplicate logic (the common logic was factored
out into new private API function _PySequence_IterContains()).
Visible change:
some_complex_number in some_instance
no longer blows up if some_instance has __getitem__ but neither
__contains__ nor __iter__. test_iter changed to ensure that remains true.
This commit is contained in:
parent
a8defaae04
commit
cb8d368b82
4 changed files with 67 additions and 77 deletions
|
|
@ -1381,29 +1381,14 @@ Fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Return -1 if error; 1 if v in w; 0 if v not in w. */
|
||||
/* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
|
||||
* Always uses the iteration protocol, and only Py_EQ comparison.
|
||||
*/
|
||||
int
|
||||
PySequence_Contains(PyObject *w, PyObject *v) /* v in w */
|
||||
_PySequence_IterContains(PyObject *seq, PyObject *ob)
|
||||
{
|
||||
PyObject *it; /* iter(w) */
|
||||
int result;
|
||||
|
||||
if (PyType_HasFeature(w->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
|
||||
PySequenceMethods *sq = w->ob_type->tp_as_sequence;
|
||||
if (sq != NULL && sq->sq_contains != NULL) {
|
||||
result = (*sq->sq_contains)(w, v);
|
||||
if (result >= 0)
|
||||
return result;
|
||||
assert(PyErr_Occurred());
|
||||
if (PyErr_ExceptionMatches(PyExc_AttributeError))
|
||||
PyErr_Clear();
|
||||
else
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try exhaustive iteration. */
|
||||
it = PyObject_GetIter(w);
|
||||
PyObject *it = PyObject_GetIter(seq);
|
||||
if (it == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"'in' or 'not in' needs iterable right argument");
|
||||
|
|
@ -1417,7 +1402,7 @@ PySequence_Contains(PyObject *w, PyObject *v) /* v in w */
|
|||
result = PyErr_Occurred() ? -1 : 0;
|
||||
break;
|
||||
}
|
||||
cmp = PyObject_RichCompareBool(v, item, Py_EQ);
|
||||
cmp = PyObject_RichCompareBool(ob, item, Py_EQ);
|
||||
Py_DECREF(item);
|
||||
if (cmp == 0)
|
||||
continue;
|
||||
|
|
@ -1428,6 +1413,20 @@ PySequence_Contains(PyObject *w, PyObject *v) /* v in w */
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
|
||||
* Use sq_contains if possible, else defer to _PySequence_IterContains().
|
||||
*/
|
||||
int
|
||||
PySequence_Contains(PyObject *seq, PyObject *ob)
|
||||
{
|
||||
if (PyType_HasFeature(seq->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
|
||||
PySequenceMethods *sqm = seq->ob_type->tp_as_sequence;
|
||||
if (sqm != NULL && sqm->sq_contains != NULL)
|
||||
return (*sqm->sq_contains)(seq, ob);
|
||||
}
|
||||
return _PySequence_IterContains(seq, ob);
|
||||
}
|
||||
|
||||
/* Backwards compatibility */
|
||||
#undef PySequence_In
|
||||
int
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue