]> granicus.if.org Git - python/commitdiff
Fix variants of deque.extend: d.extend(d) d+=d d.extendleft(d)
authorRaymond Hettinger <python@rcn.com>
Thu, 10 Dec 2009 05:36:11 +0000 (05:36 +0000)
committerRaymond Hettinger <python@rcn.com>
Thu, 10 Dec 2009 05:36:11 +0000 (05:36 +0000)
Lib/test/test_deque.py
Misc/NEWS
Modules/_collectionsmodule.c

index 1a03188e12cbb6a29e33a8e56b9b09d3d476da46..67e41d681a7a6db3463735808e3c0601d65cf32e 100644 (file)
@@ -136,12 +136,23 @@ class TestBasic(unittest.TestCase):
         self.assertRaises(TypeError, d.extend, 1)
         d.extend('bcd')
         self.assertEqual(list(d), list('abcd'))
+        d.extend(d)
+        self.assertEqual(list(d), list('abcdabcd'))
+
+    def test_iadd(self):
+        d = deque('a')
+        d += 'bcd'
+        self.assertEqual(list(d), list('abcd'))
+        d += d
+        self.assertEqual(list(d), list('abcdabcd'))
 
     def test_extendleft(self):
         d = deque('a')
         self.assertRaises(TypeError, d.extendleft, 1)
         d.extendleft('bcd')
         self.assertEqual(list(d), list(reversed('abcd')))
+        d.extendleft(d)
+        self.assertEqual(list(d), list('abcddcba'))
         d = deque()
         d.extendleft(range(1000))
         self.assertEqual(list(d), list(reversed(range(1000))))
index d6c3e97afa8fba57ba7608a48624fc48542b7b0d..700a1aeae86c505cc12571ee7c6eab9f8f66f9f6 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -55,6 +55,8 @@ Core and Builtins
 Library
 -------
 
+- Fix variations of extending deques:  d.extend(d)  d.extendleft(d)  d+=d
+
 - Issue #6986: Fix crash in the JSON C accelerator when called with the
   wrong parameter types.  Patch by Victor Stinner.
 
index 68e01836cb8764f15ddea5e3d6926a58b1c17272..d20c839ae3332735e166af9691341969546ac6eb 100644 (file)
@@ -298,6 +298,17 @@ deque_extend(dequeobject *deque, PyObject *iterable)
 {
        PyObject *it, *item;
 
+       /* Handle case where id(deque) == id(iterable) */
+       if ((PyObject *)deque == iterable) {
+               PyObject *result;
+               PyObject *s = PySequence_List(iterable);
+               if (s == NULL)
+                       return NULL;
+               result = deque_extend(deque, s);
+               Py_DECREF(s);
+               return result;
+       }
+
        it = PyObject_GetIter(iterable);
        if (it == NULL)
                return NULL;
@@ -339,6 +350,17 @@ deque_extendleft(dequeobject *deque, PyObject *iterable)
 {
        PyObject *it, *item;
 
+       /* Handle case where id(deque) == id(iterable) */
+       if ((PyObject *)deque == iterable) {
+               PyObject *result;
+               PyObject *s = PySequence_List(iterable);
+               if (s == NULL)
+                       return NULL;
+               result = deque_extendleft(deque, s);
+               Py_DECREF(s);
+               return result;
+       }
+
        it = PyObject_GetIter(iterable);
        if (it == NULL)
                return NULL;
@@ -375,6 +397,19 @@ deque_extendleft(dequeobject *deque, PyObject *iterable)
 PyDoc_STRVAR(extendleft_doc,
 "Extend the left side of the deque with elements from the iterable");
 
+static PyObject *
+deque_inplace_concat(dequeobject *deque, PyObject *other)
+{
+       PyObject *result;
+
+       result = deque_extend(deque, other);
+       if (result == NULL)
+               return result;
+       Py_DECREF(result);
+       Py_INCREF(deque);
+       return (PyObject *)deque;
+}
+
 static int
 _deque_rotate(dequeobject *deque, Py_ssize_t n)
 {
@@ -833,6 +868,11 @@ static PySequenceMethods deque_as_sequence = {
        (ssizeargfunc)deque_item,       /* sq_item */
        0,                              /* sq_slice */
        (ssizeobjargproc)deque_ass_item,        /* sq_ass_item */
+       0,                              /* sq_ass_slice */
+       0,                              /* sq_contains */
+       (binaryfunc)deque_inplace_concat,       /* sq_inplace_concat */
+       0,                              /* sq_inplace_repeat */
+
 };
 
 /* deque object ********************************************************/