Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
41290a68
Commit
41290a68
authored
Mar 31, 2015
by
Raymond Hettinger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue 23793: Add deque support for __add__(), __mul__(), and __imul__().
parent
b6c15bca
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
204 additions
and
10 deletions
+204
-10
Doc/library/collections.rst
Doc/library/collections.rst
+3
-0
Lib/test/test_deque.py
Lib/test/test_deque.py
+77
-0
Misc/NEWS
Misc/NEWS
+1
-0
Modules/_collectionsmodule.c
Modules/_collectionsmodule.c
+123
-10
No files found.
Doc/library/collections.rst
View file @
41290a68
...
@@ -526,6 +526,9 @@ the :keyword:`in` operator, and subscript references such as ``d[-1]``. Indexed
...
@@ -526,6 +526,9 @@ the :keyword:`in` operator, and subscript references such as ``d[-1]``. Indexed
access is O(1) at both ends but slows to O(n) in the middle. For fast random
access is O(1) at both ends but slows to O(n) in the middle. For fast random
access, use lists instead.
access, use lists instead.
Starting in version 3.5, deques support ``__add__()``, ``__mul__()``,
and ``__imul__()``.
Example:
Example:
.. doctest::
.. doctest::
...
...
Lib/test/test_deque.py
View file @
41290a68
...
@@ -192,6 +192,26 @@ class TestBasic(unittest.TestCase):
...
@@ -192,6 +192,26 @@ class TestBasic(unittest.TestCase):
d
.
extend
(
d
)
d
.
extend
(
d
)
self
.
assertEqual
(
list
(
d
),
list
(
'abcdabcd'
))
self
.
assertEqual
(
list
(
d
),
list
(
'abcdabcd'
))
def
test_add
(
self
):
d
=
deque
()
e
=
deque
(
'abc'
)
f
=
deque
(
'def'
)
self
.
assertEqual
(
d
+
d
,
deque
())
self
.
assertEqual
(
e
+
f
,
deque
(
'abcdef'
))
self
.
assertEqual
(
e
+
e
,
deque
(
'abcabc'
))
self
.
assertEqual
(
e
+
d
,
deque
(
'abc'
))
self
.
assertEqual
(
d
+
e
,
deque
(
'abc'
))
self
.
assertIsNot
(
d
+
d
,
deque
())
self
.
assertIsNot
(
e
+
d
,
deque
(
'abc'
))
self
.
assertIsNot
(
d
+
e
,
deque
(
'abc'
))
g
=
deque
(
'abcdef'
,
maxlen
=
4
)
h
=
deque
(
'gh'
)
self
.
assertEqual
(
g
+
h
,
deque
(
'efgh'
))
with
self
.
assertRaises
(
TypeError
):
deque
(
'abc'
)
+
'def'
def
test_iadd
(
self
):
def
test_iadd
(
self
):
d
=
deque
(
'a'
)
d
=
deque
(
'a'
)
d
+=
'bcd'
d
+=
'bcd'
...
@@ -279,6 +299,63 @@ class TestBasic(unittest.TestCase):
...
@@ -279,6 +299,63 @@ class TestBasic(unittest.TestCase):
s
.
insert
(
i
,
'Z'
)
s
.
insert
(
i
,
'Z'
)
self
.
assertEqual
(
list
(
d
),
s
)
self
.
assertEqual
(
list
(
d
),
s
)
def
test_imul
(
self
):
for
n
in
(
-
10
,
-
1
,
0
,
1
,
2
,
10
,
1000
):
d
=
deque
()
d
*=
n
self
.
assertEqual
(
d
,
deque
())
self
.
assertIsNone
(
d
.
maxlen
)
for
n
in
(
-
10
,
-
1
,
0
,
1
,
2
,
10
,
1000
):
d
=
deque
(
'a'
)
d
*=
n
self
.
assertEqual
(
d
,
deque
(
'a'
*
n
))
self
.
assertIsNone
(
d
.
maxlen
)
for
n
in
(
-
10
,
-
1
,
0
,
1
,
2
,
10
,
499
,
500
,
501
,
1000
):
d
=
deque
(
'a'
,
500
)
d
*=
n
self
.
assertEqual
(
d
,
deque
(
'a'
*
min
(
n
,
500
)))
self
.
assertEqual
(
d
.
maxlen
,
500
)
for
n
in
(
-
10
,
-
1
,
0
,
1
,
2
,
10
,
1000
):
d
=
deque
(
'abcdef'
)
d
*=
n
self
.
assertEqual
(
d
,
deque
(
'abcdef'
*
n
))
self
.
assertIsNone
(
d
.
maxlen
)
for
n
in
(
-
10
,
-
1
,
0
,
1
,
2
,
10
,
499
,
500
,
501
,
1000
):
d
=
deque
(
'abcdef'
,
500
)
d
*=
n
self
.
assertEqual
(
d
,
deque
((
'abcdef'
*
n
)[
-
500
:]))
self
.
assertEqual
(
d
.
maxlen
,
500
)
def
test_mul
(
self
):
d
=
deque
(
'abc'
)
self
.
assertEqual
(
d
*
-
5
,
deque
())
self
.
assertEqual
(
d
*
0
,
deque
())
self
.
assertEqual
(
d
*
1
,
deque
(
'abc'
))
self
.
assertEqual
(
d
*
2
,
deque
(
'abcabc'
))
self
.
assertEqual
(
d
*
3
,
deque
(
'abcabcabc'
))
self
.
assertIsNot
(
d
*
1
,
d
)
self
.
assertEqual
(
deque
()
*
0
,
deque
())
self
.
assertEqual
(
deque
()
*
1
,
deque
())
self
.
assertEqual
(
deque
()
*
5
,
deque
())
self
.
assertEqual
(
-
5
*
d
,
deque
())
self
.
assertEqual
(
0
*
d
,
deque
())
self
.
assertEqual
(
1
*
d
,
deque
(
'abc'
))
self
.
assertEqual
(
2
*
d
,
deque
(
'abcabc'
))
self
.
assertEqual
(
3
*
d
,
deque
(
'abcabcabc'
))
d
=
deque
(
'abc'
,
maxlen
=
5
)
self
.
assertEqual
(
d
*
-
5
,
deque
())
self
.
assertEqual
(
d
*
0
,
deque
())
self
.
assertEqual
(
d
*
1
,
deque
(
'abc'
))
self
.
assertEqual
(
d
*
2
,
deque
(
'bcabc'
))
self
.
assertEqual
(
d
*
30
,
deque
(
'bcabc'
))
def
test_setitem
(
self
):
def
test_setitem
(
self
):
n
=
200
n
=
200
d
=
deque
(
range
(
n
))
d
=
deque
(
range
(
n
))
...
...
Misc/NEWS
View file @
41290a68
...
@@ -152,6 +152,7 @@ Library
...
@@ -152,6 +152,7 @@ Library
-
Issue
#
23704
:
collections
.
deque
()
objects
now
support
methods
for
index
(),
-
Issue
#
23704
:
collections
.
deque
()
objects
now
support
methods
for
index
(),
insert
(),
and
copy
().
This
allows
deques
to
be
registered
as
a
insert
(),
and
copy
().
This
allows
deques
to
be
registered
as
a
MutableSequence
and
it
improves
their
substitutablity
for
lists
.
MutableSequence
and
it
improves
their
substitutablity
for
lists
.
Deques
now
also
support
__add__
,
__mul__
,
and
__imul__
().
-
Issue
#
23715
:
:
func
:`
signal
.
sigwaitinfo
`
and
:
func
:`
signal
.
sigtimedwait
`
are
-
Issue
#
23715
:
:
func
:`
signal
.
sigwaitinfo
`
and
:
func
:`
signal
.
sigtimedwait
`
are
now
retried
when
interrupted
by
a
signal
not
in
the
*
sigset
*
parameter
,
if
now
retried
when
interrupted
by
a
signal
not
in
the
*
sigset
*
parameter
,
if
...
...
Modules/_collectionsmodule.c
View file @
41290a68
...
@@ -110,6 +110,12 @@ static PyTypeObject deque_type;
...
@@ -110,6 +110,12 @@ static PyTypeObject deque_type;
#define CHECK_NOT_END(link)
#define CHECK_NOT_END(link)
#endif
#endif
/* To prevent len from overflowing PY_SSIZE_T_MAX, we refuse to
allocate new blocks if the current len is nearing overflow.
*/
#define MAX_DEQUE_LEN (PY_SSIZE_T_MAX - 3*BLOCKLEN)
/* A simple freelisting scheme is used to minimize calls to the memory
/* A simple freelisting scheme is used to minimize calls to the memory
allocator. It accommodates common use cases where new blocks are being
allocator. It accommodates common use cases where new blocks are being
added at about the same rate as old blocks are being freed.
added at about the same rate as old blocks are being freed.
...
@@ -122,9 +128,7 @@ static block *freeblocks[MAXFREEBLOCKS];
...
@@ -122,9 +128,7 @@ static block *freeblocks[MAXFREEBLOCKS];
static
block
*
static
block
*
newblock
(
Py_ssize_t
len
)
{
newblock
(
Py_ssize_t
len
)
{
block
*
b
;
block
*
b
;
/* To prevent len from overflowing PY_SSIZE_T_MAX, we refuse to
if
(
len
>=
MAX_DEQUE_LEN
)
{
* allocate new blocks if the current len is nearing overflow. */
if
(
len
>=
PY_SSIZE_T_MAX
-
2
*
BLOCKLEN
)
{
PyErr_SetString
(
PyExc_OverflowError
,
PyErr_SetString
(
PyExc_OverflowError
,
"cannot add more blocks to the deque"
);
"cannot add more blocks to the deque"
);
return
NULL
;
return
NULL
;
...
@@ -498,6 +502,115 @@ deque_inplace_concat(dequeobject *deque, PyObject *other)
...
@@ -498,6 +502,115 @@ deque_inplace_concat(dequeobject *deque, PyObject *other)
return
(
PyObject
*
)
deque
;
return
(
PyObject
*
)
deque
;
}
}
static
PyObject
*
deque_copy
(
PyObject
*
deque
);
static
PyObject
*
deque_concat
(
dequeobject
*
deque
,
PyObject
*
other
)
{
PyObject
*
new_deque
;
int
rv
;
rv
=
PyObject_IsInstance
(
other
,
(
PyObject
*
)
&
deque_type
);
if
(
rv
<=
0
)
{
if
(
rv
==
0
)
{
PyErr_Format
(
PyExc_TypeError
,
"can only concatenate deque (not
\"
%.200s
\"
) to deque"
,
other
->
ob_type
->
tp_name
);
}
return
NULL
;
}
new_deque
=
deque_copy
((
PyObject
*
)
deque
);
if
(
new_deque
==
NULL
)
return
NULL
;
return
deque_inplace_concat
((
dequeobject
*
)
new_deque
,
other
);
}
static
void
deque_clear
(
dequeobject
*
deque
);
static
PyObject
*
deque_repeat
(
dequeobject
*
deque
,
Py_ssize_t
n
)
{
dequeobject
*
new_deque
;
PyObject
*
result
;
/* XXX add a special case for when maxlen is defined */
if
(
n
<
0
)
n
=
0
;
else
if
(
n
>
0
&&
Py_SIZE
(
deque
)
>
MAX_DEQUE_LEN
/
n
)
return
PyErr_NoMemory
();
new_deque
=
(
dequeobject
*
)
deque_new
(
&
deque_type
,
(
PyObject
*
)
NULL
,
(
PyObject
*
)
NULL
);
new_deque
->
maxlen
=
deque
->
maxlen
;
for
(
;
n
;
n
--
)
{
result
=
deque_extend
(
new_deque
,
(
PyObject
*
)
deque
);
if
(
result
==
NULL
)
{
Py_DECREF
(
new_deque
);
return
NULL
;
}
Py_DECREF
(
result
);
}
return
(
PyObject
*
)
new_deque
;
}
static
PyObject
*
deque_inplace_repeat
(
dequeobject
*
deque
,
Py_ssize_t
n
)
{
Py_ssize_t
i
,
size
;
PyObject
*
seq
;
PyObject
*
rv
;
size
=
Py_SIZE
(
deque
);
if
(
size
==
0
||
n
==
1
)
{
Py_INCREF
(
deque
);
return
(
PyObject
*
)
deque
;
}
if
(
n
<=
0
)
{
deque_clear
(
deque
);
Py_INCREF
(
deque
);
return
(
PyObject
*
)
deque
;
}
if
(
size
>
MAX_DEQUE_LEN
/
n
)
{
return
PyErr_NoMemory
();
}
if
(
size
==
1
)
{
/* common case, repeating a single element */
PyObject
*
item
=
deque
->
leftblock
->
data
[
deque
->
leftindex
];
if
(
deque
->
maxlen
!=
-
1
&&
n
>
deque
->
maxlen
)
n
=
deque
->
maxlen
;
for
(
i
=
0
;
i
<
n
-
1
;
i
++
)
{
rv
=
deque_append
(
deque
,
item
);
if
(
rv
==
NULL
)
return
NULL
;
Py_DECREF
(
rv
);
}
Py_INCREF
(
deque
);
return
(
PyObject
*
)
deque
;
}
seq
=
PySequence_List
((
PyObject
*
)
deque
);
if
(
seq
==
NULL
)
return
seq
;
for
(
i
=
0
;
i
<
n
-
1
;
i
++
)
{
rv
=
deque_extend
(
deque
,
seq
);
if
(
rv
==
NULL
)
{
Py_DECREF
(
seq
);
return
NULL
;
}
Py_DECREF
(
rv
);
}
Py_INCREF
(
deque
);
Py_DECREF
(
seq
);
return
(
PyObject
*
)
deque
;
}
/* The rotate() method is part of the public API and is used internally
/* The rotate() method is part of the public API and is used internally
as a primitive for other methods.
as a primitive for other methods.
...
@@ -1283,6 +1396,9 @@ deque_get_maxlen(dequeobject *deque)
...
@@ -1283,6 +1396,9 @@ deque_get_maxlen(dequeobject *deque)
return
PyLong_FromSsize_t
(
deque
->
maxlen
);
return
PyLong_FromSsize_t
(
deque
->
maxlen
);
}
}
/* deque object ********************************************************/
static
PyGetSetDef
deque_getset
[]
=
{
static
PyGetSetDef
deque_getset
[]
=
{
{
"maxlen"
,
(
getter
)
deque_get_maxlen
,
(
setter
)
NULL
,
{
"maxlen"
,
(
getter
)
deque_get_maxlen
,
(
setter
)
NULL
,
"maximum size of a deque or None if unbounded"
},
"maximum size of a deque or None if unbounded"
},
...
@@ -1291,15 +1407,15 @@ static PyGetSetDef deque_getset[] = {
...
@@ -1291,15 +1407,15 @@ static PyGetSetDef deque_getset[] = {
static
PySequenceMethods
deque_as_sequence
=
{
static
PySequenceMethods
deque_as_sequence
=
{
(
lenfunc
)
deque_len
,
/* sq_length */
(
lenfunc
)
deque_len
,
/* sq_length */
0
,
/* sq_concat */
(
binaryfunc
)
deque_concat
,
/* sq_concat */
0
,
/* sq_repeat */
(
ssizeargfunc
)
deque_repeat
,
/* sq_repeat */
(
ssizeargfunc
)
deque_item
,
/* sq_item */
(
ssizeargfunc
)
deque_item
,
/* sq_item */
0
,
/* sq_slice */
0
,
/* sq_slice */
(
ssizeobjargproc
)
deque_ass_item
,
/* sq_ass_item */
(
ssizeobjargproc
)
deque_ass_item
,
/* sq_ass_item */
0
,
/* sq_ass_slice */
0
,
/* sq_ass_slice */
(
objobjproc
)
deque_contains
,
/* sq_contains */
(
objobjproc
)
deque_contains
,
/* sq_contains */
(
binaryfunc
)
deque_inplace_concat
,
/* sq_inplace_concat */
(
binaryfunc
)
deque_inplace_concat
,
/* sq_inplace_concat */
0
,
/* sq_inplace_repeat */
(
ssizeargfunc
)
deque_inplace_repeat
,
/* sq_inplace_repeat */
};
};
static
PyNumberMethods
deque_as_number
=
{
static
PyNumberMethods
deque_as_number
=
{
...
@@ -1316,9 +1432,6 @@ static PyNumberMethods deque_as_number = {
...
@@ -1316,9 +1432,6 @@ static PyNumberMethods deque_as_number = {
0
,
/* nb_invert */
0
,
/* nb_invert */
};
};
/* deque object ********************************************************/
static
PyObject
*
deque_iter
(
dequeobject
*
deque
);
static
PyObject
*
deque_iter
(
dequeobject
*
deque
);
static
PyObject
*
deque_reviter
(
dequeobject
*
deque
);
static
PyObject
*
deque_reviter
(
dequeobject
*
deque
);
PyDoc_STRVAR
(
reversed_doc
,
PyDoc_STRVAR
(
reversed_doc
,
...
@@ -1367,7 +1480,7 @@ static PyMethodDef deque_methods[] = {
...
@@ -1367,7 +1480,7 @@ static PyMethodDef deque_methods[] = {
PyDoc_STRVAR
(
deque_doc
,
PyDoc_STRVAR
(
deque_doc
,
"deque([iterable[, maxlen]]) --> deque object
\n
\
"deque([iterable[, maxlen]]) --> deque object
\n
\
\n
\
\n
\
Build an ordered collection with optimized access from
its endpoints."
);
A list-like sequence optimized for data accesses near
its endpoints."
);
static
PyTypeObject
deque_type
=
{
static
PyTypeObject
deque_type
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
PyVarObject_HEAD_INIT
(
NULL
,
0
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment