summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2011-01-25 21:32:39 (GMT)
committerRaymond Hettinger <python@rcn.com>2011-01-25 21:32:39 (GMT)
commit512d2cc64328d06f4ff627497ab444e83e513348 (patch)
tree6d3599b5f69310a74dba4eb02c79e91899aba4a0
parent5543e8135240cfe4f3d1021c1debe752e3cd7309 (diff)
downloadcpython-512d2cc64328d06f4ff627497ab444e83e513348.zip
cpython-512d2cc64328d06f4ff627497ab444e83e513348.tar.gz
cpython-512d2cc64328d06f4ff627497ab444e83e513348.tar.bz2
Issue #11004: Repair edge case in deque.count().
(Reviewed by Georg Brandl.) Also made similar changes to deque.reverse() though this wasn't strictly necessary (the edge case cannot occur with two pointers moving to meet in the middle). Making the change in reverse() was more a matter of future-proofing.
-rw-r--r--Lib/test/test_deque.py9
-rw-r--r--Misc/NEWS2
-rw-r--r--Modules/_collectionsmodule.c11
3 files changed, 18 insertions, 4 deletions
diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py
index da00c0d..0dcadeb 100644
--- a/Lib/test/test_deque.py
+++ b/Lib/test/test_deque.py
@@ -138,6 +138,15 @@ class TestBasic(unittest.TestCase):
m.d = d
self.assertRaises(RuntimeError, d.count, 3)
+ # test issue11004
+ # block advance failed after rotation aligned elements on right side of block
+ d = deque([None]*16)
+ for i in range(len(d)):
+ d.rotate(-1)
+ d.rotate(1)
+ self.assertEqual(d.count(1), 0)
+ self.assertEqual(d.count(None), 16)
+
def test_comparisons(self):
d = deque('xabc'); d.popleft()
for e in [d, deque('abc'), deque('ab'), deque(), list(d)]:
diff --git a/Misc/NEWS b/Misc/NEWS
index 07f493a..5655205 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -16,6 +16,8 @@ Core and Builtins
Library
-------
+- Issue #11004: Repaired edge case in deque.count().
+
- Issue #10974: IDLE no longer crashes if its recent files list includes files
with non-ASCII characters in their path names.
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
index f4a2c8b..2391c0d 100644
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -485,7 +485,8 @@ deque_reverse(dequeobject *deque, PyObject *unused)
/* Advance left block/index pair */
leftindex++;
if (leftindex == BLOCKLEN) {
- assert (leftblock->rightlink != NULL);
+ if (leftblock->rightlink == NULL)
+ break;
leftblock = leftblock->rightlink;
leftindex = 0;
}
@@ -493,7 +494,8 @@ deque_reverse(dequeobject *deque, PyObject *unused)
/* Step backwards with the right block/index pair */
rightindex--;
if (rightindex == -1) {
- assert (rightblock->leftlink != NULL);
+ if (rightblock->leftlink == NULL)
+ break;
rightblock = rightblock->leftlink;
rightindex = BLOCKLEN - 1;
}
@@ -509,7 +511,7 @@ deque_count(dequeobject *deque, PyObject *v)
{
block *leftblock = deque->leftblock;
Py_ssize_t leftindex = deque->leftindex;
- Py_ssize_t n = (deque->len);
+ Py_ssize_t n = deque->len;
Py_ssize_t i;
Py_ssize_t count = 0;
PyObject *item;
@@ -533,7 +535,8 @@ deque_count(dequeobject *deque, PyObject *v)
/* Advance left block/index pair */
leftindex++;
if (leftindex == BLOCKLEN) {
- assert (leftblock->rightlink != NULL);
+ if (leftblock->rightlink == NULL) /* can occur when i==n-1 */
+ break;
leftblock = leftblock->rightlink;
leftindex = 0;
}