Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3.3
Changeset: r81996:e4a76a0698fc
Date: 2016-01-27 09:35 +0100
http://bitbucket.org/pypy/pypy/changeset/e4a76a0698fc/
Log: Add pickle support to itertools.combinations (and probably
combinations_with_replacement as well)
diff --git a/pypy/module/itertools/interp_itertools.py
b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -1088,6 +1088,42 @@
self.last_result_w = result_w
return space.newtuple(result_w)
+ def descr_reduce(self, space):
+ if self.stopped:
+ pool_w = []
+ else:
+ pool_w = self.pool_w
+ result_w = [
+ space.type(self),
+ space.newtuple([
+ space.newtuple(pool_w), space.wrap(self.r)
+ ])]
+ if self.last_result_w is not None and not self.stopped:
+ # we must pickle the indices and use them for setstate
+ result_w = result_w + [
+ space.newtuple([
+ space.wrap(index) for index in self.indices])]
+ return space.newtuple(result_w)
+
+ def descr_setstate(self, space, w_state):
+ indices_w = space.fixedview(w_state)
+ if len(indices_w) != self.r:
+ import pdb;pdb.set_trace()
+ raise OperationError(space.w_ValueError, space.wrap(
+ "invalid arguments"))
+ for i in range(self.r):
+ index = space.int_w(indices_w[i])
+ max = self.get_maximum(i)
+ # clamp the index (beware of negative max)
+ if index > max:
+ index = max
+ if index < 0:
+ index = 0
+ self.indices.append(index)
+ self.last_result_w = [
+ self.pool_w[self.indices[i]]
+ for i in range(self.r)]
+
@unwrap_spec(r=int)
def W_Combinations__new__(space, w_subtype, w_iterable, r):
pool_w = space.fixedview(w_iterable)
@@ -1095,7 +1131,7 @@
raise OperationError(space.w_ValueError,
space.wrap("r must be non-negative")
)
- indices = range(len(pool_w))
+ indices = range(r)
res = space.allocate_instance(W_Combinations, w_subtype)
res.__init__(space, pool_w, indices, r)
return space.wrap(res)
@@ -1104,6 +1140,8 @@
__new__ = interp2app(W_Combinations__new__),
__iter__ = interp2app(W_Combinations.descr__iter__),
__next__ = interp2app(W_Combinations.descr_next),
+ __reduce__ = interp2app(W_Combinations.descr_reduce),
+ __setstate__ = interp2app(W_Combinations.descr_setstate),
__doc__ = """\
combinations(iterable, r) --> combinations object
diff --git a/pypy/module/itertools/test/test_itertools.py
b/pypy/module/itertools/test/test_itertools.py
--- a/pypy/module/itertools/test/test_itertools.py
+++ b/pypy/module/itertools/test/test_itertools.py
@@ -975,6 +975,25 @@
islice = itertools.islice(myiter, 5, 8)
raises(StopIteration, islice.__next__)
+ def test_combinations_pickle(self):
+ from itertools import combinations
+ import pickle
+ for op in (lambda a:a, lambda a:pickle.loads(pickle.dumps(a))):
+ assert list(op(combinations('abc', 32))) == [] # r > n
+ assert list(op(combinations('ABCD', 2))) == [
+ ('A','B'), ('A','C'), ('A','D'), ('B','C'), ('B','D'),
('C','D')]
+ testIntermediate = combinations('ABCD', 2)
+ next(testIntermediate)
+ assert list(op(testIntermediate)) == [
+ ('A','C'), ('A','D'), ('B','C'), ('B','D'), ('C','D')]
+
+ assert list(op(combinations(range(4), 3))) == [
+ (0,1,2), (0,1,3), (0,2,3), (1,2,3)]
+ testIntermediate = combinations(range(4), 3)
+ next(testIntermediate)
+ assert list(op(testIntermediate)) == [
+ (0,1,3), (0,2,3), (1,2,3)]
+
class AppTestItertools32:
spaceconfig = dict(usemodules=['itertools'])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit