Fix crash in itertools.cycle.__setstate__() caused by lack of type checking.

Will backport after the 3.6 release is done.
This commit is contained in:
Raymond Hettinger 2015-08-15 13:51:59 -07:00
parent b468e1f595
commit 79c878d5f2
3 changed files with 37 additions and 1 deletions

View file

@ -613,6 +613,39 @@ class TestBasicOps(unittest.TestCase):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
self.pickletest(proto, cycle('abc'))
def test_cycle_setstate(self):
# Verify both modes for restoring state
# Mode 0 is efficient. It uses an incompletely consumed input
# iterator to build a cycle object and then passes in state with
# a list of previously consumed values. There is no data
# overlap bewteen the two.
c = cycle('defg')
c.__setstate__((list('abc'), 0))
self.assertEqual(take(20, c), list('defgabcdefgabcdefgab'))
# Mode 1 is inefficient. It starts with a cycle object built
# from an iterator over the remaining elements in a partial
# cycle and then passes in state with all of the previously
# seen values (this overlaps values included in the iterator).
c = cycle('defg')
c.__setstate__((list('abcdefg'), 1))
self.assertEqual(take(20, c), list('defgabcdefgabcdefgab'))
# The first argument to setstate needs to be a tuple
with self.assertRaises(SystemError):
cycle('defg').__setstate__([list('abcdefg'), 0])
# The first argument in the setstate tuple must be a list
with self.assertRaises(TypeError):
c = cycle('defg')
c.__setstate__((dict.fromkeys('defg'), 0))
take(20, c)
# The first argument in the setstate tuple must be a list
with self.assertRaises(TypeError):
cycle('defg').__setstate__((list('abcdefg'), 'x'))
def test_groupby(self):
# Check whether it accepts arguments correctly
self.assertEqual([], list(groupby([])))