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
31668b8f
Commit
31668b8f
authored
Apr 03, 2012
by
Kristján Valur Jónsson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #14288: Serialization support for builtin iterators.
parent
283b96b6
Changes
28
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
2190 additions
and
104 deletions
+2190
-104
Include/iterobject.h
Include/iterobject.h
+2
-0
Lib/test/seq_tests.py
Lib/test/seq_tests.py
+7
-0
Lib/test/test_array.py
Lib/test/test_array.py
+14
-0
Lib/test/test_builtin.py
Lib/test/test_builtin.py
+41
-0
Lib/test/test_bytes.py
Lib/test/test_bytes.py
+18
-0
Lib/test/test_deque.py
Lib/test/test_deque.py
+13
-0
Lib/test/test_dict.py
Lib/test/test_dict.py
+54
-0
Lib/test/test_enumerate.py
Lib/test/test_enumerate.py
+28
-2
Lib/test/test_iter.py
Lib/test/test_iter.py
+35
-8
Lib/test/test_itertools.py
Lib/test/test_itertools.py
+358
-28
Lib/test/test_list.py
Lib/test/test_list.py
+28
-0
Lib/test/test_range.py
Lib/test/test_range.py
+23
-1
Lib/test/test_set.py
Lib/test/test_set.py
+21
-0
Lib/test/test_tuple.py
Lib/test/test_tuple.py
+29
-0
Modules/_collectionsmodule.c
Modules/_collectionsmodule.c
+91
-2
Modules/arraymodule.c
Modules/arraymodule.c
+29
-1
Modules/itertoolsmodule.c
Modules/itertoolsmodule.c
+837
-53
Objects/bytearrayobject.c
Objects/bytearrayobject.c
+34
-2
Objects/bytesobject.c
Objects/bytesobject.c
+34
-0
Objects/dictobject.c
Objects/dictobject.c
+53
-0
Objects/enumobject.c
Objects/enumobject.c
+49
-1
Objects/iterobject.c
Objects/iterobject.c
+59
-1
Objects/listobject.c
Objects/listobject.c
+80
-0
Objects/rangeobject.c
Objects/rangeobject.c
+92
-0
Objects/setobject.c
Objects/setobject.c
+43
-2
Objects/tupleobject.c
Objects/tupleobject.c
+31
-0
Objects/unicodeobject.c
Objects/unicodeobject.c
+34
-0
Python/bltinmodule.c
Python/bltinmodule.c
+53
-3
No files found.
Include/iterobject.h
View file @
31668b8f
...
...
@@ -18,6 +18,8 @@ PyAPI_FUNC(PyObject *) PySeqIter_New(PyObject *);
PyAPI_FUNC
(
PyObject
*
)
PyCallIter_New
(
PyObject
*
,
PyObject
*
);
PyAPI_FUNC
(
PyObject
*
)
_PyIter_GetBuiltin
(
const
char
*
iter
);
#ifdef __cplusplus
}
#endif
...
...
Lib/test/seq_tests.py
View file @
31668b8f
...
...
@@ -4,6 +4,7 @@ Tests common to tuple, list and UserList.UserList
import
unittest
import
sys
import
pickle
# Various iterables
# This is used for checking the constructor (here and in test_deque.py)
...
...
@@ -388,3 +389,9 @@ class CommonTest(unittest.TestCase):
self
.
assertEqual
(
a
.
index
(
0
,
-
4
*
sys
.
maxsize
,
4
*
sys
.
maxsize
),
2
)
self
.
assertRaises
(
ValueError
,
a
.
index
,
0
,
4
*
sys
.
maxsize
,
-
4
*
sys
.
maxsize
)
self
.
assertRaises
(
ValueError
,
a
.
index
,
2
,
0
,
-
10
)
def
test_pickle
(
self
):
lst
=
self
.
type2test
([
4
,
5
,
6
,
7
])
lst2
=
pickle
.
loads
(
pickle
.
dumps
(
lst
))
self
.
assertEqual
(
lst2
,
lst
)
self
.
assertNotEqual
(
id
(
lst2
),
id
(
lst
))
Lib/test/test_array.py
View file @
31668b8f
...
...
@@ -285,6 +285,20 @@ class BaseTest(unittest.TestCase):
self
.
assertEqual
(
a
.
x
,
b
.
x
)
self
.
assertEqual
(
type
(
a
),
type
(
b
))
def
test_iterator_pickle
(
self
):
data
=
array
.
array
(
self
.
typecode
,
self
.
example
)
orgit
=
iter
(
data
)
d
=
pickle
.
dumps
(
orgit
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
type
(
orgit
),
type
(
it
))
self
.
assertEqual
(
list
(
it
),
list
(
data
))
if
len
(
data
):
it
=
pickle
.
loads
(
d
)
next
(
it
)
d
=
pickle
.
dumps
(
it
)
self
.
assertEqual
(
list
(
it
),
list
(
data
)[
1
:])
def
test_insert
(
self
):
a
=
array
.
array
(
self
.
typecode
,
self
.
example
)
a
.
insert
(
0
,
self
.
example
[
0
])
...
...
Lib/test/test_builtin.py
View file @
31668b8f
...
...
@@ -14,6 +14,7 @@ import random
import
traceback
from
test.support
import
TESTFN
,
unlink
,
run_unittest
,
check_warnings
from
operator
import
neg
import
pickle
try
:
import
pty
,
signal
except
ImportError
:
...
...
@@ -110,7 +111,30 @@ class TestFailingIter:
def
__iter__
(
self
):
raise
RuntimeError
def
filter_char
(
arg
):
return
ord
(
arg
)
>
ord
(
"d"
)
def
map_char
(
arg
):
return
chr
(
ord
(
arg
)
+
1
)
class
BuiltinTest
(
unittest
.
TestCase
):
# Helper to check picklability
def
check_iter_pickle
(
self
,
it
,
seq
):
itorg
=
it
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
type
(
itorg
),
type
(
it
))
self
.
assertEqual
(
list
(
it
),
seq
)
#test the iterator after dropping one from it
it
=
pickle
.
loads
(
d
)
try
:
next
(
it
)
except
StopIteration
:
return
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
list
(
it
),
seq
[
1
:])
def
test_import
(
self
):
__import__
(
'sys'
)
...
...
@@ -566,6 +590,11 @@ class BuiltinTest(unittest.TestCase):
self
.
assertEqual
(
list
(
filter
(
lambda
x
:
x
>=
3
,
(
1
,
2
,
3
,
4
))),
[
3
,
4
])
self
.
assertRaises
(
TypeError
,
list
,
filter
(
42
,
(
1
,
2
)))
def
test_filter_pickle
(
self
):
f1
=
filter
(
filter_char
,
"abcdeabcde"
)
f2
=
filter
(
filter_char
,
"abcdeabcde"
)
self
.
check_iter_pickle
(
f1
,
list
(
f2
))
def
test_getattr
(
self
):
self
.
assertTrue
(
getattr
(
sys
,
'stdout'
)
is
sys
.
stdout
)
self
.
assertRaises
(
TypeError
,
getattr
,
sys
,
1
)
...
...
@@ -759,6 +788,11 @@ class BuiltinTest(unittest.TestCase):
raise
RuntimeError
self
.
assertRaises
(
RuntimeError
,
list
,
map
(
badfunc
,
range
(
5
)))
def
test_map_pickle
(
self
):
m1
=
map
(
map_char
,
"Is this the real life?"
)
m2
=
map
(
map_char
,
"Is this the real life?"
)
self
.
check_iter_pickle
(
m1
,
list
(
m2
))
def
test_max
(
self
):
self
.
assertEqual
(
max
(
'123123'
),
'3'
)
self
.
assertEqual
(
max
(
1
,
2
,
3
),
3
)
...
...
@@ -1300,6 +1334,13 @@ class BuiltinTest(unittest.TestCase):
return
i
self
.
assertRaises
(
ValueError
,
list
,
zip
(
BadSeq
(),
BadSeq
()))
def
test_zip_pickle
(
self
):
a
=
(
1
,
2
,
3
)
b
=
(
4
,
5
,
6
)
t
=
[(
1
,
4
),
(
2
,
5
),
(
3
,
6
)]
z1
=
zip
(
a
,
b
)
self
.
check_iter_pickle
(
z1
,
t
)
def
test_format
(
self
):
# Test the basic machinery of the format() builtin. Don't test
# the specifics of the various formatters
...
...
Lib/test/test_bytes.py
View file @
31668b8f
...
...
@@ -518,6 +518,24 @@ class BaseBytesTest(unittest.TestCase):
q = pickle.loads(ps)
self.assertEqual(b, q)
def test_iterator_pickling(self):
for b in b"", b"a", b"abc", b"
\
xff
ab
\
x80
", b"
\
0
\
0
\
377
\
0
\
0
":
it = itorg = iter(self.type2test(b))
data = list(self.type2test(b))
d = pickle.dumps(it)
it = pickle.loads(d)
self.assertEqual(type(itorg), type(it))
self.assertEqual(list(it), data)
it = pickle.loads(d)
try:
next(it)
except StopIteration:
continue
d = pickle.dumps(it)
it = pickle.loads(d)
self.assertEqual(list(it), data[1:])
def test_strip(self):
b = self.type2test(b'
mississippi
')
self.assertEqual(b.strip(b'
i
'), b'
mississipp
')
...
...
Lib/test/test_deque.py
View file @
31668b8f
...
...
@@ -471,6 +471,19 @@ class TestBasic(unittest.TestCase):
## self.assertNotEqual(id(d), id(e))
## self.assertEqual(id(e), id(e[-1]))
def
test_iterator_pickle
(
self
):
data
=
deque
(
range
(
200
))
it
=
itorg
=
iter
(
data
)
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
type
(
itorg
),
type
(
it
))
self
.
assertEqual
(
list
(
it
),
list
(
data
))
it
=
pickle
.
loads
(
d
)
next
(
it
)
d
=
pickle
.
dumps
(
it
)
self
.
assertEqual
(
list
(
it
),
list
(
data
)[
1
:])
def
test_deepcopy
(
self
):
mut
=
[
10
]
d
=
deque
([
mut
])
...
...
Lib/test/test_dict.py
View file @
31668b8f
...
...
@@ -2,7 +2,9 @@ import unittest
from
test
import
support
import
collections
,
random
,
string
import
collections.abc
import
gc
,
weakref
import
pickle
class
DictTest
(
unittest
.
TestCase
):
...
...
@@ -803,6 +805,58 @@ class DictTest(unittest.TestCase):
pass
self
.
_tracked
(
MyDict
())
def
test_iterator_pickling
(
self
):
data
=
{
1
:
"a"
,
2
:
"b"
,
3
:
"c"
}
it
=
iter
(
data
)
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
sorted
(
it
),
sorted
(
data
))
it
=
pickle
.
loads
(
d
)
try
:
drop
=
next
(
it
)
except
StopIteration
:
return
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
del
data
[
drop
]
self
.
assertEqual
(
sorted
(
it
),
sorted
(
data
))
def
test_itemiterator_pickling
(
self
):
data
=
{
1
:
"a"
,
2
:
"b"
,
3
:
"c"
}
# dictviews aren't picklable, only their iterators
itorg
=
iter
(
data
.
items
())
d
=
pickle
.
dumps
(
itorg
)
it
=
pickle
.
loads
(
d
)
# note that the type of type of the unpickled iterator
# is not necessarily the same as the original. It is
# merely an object supporting the iterator protocol, yielding
# the same objects as the original one.
# self.assertEqual(type(itorg), type(it))
self
.
assertTrue
(
isinstance
(
it
,
collections
.
abc
.
Iterator
))
self
.
assertEqual
(
dict
(
it
),
data
)
it
=
pickle
.
loads
(
d
)
drop
=
next
(
it
)
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
del
data
[
drop
[
0
]]
self
.
assertEqual
(
dict
(
it
),
data
)
def
test_valuesiterator_pickling
(
self
):
data
=
{
1
:
"a"
,
2
:
"b"
,
3
:
"c"
}
# data.values() isn't picklable, only its iterator
it
=
iter
(
data
.
values
())
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
sorted
(
list
(
it
)),
sorted
(
list
(
data
.
values
())))
it
=
pickle
.
loads
(
d
)
drop
=
next
(
it
)
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
values
=
list
(
it
)
+
[
drop
]
self
.
assertEqual
(
sorted
(
values
),
sorted
(
list
(
data
.
values
())))
from
test
import
mapping_tests
...
...
Lib/test/test_enumerate.py
View file @
31668b8f
import
unittest
import
sys
import
pickle
from
test
import
support
...
...
@@ -61,7 +62,25 @@ class N:
def
__iter__
(
self
):
return
self
class
EnumerateTestCase
(
unittest
.
TestCase
):
class
PickleTest
:
# Helper to check picklability
def
check_pickle
(
self
,
itorg
,
seq
):
d
=
pickle
.
dumps
(
itorg
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
type
(
itorg
),
type
(
it
))
self
.
assertEqual
(
list
(
it
),
seq
)
it
=
pickle
.
loads
(
d
)
try
:
next
(
it
)
except
StopIteration
:
self
.
assertFalse
(
seq
[
1
:])
return
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
list
(
it
),
seq
[
1
:])
class
EnumerateTestCase
(
unittest
.
TestCase
,
PickleTest
):
enum
=
enumerate
seq
,
res
=
'abc'
,
[(
0
,
'a'
),
(
1
,
'b'
),
(
2
,
'c'
)]
...
...
@@ -73,6 +92,9 @@ class EnumerateTestCase(unittest.TestCase):
self
.
assertEqual
(
list
(
self
.
enum
(
self
.
seq
)),
self
.
res
)
self
.
enum
.
__doc__
def
test_pickle
(
self
):
self
.
check_pickle
(
self
.
enum
(
self
.
seq
),
self
.
res
)
def
test_getitemseqn
(
self
):
self
.
assertEqual
(
list
(
self
.
enum
(
G
(
self
.
seq
))),
self
.
res
)
e
=
self
.
enum
(
G
(
''
))
...
...
@@ -126,7 +148,7 @@ class TestBig(EnumerateTestCase):
seq
=
range
(
10
,
20000
,
2
)
res
=
list
(
zip
(
range
(
20000
),
seq
))
class
TestReversed
(
unittest
.
TestCase
):
class
TestReversed
(
unittest
.
TestCase
,
PickleTest
):
def
test_simple
(
self
):
class
A
:
...
...
@@ -212,6 +234,10 @@ class TestReversed(unittest.TestCase):
ngi
=
NoGetItem
()
self
.
assertRaises
(
TypeError
,
reversed
,
ngi
)
def
test_pickle
(
self
):
for
data
in
'abc'
,
range
(
5
),
tuple
(
enumerate
(
'abc'
)),
range
(
1
,
17
,
5
):
self
.
check_pickle
(
reversed
(
data
),
list
(
data
)[::
-
1
])
class
EnumerateStartTestCase
(
EnumerateTestCase
):
...
...
Lib/test/test_iter.py
View file @
31668b8f
...
...
@@ -2,6 +2,8 @@
import
unittest
from
test.support
import
run_unittest
,
TESTFN
,
unlink
,
cpython_only
import
pickle
import
collections.abc
# Test result of triple loop (too big to inline)
TRIPLETS
=
[(
0
,
0
,
0
),
(
0
,
0
,
1
),
(
0
,
0
,
2
),
...
...
@@ -28,6 +30,8 @@ class BasicIterClass:
raise
StopIteration
self
.
i
=
res
+
1
return
res
def
__iter__
(
self
):
return
self
class
IteratingSequenceClass
:
def
__init__
(
self
,
n
):
...
...
@@ -49,7 +53,9 @@ class SequenceClass:
class
TestCase
(
unittest
.
TestCase
):
# Helper to check that an iterator returns a given sequence
def
check_iterator
(
self
,
it
,
seq
):
def
check_iterator
(
self
,
it
,
seq
,
pickle
=
True
):
if
pickle
:
self
.
check_pickle
(
it
,
seq
)
res
=
[]
while
1
:
try
:
...
...
@@ -60,12 +66,33 @@ class TestCase(unittest.TestCase):
self
.
assertEqual
(
res
,
seq
)
# Helper to check that a for loop generates a given sequence
def
check_for_loop
(
self
,
expr
,
seq
):
def
check_for_loop
(
self
,
expr
,
seq
,
pickle
=
True
):
if
pickle
:
self
.
check_pickle
(
iter
(
expr
),
seq
)
res
=
[]
for
val
in
expr
:
res
.
append
(
val
)
self
.
assertEqual
(
res
,
seq
)
# Helper to check picklability
def
check_pickle
(
self
,
itorg
,
seq
):
d
=
pickle
.
dumps
(
itorg
)
it
=
pickle
.
loads
(
d
)
# Cannot assert type equality because dict iterators unpickle as list
# iterators.
# self.assertEqual(type(itorg), type(it))
self
.
assertTrue
(
isinstance
(
it
,
collections
.
abc
.
Iterator
))
self
.
assertEqual
(
list
(
it
),
seq
)
it
=
pickle
.
loads
(
d
)
try
:
next
(
it
)
except
StopIteration
:
return
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
list
(
it
),
seq
[
1
:])
# Test basic use of iter() function
def
test_iter_basic
(
self
):
self
.
check_iterator
(
iter
(
range
(
10
)),
list
(
range
(
10
)))
...
...
@@ -138,7 +165,7 @@ class TestCase(unittest.TestCase):
if
i
>
100
:
raise
IndexError
# Emergency stop
return
i
self
.
check_iterator
(
iter
(
C
(),
10
),
list
(
range
(
10
)))
self
.
check_iterator
(
iter
(
C
(),
10
),
list
(
range
(
10
))
,
pickle
=
False
)
# Test two-argument iter() with function
def
test_iter_function
(
self
):
...
...
@@ -146,7 +173,7 @@ class TestCase(unittest.TestCase):
i
=
state
[
0
]
state
[
0
]
=
i
+
1
return
i
self
.
check_iterator
(
iter
(
spam
,
10
),
list
(
range
(
10
)))
self
.
check_iterator
(
iter
(
spam
,
10
),
list
(
range
(
10
))
,
pickle
=
False
)
# Test two-argument iter() with function that raises StopIteration
def
test_iter_function_stop
(
self
):
...
...
@@ -156,7 +183,7 @@ class TestCase(unittest.TestCase):
raise
StopIteration
state
[
0
]
=
i
+
1
return
i
self
.
check_iterator
(
iter
(
spam
,
20
),
list
(
range
(
10
)))
self
.
check_iterator
(
iter
(
spam
,
20
),
list
(
range
(
10
))
,
pickle
=
False
)
# Test exception propagation through function iterator
def
test_exception_function
(
self
):
...
...
@@ -198,7 +225,7 @@ class TestCase(unittest.TestCase):
if
i
==
10
:
raise
StopIteration
return
SequenceClass
.
__getitem__
(
self
,
i
)
self
.
check_for_loop
(
MySequenceClass
(
20
),
list
(
range
(
10
)))
self
.
check_for_loop
(
MySequenceClass
(
20
),
list
(
range
(
10
))
,
pickle
=
False
)
# Test a big range
def
test_iter_big_range
(
self
):
...
...
@@ -237,8 +264,8 @@ class TestCase(unittest.TestCase):
f
.
close
()
f
=
open
(
TESTFN
,
"r"
)
try
:
self
.
check_for_loop
(
f
,
[
"0
\
n
"
,
"1
\
n
"
,
"2
\
n
"
,
"3
\
n
"
,
"4
\
n
"
])
self
.
check_for_loop
(
f
,
[])
self
.
check_for_loop
(
f
,
[
"0
\
n
"
,
"1
\
n
"
,
"2
\
n
"
,
"3
\
n
"
,
"4
\
n
"
]
,
pickle
=
False
)
self
.
check_for_loop
(
f
,
[]
,
pickle
=
False
)
finally
:
f
.
close
()
try
:
...
...
Lib/test/test_itertools.py
View file @
31668b8f
This diff is collapsed.
Click to expand it.
Lib/test/test_list.py
View file @
31668b8f
import
sys
from
test
import
support
,
list_tests
import
pickle
class
ListTest
(
list_tests
.
CommonTest
):
type2test
=
list
...
...
@@ -69,6 +70,33 @@ class ListTest(list_tests.CommonTest):
check
(
10
)
# check our checking code
check
(
1000000
)
def
test_iterator_pickle
(
self
):
# Userlist iterators don't support pickling yet since
# they are based on generators.
data
=
self
.
type2test
([
4
,
5
,
6
,
7
])
it
=
itorg
=
iter
(
data
)
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
type
(
itorg
),
type
(
it
))
self
.
assertEqual
(
self
.
type2test
(
it
),
self
.
type2test
(
data
))
it
=
pickle
.
loads
(
d
)
next
(
it
)
d
=
pickle
.
dumps
(
it
)
self
.
assertEqual
(
self
.
type2test
(
it
),
self
.
type2test
(
data
)[
1
:])
def
test_reversed_pickle
(
self
):
data
=
self
.
type2test
([
4
,
5
,
6
,
7
])
it
=
itorg
=
reversed
(
data
)
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
type
(
itorg
),
type
(
it
))
self
.
assertEqual
(
self
.
type2test
(
it
),
self
.
type2test
(
reversed
(
data
)))
it
=
pickle
.
loads
(
d
)
next
(
it
)
d
=
pickle
.
dumps
(
it
)
self
.
assertEqual
(
self
.
type2test
(
it
),
self
.
type2test
(
reversed
(
data
))[
1
:])
def
test_main
(
verbose
=
None
):
support
.
run_unittest
(
ListTest
)
...
...
Lib/test/test_range.py
View file @
31668b8f
...
...
@@ -341,13 +341,35 @@ class RangeTest(unittest.TestCase):
def
test_pickling
(
self
):
testcases
=
[(
13
,),
(
0
,
11
),
(
-
22
,
10
),
(
20
,
3
,
-
1
),
(
13
,
21
,
3
),
(
-
2
,
2
,
2
)]
(
13
,
21
,
3
),
(
-
2
,
2
,
2
)
,
(
2
**
65
,
2
**
65
+
2
)
]
for
proto
in
range
(
pickle
.
HIGHEST_PROTOCOL
+
1
):
for
t
in
testcases
:
r
=
range
(
*
t
)
self
.
assertEqual
(
list
(
pickle
.
loads
(
pickle
.
dumps
(
r
,
proto
))),
list
(
r
))
def
test_iterator_pickling
(
self
):
testcases
=
[(
13
,),
(
0
,
11
),
(
-
22
,
10
),
(
20
,
3
,
-
1
),
(
13
,
21
,
3
),
(
-
2
,
2
,
2
),
(
2
**
65
,
2
**
65
+
2
)]
for
proto
in
range
(
pickle
.
HIGHEST_PROTOCOL
+
1
):
for
t
in
testcases
:
it
=
itorg
=
iter
(
range
(
*
t
))
data
=
list
(
range
(
*
t
))
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
type
(
itorg
),
type
(
it
))
self
.
assertEqual
(
list
(
it
),
data
)
it
=
pickle
.
loads
(
d
)
try
:
next
(
it
)
except
StopIteration
:
continue
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
list
(
it
),
data
[
1
:])
def
test_odd_bug
(
self
):
# This used to raise a "SystemError: NULL result without error"
# because the range validation step was eating the exception
...
...
Lib/test/test_set.py
View file @
31668b8f
...
...
@@ -9,6 +9,7 @@ from random import randrange, shuffle
import
sys
import
warnings
import
collections
import
collections.abc
class
PassThru
(
Exception
):
pass
...
...
@@ -234,6 +235,26 @@ class TestJointOps(unittest.TestCase):
dup
=
pickle
.
loads
(
p
)
self
.
assertEqual
(
self
.
s
.
x
,
dup
.
x
)
def
test_iterator_pickling
(
self
):
itorg
=
iter
(
self
.
s
)
data
=
self
.
thetype
(
self
.
s
)
d
=
pickle
.
dumps
(
itorg
)
it
=
pickle
.
loads
(
d
)
# Set iterators unpickle as list iterators due to the
# undefined order of set items.
# self.assertEqual(type(itorg), type(it))
self
.
assertTrue
(
isinstance
(
it
,
collections
.
abc
.
Iterator
))
self
.
assertEqual
(
self
.
thetype
(
it
),
data
)
it
=
pickle
.
loads
(
d
)
try
:
drop
=
next
(
it
)
except
StopIteration
:
return
d
=
pickle
.
dumps
(
it
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
self
.
thetype
(
it
),
data
-
self
.
thetype
((
drop
,)))
def
test_deepcopy
(
self
):
class
Tracer
:
def
__init__
(
self
,
value
):
...
...
Lib/test/test_tuple.py
View file @
31668b8f
from
test
import
support
,
seq_tests
import
gc
import
pickle
class
TupleTest
(
seq_tests
.
CommonTest
):
type2test
=
tuple
...
...
@@ -164,6 +165,34 @@ class TupleTest(seq_tests.CommonTest):
check
(
10
)
# check our checking code
check
(
1000000
)
def
test_iterator_pickle
(
self
):
# Userlist iterators don't support pickling yet since
# they are based on generators.
data
=
self
.
type2test
([
4
,
5
,
6
,
7
])
itorg
=
iter
(
data
)
d
=
pickle
.
dumps
(
itorg
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
type
(
itorg
),
type
(
it
))
self
.
assertEqual
(
self
.
type2test
(
it
),
self
.
type2test
(
data
))
it
=
pickle
.
loads
(
d
)
next
(
it
)
d
=
pickle
.
dumps
(
it
)
self
.
assertEqual
(
self
.
type2test
(
it
),
self
.
type2test
(
data
)[
1
:])
def
test_reversed_pickle
(
self
):
data
=
self
.
type2test
([
4
,
5
,
6
,
7
])
itorg
=
reversed
(
data
)
d
=
pickle
.
dumps
(
itorg
)
it
=
pickle
.
loads
(
d
)
self
.
assertEqual
(
type
(
itorg
),
type
(
it
))
self
.
assertEqual
(
self
.
type2test
(
it
),
self
.
type2test
(
reversed
(
data
)))
it
=
pickle
.
loads
(
d
)
next
(
it
)
d
=
pickle
.
dumps
(
it
)
self
.
assertEqual
(
self
.
type2test
(
it
),
self
.
type2test
(
reversed
(
data
))[
1
:])
def
test_main
():
support
.
run_unittest
(
TupleTest
)
...
...
Modules/_collectionsmodule.c
View file @
31668b8f
...
...
@@ -1121,6 +1121,35 @@ dequeiter_next(dequeiterobject *it)
return
item
;
}
static
PyObject
*
dequeiter_new
(
PyTypeObject
*
type
,
PyObject
*
args
,
PyObject
*
kwds
)
{
Py_ssize_t
i
,
index
=
0
;
PyObject
*
deque
;
dequeiterobject
*
it
;
if
(
!
PyArg_ParseTuple
(
args
,
"O!|n"
,
&
deque_type
,
&
deque
,
&
index
))
return
NULL
;
assert
(
type
==
&
dequeiter_type
);
it
=
(
dequeiterobject
*
)
deque_iter
((
dequeobject
*
)
deque
);
if
(
!
it
)
return
NULL
;
/* consume items from the queue */
for
(
i
=
0
;
i
<
index
;
i
++
)
{
PyObject
*
item
=
dequeiter_next
(
it
);
if
(
item
)
{
Py_DECREF
(
item
);
}
else
{
if
(
it
->
counter
)
{
Py_DECREF
(
it
);
return
NULL
;
}
else
break
;
}
}
return
(
PyObject
*
)
it
;
}
static
PyObject
*
dequeiter_len
(
dequeiterobject
*
it
)
{
...
...
@@ -1129,14 +1158,21 @@ dequeiter_len(dequeiterobject *it)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
dequeiter_reduce
(
dequeiterobject
*
it
)
{
return
Py_BuildValue
(
"O(On)"
,
Py_TYPE
(
it
),
it
->
deque
,
it
->
deque
->
len
-
it
->
counter
);
}
static
PyMethodDef
dequeiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
dequeiter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
dequeiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
static
PyTypeObject
dequeiter_type
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"
deque_iterator"
,
/* tp_name */
"
_collections._deque_iterator"
,
/* tp_name */
sizeof
(
dequeiterobject
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
...
...
@@ -1164,6 +1200,16 @@ static PyTypeObject dequeiter_type = {
PyObject_SelfIter
,
/* tp_iter */
(
iternextfunc
)
dequeiter_next
,
/* tp_iternext */
dequeiter_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
0
,
/* tp_init */
0
,
/* tp_alloc */
dequeiter_new
,
/* tp_new */
0
,
};
...
...
@@ -1217,9 +1263,38 @@ dequereviter_next(dequeiterobject *it)
return
item
;
}
static
PyObject
*
dequereviter_new
(
PyTypeObject
*
type
,
PyObject
*
args
,
PyObject
*
kwds
)
{
Py_ssize_t
i
,
index
=
0
;
PyObject
*
deque
;
dequeiterobject
*
it
;
if
(
!
PyArg_ParseTuple
(
args
,
"O!|n"
,
&
deque_type
,
&
deque
,
&
index
))
return
NULL
;
assert
(
type
==
&
dequereviter_type
);
it
=
(
dequeiterobject
*
)
deque_reviter
((
dequeobject
*
)
deque
);
if
(
!
it
)
return
NULL
;
/* consume items from the queue */
for
(
i
=
0
;
i
<
index
;
i
++
)
{
PyObject
*
item
=
dequereviter_next
(
it
);
if
(
item
)
{
Py_DECREF
(
item
);
}
else
{
if
(
it
->
counter
)
{
Py_DECREF
(
it
);
return
NULL
;
}
else
break
;
}
}
return
(
PyObject
*
)
it
;
}
static
PyTypeObject
dequereviter_type
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"
deque_reverse_iterator"
,
/* tp_name */
"
_collections._deque_reverse_iterator"
,
/* tp_name */
sizeof
(
dequeiterobject
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
...
...
@@ -1247,6 +1322,16 @@ static PyTypeObject dequereviter_type = {
PyObject_SelfIter
,
/* tp_iter */
(
iternextfunc
)
dequereviter_next
,
/* tp_iternext */
dequeiter_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
0
,
/* tp_init */
0
,
/* tp_alloc */
dequereviter_new
,
/* tp_new */
0
,
};
...
...
@@ -1653,9 +1738,13 @@ PyInit__collections(void)
if
(
PyType_Ready
(
&
dequeiter_type
)
<
0
)
return
NULL
;
Py_INCREF
(
&
dequeiter_type
);
PyModule_AddObject
(
m
,
"_deque_iterator"
,
(
PyObject
*
)
&
dequeiter_type
);
if
(
PyType_Ready
(
&
dequereviter_type
)
<
0
)
return
NULL
;
Py_INCREF
(
&
dequereviter_type
);
PyModule_AddObject
(
m
,
"_deque_reverse_iterator"
,
(
PyObject
*
)
&
dequereviter_type
);
return
m
;
}
Modules/arraymodule.c
View file @
31668b8f
...
...
@@ -2753,6 +2753,34 @@ arrayiter_traverse(arrayiterobject *it, visitproc visit, void *arg)
return
0
;
}
static
PyObject
*
arrayiter_reduce
(
arrayiterobject
*
it
)
{
return
Py_BuildValue
(
"N(O)n"
,
_PyIter_GetBuiltin
(
"iter"
),
it
->
ao
,
it
->
index
);
}
static
PyObject
*
arrayiter_setstate
(
arrayiterobject
*
it
,
PyObject
*
state
)
{
Py_ssize_t
index
=
PyLong_AsSsize_t
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
index
<
0
)
index
=
0
;
it
->
index
=
index
;
Py_RETURN_NONE
;
}
PyDoc_STRVAR
(
setstate_doc
,
"Set state information for unpickling."
);
static
PyMethodDef
arrayiter_methods
[]
=
{
{
"__reduce__"
,
(
PyCFunction
)
arrayiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
arrayiter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
static
PyTypeObject
PyArrayIter_Type
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"arrayiterator"
,
/* tp_name */
...
...
@@ -2782,7 +2810,7 @@ static PyTypeObject PyArrayIter_Type = {
0
,
/* tp_weaklistoffset */
PyObject_SelfIter
,
/* tp_iter */
(
iternextfunc
)
arrayiter_next
,
/* tp_iternext */
0
,
/* tp_methods */
arrayiter_methods
,
/* tp_methods */
};
...
...
Modules/itertoolsmodule.c
View file @
31668b8f
This diff is collapsed.
Click to expand it.
Objects/bytearrayobject.c
View file @
31668b8f
...
...
@@ -3003,7 +3003,7 @@ bytearrayiter_next(bytesiterobject *it)
}
static
PyObject
*
byte
s
arrayiter_length_hint
(
bytesiterobject
*
it
)
bytearrayiter_length_hint
(
bytesiterobject
*
it
)
{
Py_ssize_t
len
=
0
;
if
(
it
->
it_seq
)
...
...
@@ -3014,9 +3014,41 @@ bytesarrayiter_length_hint(bytesiterobject *it)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
bytearrayiter_reduce
(
bytesiterobject
*
it
)
{
if
(
it
->
it_seq
!=
NULL
)
{
return
Py_BuildValue
(
"N(O)n"
,
_PyIter_GetBuiltin
(
"iter"
),
it
->
it_seq
,
it
->
it_index
);
}
else
{
PyObject
*
u
=
PyUnicode_FromUnicode
(
NULL
,
0
);
if
(
u
==
NULL
)
return
NULL
;
return
Py_BuildValue
(
"N(N)"
,
_PyIter_GetBuiltin
(
"iter"
),
u
);
}
}
static
PyObject
*
bytearrayiter_setstate
(
bytesiterobject
*
it
,
PyObject
*
state
)
{
Py_ssize_t
index
=
PyLong_AsSsize_t
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
index
<
0
)
index
=
0
;
it
->
it_index
=
index
;
Py_RETURN_NONE
;
}
PyDoc_STRVAR
(
setstate_doc
,
"Set state information for unpickling."
);
static
PyMethodDef
bytearrayiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
byte
s
arrayiter_length_hint
,
METH_NOARGS
,
{
"__length_hint__"
,
(
PyCFunction
)
bytearrayiter_length_hint
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
bytearrayiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
bytearrayiter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
Objects/bytesobject.c
View file @
31668b8f
...
...
@@ -3074,9 +3074,43 @@ striter_len(striterobject *it)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
striter_reduce
(
striterobject
*
it
)
{
if
(
it
->
it_seq
!=
NULL
)
{
return
Py_BuildValue
(
"N(O)n"
,
_PyIter_GetBuiltin
(
"iter"
),
it
->
it_seq
,
it
->
it_index
);
}
else
{
PyObject
*
u
=
PyUnicode_FromUnicode
(
NULL
,
0
);
if
(
u
==
NULL
)
return
NULL
;
return
Py_BuildValue
(
"N(N)"
,
_PyIter_GetBuiltin
(
"iter"
),
u
);
}
}
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
static
PyObject
*
striter_setstate
(
striterobject
*
it
,
PyObject
*
state
)
{
Py_ssize_t
index
=
PyLong_AsSsize_t
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
index
<
0
)
index
=
0
;
it
->
it_index
=
index
;
Py_RETURN_NONE
;
}
PyDoc_STRVAR
(
setstate_doc
,
"Set state information for unpickling."
);
static
PyMethodDef
striter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
striter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
striter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
striter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
Objects/dictobject.c
View file @
31668b8f
...
...
@@ -2323,9 +2323,16 @@ dictiter_len(dictiterobject *di)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
dictiter_reduce
(
dictiterobject
*
di
);
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
static
PyMethodDef
dictiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
dictiter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
dictiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -2560,6 +2567,52 @@ PyTypeObject PyDictIterItem_Type = {
};
static
PyObject
*
dictiter_reduce
(
dictiterobject
*
di
)
{
PyObject
*
list
;
dictiterobject
tmp
;
list
=
PyList_New
(
0
);
if
(
!
list
)
return
NULL
;
/* copy the itertor state */
tmp
=
*
di
;
Py_XINCREF
(
tmp
.
di_dict
);
/* iterate the temporary into a list */
for
(;;)
{
PyObject
*
element
=
0
;
if
(
Py_TYPE
(
di
)
==
&
PyDictIterItem_Type
)
element
=
dictiter_iternextitem
(
&
tmp
);
else
if
(
Py_TYPE
(
di
)
==
&
PyDictIterKey_Type
)
element
=
dictiter_iternextkey
(
&
tmp
);
else
if
(
Py_TYPE
(
di
)
==
&
PyDictIterValue_Type
)
element
=
dictiter_iternextvalue
(
&
tmp
);
else
assert
(
0
);
if
(
element
)
{
if
(
PyList_Append
(
list
,
element
))
{
Py_DECREF
(
element
);
Py_DECREF
(
list
);
Py_XDECREF
(
tmp
.
di_dict
);
return
NULL
;
}
Py_DECREF
(
element
);
}
else
break
;
}
Py_XDECREF
(
tmp
.
di_dict
);
/* check for error */
if
(
tmp
.
di_dict
!=
NULL
)
{
/* we have an error */
Py_DECREF
(
list
);
return
NULL
;
}
return
Py_BuildValue
(
"N(N)"
,
_PyIter_GetBuiltin
(
"iter"
),
list
);
}
/***********************************************/
/* View objects for keys(), items(), values(). */
/***********************************************/
...
...
Objects/enumobject.c
View file @
31668b8f
...
...
@@ -158,6 +158,22 @@ enum_next(enumobject *en)
return
result
;
}
static
PyObject
*
enum_reduce
(
enumobject
*
en
)
{
if
(
en
->
en_longindex
!=
NULL
)
return
Py_BuildValue
(
"O(OO)"
,
Py_TYPE
(
en
),
en
->
en_sit
,
en
->
en_longindex
);
else
return
Py_BuildValue
(
"O(On)"
,
Py_TYPE
(
en
),
en
->
en_sit
,
en
->
en_index
);
}
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
static
PyMethodDef
enum_methods
[]
=
{
{
"__reduce__"
,
(
PyCFunction
)
enum_reduce
,
METH_NOARGS
,
reduce_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
PyDoc_STRVAR
(
enum_doc
,
"enumerate(iterable[, start]) -> iterator for index, value of iterable
\n
"
"
\n
"
...
...
@@ -197,7 +213,7 @@ PyTypeObject PyEnum_Type = {
0
,
/* tp_weaklistoffset */
PyObject_SelfIter
,
/* tp_iter */
(
iternextfunc
)
enum_next
,
/* tp_iternext */
0
,
/* tp_methods */
enum_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
...
...
@@ -319,8 +335,40 @@ reversed_len(reversedobject *ro)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
reversed_reduce
(
reversedobject
*
ro
)
{
if
(
ro
->
seq
)
return
Py_BuildValue
(
"O(O)n"
,
Py_TYPE
(
ro
),
ro
->
seq
,
ro
->
index
);
else
return
Py_BuildValue
(
"O(())"
,
Py_TYPE
(
ro
));
}
static
PyObject
*
reversed_setstate
(
reversedobject
*
ro
,
PyObject
*
state
)
{
Py_ssize_t
index
=
PyLong_AsSsize_t
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
ro
->
seq
!=
0
)
{
Py_ssize_t
n
=
PySequence_Size
(
ro
->
seq
);
if
(
n
<
0
)
return
NULL
;
if
(
index
<
-
1
)
index
=
-
1
;
else
if
(
index
>
n
-
1
)
index
=
n
-
1
;
ro
->
index
=
index
;
}
Py_RETURN_NONE
;
}
PyDoc_STRVAR
(
setstate_doc
,
"Set state information for unpickling."
);
static
PyMethodDef
reversediter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
reversed_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
reversed_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
reversed_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
Objects/iterobject.c
View file @
31668b8f
...
...
@@ -2,6 +2,19 @@
#include "Python.h"
/* Convenience function to get builtins.iter or builtins.reversed */
PyObject
*
_PyIter_GetBuiltin
(
const
char
*
iter
)
{
PyObject
*
mod
,
*
attr
;
mod
=
PyImport_ImportModule
(
"builtins"
);
if
(
mod
==
NULL
)
return
NULL
;
attr
=
PyObject_GetAttrString
(
mod
,
iter
);
Py_DECREF
(
mod
);
return
attr
;
}
typedef
struct
{
PyObject_HEAD
long
it_index
;
...
...
@@ -88,8 +101,38 @@ iter_len(seqiterobject *it)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
iter_reduce
(
seqiterobject
*
it
)
{
if
(
it
->
it_seq
!=
NULL
)
return
Py_BuildValue
(
"N(O)n"
,
_PyIter_GetBuiltin
(
"iter"
),
it
->
it_seq
,
it
->
it_index
);
else
return
Py_BuildValue
(
"N(())"
,
_PyIter_GetBuiltin
(
"iter"
));
}
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
static
PyObject
*
iter_setstate
(
seqiterobject
*
it
,
PyObject
*
state
)
{
Py_ssize_t
index
=
PyLong_AsSsize_t
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
it
->
it_seq
!=
NULL
)
{
if
(
index
<
0
)
index
=
0
;
it
->
it_index
=
index
;
}
Py_RETURN_NONE
;
}
PyDoc_STRVAR
(
setstate_doc
,
"Set state information for unpickling."
);
static
PyMethodDef
seqiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
iter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
iter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
iter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -195,6 +238,21 @@ calliter_iternext(calliterobject *it)
return
NULL
;
}
static
PyObject
*
calliter_reduce
(
calliterobject
*
it
)
{
if
(
it
->
it_callable
!=
NULL
&&
it
->
it_sentinel
!=
NULL
)
return
Py_BuildValue
(
"N(OO)"
,
_PyIter_GetBuiltin
(
"iter"
),
it
->
it_callable
,
it
->
it_sentinel
);
else
return
Py_BuildValue
(
"N(())"
,
_PyIter_GetBuiltin
(
"iter"
));
}
static
PyMethodDef
calliter_methods
[]
=
{
{
"__reduce__"
,
(
PyCFunction
)
calliter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
PyTypeObject
PyCallIter_Type
=
{
PyVarObject_HEAD_INIT
(
&
PyType_Type
,
0
)
"callable_iterator"
,
/* tp_name */
...
...
@@ -224,7 +282,7 @@ PyTypeObject PyCallIter_Type = {
0
,
/* tp_weaklistoffset */
PyObject_SelfIter
,
/* tp_iter */
(
iternextfunc
)
calliter_iternext
,
/* tp_iternext */
0
,
/* tp_methods */
calliter_methods
,
/* tp_methods */
};
Objects/listobject.c
View file @
31668b8f
...
...
@@ -2660,11 +2660,18 @@ static void listiter_dealloc(listiterobject *);
static
int
listiter_traverse
(
listiterobject
*
,
visitproc
,
void
*
);
static
PyObject
*
listiter_next
(
listiterobject
*
);
static
PyObject
*
listiter_len
(
listiterobject
*
);
static
PyObject
*
listiter_reduce_general
(
void
*
_it
,
int
forward
);
static
PyObject
*
listiter_reduce
(
listiterobject
*
);
static
PyObject
*
listiter_setstate
(
listiterobject
*
,
PyObject
*
state
);
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
PyDoc_STRVAR
(
setstate_doc
,
"Set state information for unpickling."
);
static
PyMethodDef
listiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
listiter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
listiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
listiter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -2771,6 +2778,27 @@ listiter_len(listiterobject *it)
}
return
PyLong_FromLong
(
0
);
}
static
PyObject
*
listiter_reduce
(
listiterobject
*
it
)
{
return
listiter_reduce_general
(
it
,
1
);
}
static
PyObject
*
listiter_setstate
(
listiterobject
*
it
,
PyObject
*
state
)
{
long
index
=
PyLong_AsLong
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
it
->
it_seq
!=
NULL
)
{
if
(
index
<
0
)
index
=
0
;
it
->
it_index
=
index
;
}
Py_RETURN_NONE
;
}
/*********************** List Reverse Iterator **************************/
typedef
struct
{
...
...
@@ -2784,9 +2812,13 @@ static void listreviter_dealloc(listreviterobject *);
static
int
listreviter_traverse
(
listreviterobject
*
,
visitproc
,
void
*
);
static
PyObject
*
listreviter_next
(
listreviterobject
*
);
static
PyObject
*
listreviter_len
(
listreviterobject
*
);
static
PyObject
*
listreviter_reduce
(
listreviterobject
*
);
static
PyObject
*
listreviter_setstate
(
listreviterobject
*
,
PyObject
*
);
static
PyMethodDef
listreviter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
listreviter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
listreviter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
listreviter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -2883,3 +2915,51 @@ listreviter_len(listreviterobject *it)
len
=
0
;
return
PyLong_FromSsize_t
(
len
);
}
static
PyObject
*
listreviter_reduce
(
listreviterobject
*
it
)
{
return
listiter_reduce_general
(
it
,
0
);
}
static
PyObject
*
listreviter_setstate
(
listreviterobject
*
it
,
PyObject
*
state
)
{
Py_ssize_t
index
=
PyLong_AsSsize_t
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
it
->
it_seq
!=
NULL
)
{
if
(
index
<
-
1
)
index
=
-
1
;
else
if
(
index
>
PyList_GET_SIZE
(
it
->
it_seq
)
-
1
)
index
=
PyList_GET_SIZE
(
it
->
it_seq
)
-
1
;
it
->
it_index
=
index
;
}
Py_RETURN_NONE
;
}
/* common pickling support */
static
PyObject
*
listiter_reduce_general
(
void
*
_it
,
int
forward
)
{
PyObject
*
list
;
/* the objects are not the same, index is of different types! */
if
(
forward
)
{
listiterobject
*
it
=
(
listiterobject
*
)
_it
;
if
(
it
->
it_seq
)
return
Py_BuildValue
(
"N(O)l"
,
_PyIter_GetBuiltin
(
"iter"
),
it
->
it_seq
,
it
->
it_index
);
}
else
{
listreviterobject
*
it
=
(
listreviterobject
*
)
_it
;
if
(
it
->
it_seq
)
return
Py_BuildValue
(
"N(O)n"
,
_PyIter_GetBuiltin
(
"reversed"
),
it
->
it_seq
,
it
->
it_index
);
}
/* empty iterator, create an empty list */
list
=
PyList_New
(
0
);
if
(
list
==
NULL
)
return
NULL
;
return
Py_BuildValue
(
"N(N)"
,
_PyIter_GetBuiltin
(
"iter"
),
list
);
}
Objects/rangeobject.c
View file @
31668b8f
...
...
@@ -964,9 +964,59 @@ rangeiter_len(rangeiterobject *r)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
rangeiter_reduce
(
rangeiterobject
*
r
)
{
PyObject
*
start
=
NULL
,
*
stop
=
NULL
,
*
step
=
NULL
;
PyObject
*
range
;
/* create a range object for pickling */
start
=
PyLong_FromLong
(
r
->
start
);
if
(
start
==
NULL
)
goto
err
;
stop
=
PyLong_FromLong
(
r
->
start
+
r
->
len
*
r
->
step
);
if
(
stop
==
NULL
)
goto
err
;
step
=
PyLong_FromLong
(
r
->
step
);
if
(
step
==
NULL
)
goto
err
;
range
=
(
PyObject
*
)
make_range_object
(
&
PyRange_Type
,
start
,
stop
,
step
);
if
(
range
==
NULL
)
goto
err
;
/* return the result */
return
Py_BuildValue
(
"N(N)i"
,
_PyIter_GetBuiltin
(
"iter"
),
range
,
r
->
index
);
err:
Py_XDECREF
(
start
);
Py_XDECREF
(
stop
);
Py_XDECREF
(
step
);
return
NULL
;
}
static
PyObject
*
rangeiter_setstate
(
rangeiterobject
*
r
,
PyObject
*
state
)
{
long
index
=
PyLong_AsLong
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
index
<
0
||
index
>=
r
->
len
)
{
PyErr_SetString
(
PyExc_ValueError
,
"index out of range"
);
return
NULL
;
}
r
->
index
=
index
;
Py_RETURN_NONE
;
}
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
PyDoc_STRVAR
(
setstate_doc
,
"Set state information for unpickling."
);
static
PyMethodDef
rangeiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
rangeiter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
rangeiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
rangeiter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -1095,9 +1145,51 @@ longrangeiter_len(longrangeiterobject *r, PyObject *no_args)
return
PyNumber_Subtract
(
r
->
len
,
r
->
index
);
}
static
PyObject
*
longrangeiter_reduce
(
longrangeiterobject
*
r
)
{
PyObject
*
product
,
*
stop
=
NULL
;
PyObject
*
range
;
/* create a range object for pickling. Must calculate the "stop" value */
product
=
PyNumber_Multiply
(
r
->
len
,
r
->
step
);
if
(
product
==
NULL
)
return
NULL
;
stop
=
PyNumber_Add
(
r
->
start
,
product
);
Py_DECREF
(
product
);
if
(
stop
==
NULL
)
return
NULL
;
Py_INCREF
(
r
->
start
);
Py_INCREF
(
r
->
step
);
range
=
(
PyObject
*
)
make_range_object
(
&
PyRange_Type
,
r
->
start
,
stop
,
r
->
step
);
if
(
range
==
NULL
)
{
Py_DECREF
(
r
->
start
);
Py_DECREF
(
stop
);
Py_DECREF
(
r
->
step
);
return
NULL
;
}
/* return the result */
return
Py_BuildValue
(
"N(N)O"
,
_PyIter_GetBuiltin
(
"iter"
),
range
,
r
->
index
);
}
static
PyObject
*
longrangeiter_setstate
(
longrangeiterobject
*
r
,
PyObject
*
state
)
{
Py_CLEAR
(
r
->
index
);
r
->
index
=
state
;
Py_INCREF
(
r
->
index
);
Py_RETURN_NONE
;
}
static
PyMethodDef
longrangeiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
longrangeiter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
longrangeiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
longrangeiter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
Objects/setobject.c
View file @
31668b8f
...
...
@@ -819,8 +819,51 @@ setiter_len(setiterobject *si)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
setiter_iternext
(
setiterobject
*
si
);
static
PyObject
*
setiter_reduce
(
setiterobject
*
si
)
{
PyObject
*
list
;
setiterobject
tmp
;
list
=
PyList_New
(
0
);
if
(
!
list
)
return
NULL
;
/* copy the itertor state */
tmp
=
*
si
;
Py_XINCREF
(
tmp
.
si_set
);
/* iterate the temporary into a list */
for
(;;)
{
PyObject
*
element
=
setiter_iternext
(
&
tmp
);
if
(
element
)
{
if
(
PyList_Append
(
list
,
element
))
{
Py_DECREF
(
element
);
Py_DECREF
(
list
);
Py_XDECREF
(
tmp
.
si_set
);
return
NULL
;
}
Py_DECREF
(
element
);
}
else
break
;
}
Py_XDECREF
(
tmp
.
si_set
);
/* check for error */
if
(
tmp
.
si_set
!=
NULL
)
{
/* we have an error */
Py_DECREF
(
list
);
return
NULL
;
}
return
Py_BuildValue
(
"N(N)"
,
_PyIter_GetBuiltin
(
"iter"
),
list
);
}
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
static
PyMethodDef
setiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
setiter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
setiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
@@ -1964,8 +2007,6 @@ done:
return
result
;
}
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
static
PyObject
*
set_sizeof
(
PySetObject
*
so
)
{
...
...
Objects/tupleobject.c
View file @
31668b8f
...
...
@@ -967,8 +967,39 @@ tupleiter_len(tupleiterobject *it)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
tupleiter_reduce
(
tupleiterobject
*
it
)
{
if
(
it
->
it_seq
)
return
Py_BuildValue
(
"N(O)l"
,
_PyIter_GetBuiltin
(
"iter"
),
it
->
it_seq
,
it
->
it_index
);
else
return
Py_BuildValue
(
"N(())"
,
_PyIter_GetBuiltin
(
"iter"
));
}
static
PyObject
*
tupleiter_setstate
(
tupleiterobject
*
it
,
PyObject
*
state
)
{
long
index
=
PyLong_AsLong
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
it
->
it_seq
!=
NULL
)
{
if
(
index
<
0
)
index
=
0
;
else
if
(
it
->
it_seq
!=
NULL
&&
index
>
PyTuple_GET_SIZE
(
it
->
it_seq
))
index
=
PyTuple_GET_SIZE
(
it
->
it_seq
);
it
->
it_index
=
index
;
}
Py_RETURN_NONE
;
}
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
PyDoc_STRVAR
(
setstate_doc
,
"Set state information for unpickling."
);
static
PyMethodDef
tupleiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
tupleiter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
tupleiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
tupleiter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
Objects/unicodeobject.c
View file @
31668b8f
...
...
@@ -14382,9 +14382,43 @@ unicodeiter_len(unicodeiterobject *it)
PyDoc_STRVAR
(
length_hint_doc
,
"Private method returning an estimate of len(list(it))."
);
static
PyObject
*
unicodeiter_reduce
(
unicodeiterobject
*
it
)
{
if
(
it
->
it_seq
!=
NULL
)
{
return
Py_BuildValue
(
"N(O)n"
,
_PyIter_GetBuiltin
(
"iter"
),
it
->
it_seq
,
it
->
it_index
);
}
else
{
PyObject
*
u
=
PyUnicode_FromUnicode
(
NULL
,
0
);
if
(
u
==
NULL
)
return
NULL
;
return
Py_BuildValue
(
"N(N)"
,
_PyIter_GetBuiltin
(
"iter"
),
u
);
}
}
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
static
PyObject
*
unicodeiter_setstate
(
unicodeiterobject
*
it
,
PyObject
*
state
)
{
Py_ssize_t
index
=
PyLong_AsSsize_t
(
state
);
if
(
index
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
if
(
index
<
0
)
index
=
0
;
it
->
it_index
=
index
;
Py_RETURN_NONE
;
}
PyDoc_STRVAR
(
setstate_doc
,
"Set state information for unpickling."
);
static
PyMethodDef
unicodeiter_methods
[]
=
{
{
"__length_hint__"
,
(
PyCFunction
)
unicodeiter_len
,
METH_NOARGS
,
length_hint_doc
},
{
"__reduce__"
,
(
PyCFunction
)
unicodeiter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
"__setstate__"
,
(
PyCFunction
)
unicodeiter_setstate
,
METH_O
,
setstate_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
...
...
Python/bltinmodule.c
View file @
31668b8f
...
...
@@ -438,6 +438,19 @@ filter_next(filterobject *lz)
}
}
static
PyObject
*
filter_reduce
(
filterobject
*
lz
)
{
return
Py_BuildValue
(
"O(OO)"
,
Py_TYPE
(
lz
),
lz
->
func
,
lz
->
it
);
}
PyDoc_STRVAR
(
reduce_doc
,
"Return state information for pickling."
);
static
PyMethodDef
filter_methods
[]
=
{
{
"__reduce__"
,
(
PyCFunction
)
filter_reduce
,
METH_NOARGS
,
reduce_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
PyDoc_STRVAR
(
filter_doc
,
"filter(function or None, iterable) --> filter object
\n
\
\n
\
...
...
@@ -474,7 +487,7 @@ PyTypeObject PyFilter_Type = {
0
,
/* tp_weaklistoffset */
PyObject_SelfIter
,
/* tp_iter */
(
iternextfunc
)
filter_next
,
/* tp_iternext */
0
,
/* tp_methods */
filter_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
...
...
@@ -1054,6 +1067,31 @@ map_next(mapobject *lz)
return
result
;
}
static
PyObject
*
map_reduce
(
mapobject
*
lz
)
{
Py_ssize_t
numargs
=
PyTuple_GET_SIZE
(
lz
->
iters
);
PyObject
*
args
=
PyTuple_New
(
numargs
+
1
);
Py_ssize_t
i
;
if
(
args
==
NULL
)
return
NULL
;
Py_INCREF
(
lz
->
func
);
PyTuple_SET_ITEM
(
args
,
0
,
lz
->
func
);
for
(
i
=
0
;
i
<
numargs
;
i
++
){
PyObject
*
it
=
PyTuple_GET_ITEM
(
lz
->
iters
,
i
);
Py_INCREF
(
it
);
PyTuple_SET_ITEM
(
args
,
i
+
1
,
it
);
}
return
Py_BuildValue
(
"ON"
,
Py_TYPE
(
lz
),
args
);
}
static
PyMethodDef
map_methods
[]
=
{
{
"__reduce__"
,
(
PyCFunction
)
map_reduce
,
METH_NOARGS
,
reduce_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
PyDoc_STRVAR
(
map_doc
,
"map(func, *iterables) --> map object
\n
\
\n
\
...
...
@@ -1090,7 +1128,7 @@ PyTypeObject PyMap_Type = {
0
,
/* tp_weaklistoffset */
PyObject_SelfIter
,
/* tp_iter */
(
iternextfunc
)
map_next
,
/* tp_iternext */
0
,
/* tp_methods */
map_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
...
...
@@ -2238,6 +2276,18 @@ zip_next(zipobject *lz)
return
result
;
}
static
PyObject
*
zip_reduce
(
zipobject
*
lz
)
{
/* Just recreate the zip with the internal iterator tuple */
return
Py_BuildValue
(
"OO"
,
Py_TYPE
(
lz
),
lz
->
ittuple
);
}
static
PyMethodDef
zip_methods
[]
=
{
{
"__reduce__"
,
(
PyCFunction
)
zip_reduce
,
METH_NOARGS
,
reduce_doc
},
{
NULL
,
NULL
}
/* sentinel */
};
PyDoc_STRVAR
(
zip_doc
,
"zip(iter1 [,iter2 [...]]) --> zip object
\n
\
\n
\
...
...
@@ -2276,7 +2326,7 @@ PyTypeObject PyZip_Type = {
0
,
/* tp_weaklistoffset */
PyObject_SelfIter
,
/* tp_iter */
(
iternextfunc
)
zip_next
,
/* tp_iternext */
0
,
/* tp_methods */
zip_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
...
...
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