[Python-checkins] r79728 - in python/branches/py3k: Doc/library/collections.rst Lib/test/test_deque.py Misc/NEWS Modules/_collectionsmodule.c

raymond.hettinger python-checkins at python.org
Sun Apr 4 01:20:46 CEST 2010


Author: raymond.hettinger
Date: Sun Apr  4 01:20:46 2010
New Revision: 79728

Log:
Add count() method to collections.deque().

Modified:
   python/branches/py3k/Doc/library/collections.rst
   python/branches/py3k/Lib/test/test_deque.py
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/_collectionsmodule.c

Modified: python/branches/py3k/Doc/library/collections.rst
==============================================================================
--- python/branches/py3k/Doc/library/collections.rst	(original)
+++ python/branches/py3k/Doc/library/collections.rst	Sun Apr  4 01:20:46 2010
@@ -338,6 +338,12 @@
       Remove all elements from the deque leaving it with length 0.
 
 
+   .. method:: count(x)
+
+      Count the number of deque elements equal to *x*.
+
+      .. versionadded:: 3.2
+
    .. method:: extend(iterable)
 
       Extend the right side of the deque by appending elements from the iterable

Modified: python/branches/py3k/Lib/test/test_deque.py
==============================================================================
--- python/branches/py3k/Lib/test/test_deque.py	(original)
+++ python/branches/py3k/Lib/test/test_deque.py	Sun Apr  4 01:20:46 2010
@@ -114,6 +114,30 @@
             d = deque('abc')
             d.maxlen = 10
 
+    def test_count(self):
+        for s in ('', 'abracadabra', 'simsalabim'*500+'abc'):
+            s = list(s)
+            d = deque(s)
+            for letter in 'abcdefghijklmnopqrstuvwxyz':
+                self.assertEqual(s.count(letter), d.count(letter), (s, d, letter))
+        self.assertRaises(TypeError, d.count)       # too few args
+        self.assertRaises(TypeError, d.count, 1, 2) # too many args
+        class BadCompare:
+            def __eq__(self, other):
+                raise ArithmeticError
+        d = deque([1, 2, BadCompare(), 3])
+        self.assertRaises(ArithmeticError, d.count, 2)
+        d = deque([1, 2, 3])
+        self.assertRaises(ArithmeticError, d.count, BadCompare())
+        class MutatingCompare:
+            def __eq__(self, other):
+                self.d.pop()
+                return True
+        m = MutatingCompare()
+        d = deque([1, 2, 3, m, 4, 5])
+        m.d = d
+        self.assertRaises(RuntimeError, d.count, 3)
+
     def test_comparisons(self):
         d = deque('xabc'); d.popleft()
         for e in [d, deque('abc'), deque('ab'), deque(), list(d)]:

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Sun Apr  4 01:20:46 2010
@@ -576,7 +576,7 @@
 - Issue #5949: added check for correct lineends in input from IMAP server
   in imaplib.
 
-- Add a reverse() method to collections.deque().
+- Add count() and reverse() methods to collections.deque().
 
 - Fix variations of extending deques:  d.extend(d)  d.extendleft(d)  d+=d
 

Modified: python/branches/py3k/Modules/_collectionsmodule.c
==============================================================================
--- python/branches/py3k/Modules/_collectionsmodule.c	(original)
+++ python/branches/py3k/Modules/_collectionsmodule.c	Sun Apr  4 01:20:46 2010
@@ -504,6 +504,46 @@
 PyDoc_STRVAR(reverse_doc,
 "D.reverse() -- reverse *IN PLACE*");
 
+static PyObject *
+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 i;
+	Py_ssize_t count = 0;
+	PyObject *item;
+	long start_state = deque->state;
+	int cmp;
+
+	for (i=0 ; i<n ; i++) {
+		item = leftblock->data[leftindex];
+		cmp = PyObject_RichCompareBool(item, v, Py_EQ);
+		if (cmp > 0)
+			count++;
+		else if (cmp < 0)
+			return NULL;
+
+		if (start_state != deque->state) {
+			PyErr_SetString(PyExc_RuntimeError,
+					"deque mutated during iteration");
+			return NULL;
+		}
+
+		/* Advance left block/index pair */
+		leftindex++;
+		if (leftindex == BLOCKLEN) {
+			assert (leftblock->rightlink != NULL);
+			leftblock = leftblock->rightlink;
+			leftindex = 0;
+		}
+	}
+	return PyLong_FromSsize_t(count);
+}
+
+PyDoc_STRVAR(count_doc,
+"D.count(value) -> integer -- return number of occurrences of value");
+
 static Py_ssize_t
 deque_len(dequeobject *deque)
 {
@@ -933,6 +973,8 @@
 		METH_NOARGS,	 clear_doc},
 	{"__copy__",		(PyCFunction)deque_copy,
 		METH_NOARGS,	 copy_doc},
+	{"count",		(PyCFunction)deque_count,
+	    METH_O,			count_doc},
 	{"extend",		(PyCFunction)deque_extend,
 		METH_O,		 extend_doc},
 	{"extendleft",		(PyCFunction)deque_extendleft,


More information about the Python-checkins mailing list