summaryrefslogtreecommitdiffstats
path: root/Objects/abstract.c
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-05-05 21:05:01 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-05-05 21:05:01 (GMT)
commitcb8d368b824a38a0b04598ba2bcd107d6aae3595 (patch)
tree36ddccccf56188d23285e0e5a8e6793d94f58c8a /Objects/abstract.c
parenta8defaae0444157c96abc13090d71f49fede0b4a (diff)
downloadcpython-cb8d368b824a38a0b04598ba2bcd107d6aae3595.zip
cpython-cb8d368b824a38a0b04598ba2bcd107d6aae3595.tar.gz
cpython-cb8d368b824a38a0b04598ba2bcd107d6aae3595.tar.bz2
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.
Diffstat (limited to 'Objects/abstract.c')
-rw-r--r--Objects/abstract.c41
1 files changed, 20 insertions, 21 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 21c1ef1..c1d7789 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -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