summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
Diffstat (limited to 'Objects')
-rw-r--r--Objects/abstract.c41
-rw-r--r--Objects/classobject.c67
2 files changed, 50 insertions, 58 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
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 2babbfb..67732ca 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -1131,11 +1131,15 @@ instance_ass_slice(PyInstanceObject *inst, int i, int j, PyObject *value)
return 0;
}
-static int instance_contains(PyInstanceObject *inst, PyObject *member)
+static int
+instance_contains(PyInstanceObject *inst, PyObject *member)
{
static PyObject *__contains__;
- PyObject *func, *arg, *res;
- int ret;
+ PyObject *func;
+
+ /* Try __contains__ first.
+ * If that can't be done, try iterator-based searching.
+ */
if(__contains__ == NULL) {
__contains__ = PyString_InternFromString("__contains__");
@@ -1143,45 +1147,34 @@ static int instance_contains(PyInstanceObject *inst, PyObject *member)
return -1;
}
func = instance_getattr(inst, __contains__);
- if(func == NULL) {
- /* fall back to previous behavior */
- int i, cmp_res;
-
- if(!PyErr_ExceptionMatches(PyExc_AttributeError))
+ if (func) {
+ PyObject *res;
+ int ret;
+ PyObject *arg = Py_BuildValue("(O)", member);
+ if(arg == NULL) {
+ Py_DECREF(func);
return -1;
- PyErr_Clear();
- for(i=0;;i++) {
- PyObject *obj = instance_item(inst, i);
- int ret = 0;
-
- if(obj == NULL) {
- if(!PyErr_ExceptionMatches(PyExc_IndexError))
- return -1;
- PyErr_Clear();
- return 0;
- }
- if(PyObject_Cmp(obj, member, &cmp_res) == -1)
- ret = -1;
- if(cmp_res == 0)
- ret = 1;
- Py_DECREF(obj);
- if(ret)
- return ret;
}
- }
- arg = Py_BuildValue("(O)", member);
- if(arg == NULL) {
+ res = PyEval_CallObject(func, arg);
Py_DECREF(func);
- return -1;
+ Py_DECREF(arg);
+ if(res == NULL)
+ return -1;
+ ret = PyObject_IsTrue(res);
+ Py_DECREF(res);
+ return ret;
}
- res = PyEval_CallObject(func, arg);
- Py_DECREF(func);
- Py_DECREF(arg);
- if(res == NULL)
+
+ /* Couldn't find __contains__. */
+ if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ /* Assume the failure was simply due to that there is no
+ * __contains__ attribute, and try iterating instead.
+ */
+ PyErr_Clear();
+ return _PySequence_IterContains((PyObject *)inst, member);
+ }
+ else
return -1;
- ret = PyObject_IsTrue(res);
- Py_DECREF(res);
- return ret;
}
static PySequenceMethods