diff options
author | Tim Peters <tim.peters@gmail.com> | 2001-05-05 21:05:01 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2001-05-05 21:05:01 (GMT) |
commit | cb8d368b824a38a0b04598ba2bcd107d6aae3595 (patch) | |
tree | 36ddccccf56188d23285e0e5a8e6793d94f58c8a /Objects/abstract.c | |
parent | a8defaae0444157c96abc13090d71f49fede0b4a (diff) | |
download | cpython-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.c | 41 |
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 |