Author: Philip Jenvey <pjen...@underboss.org>
Branch: stdlib-2.7.4
Changeset: r64953:de804d0c19b6
Date: 2013-06-20 17:01 -0700
http://bitbucket.org/pypy/pypy/changeset/de804d0c19b6/

Log:    cpython issues #16029/16030: Fix pickling and repr of large xranges

diff --git a/pypy/module/__builtin__/functional.py 
b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -2,6 +2,7 @@
 Interp-level definition of frequently used functionals.
 
 """
+import sys
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError
@@ -367,13 +368,12 @@
         return space.wrap(obj)
 
     def descr_repr(self):
-        stop = self.start + self.len * self.step
         if self.start == 0 and self.step == 1:
-            s = "xrange(%d)" % (stop,)
+            s = "xrange(%d)" % (self._get_stop(),)
         elif self.step == 1:
-            s = "xrange(%d, %d)" % (self.start, stop)
+            s = "xrange(%d, %d)" % (self.start, self._get_stop())
         else:
-            s = "xrange(%d, %d, %d)" %(self.start, stop, self.step)
+            s = "xrange(%d, %d, %d)" %(self.start, self._get_stop(), self.step)
         return self.space.wrap(s)
 
     def descr_len(self):
@@ -402,19 +402,29 @@
                                                     self.len, self.step))
 
     def descr_reversed(self):
-        lastitem = self.start + (self.len-1) * self.step
-        return self.space.wrap(W_XRangeIterator(self.space, lastitem,
-                                                self.len, -self.step))
+        last = self.start + (self.len - 1) * self.step
+        return self.space.wrap(W_XRangeIterator(self.space, last, self.len,
+                                                -self.step))
 
     def descr_reduce(self):
         space = self.space
         return space.newtuple(
             [space.type(self),
              space.newtuple([space.wrap(self.start),
-                             space.wrap(self.start + self.len * self.step),
+                             space.wrap(self._get_stop()),
                              space.wrap(self.step)])
              ])
 
+    def _get_stop(self):
+        if not self.len:
+            return self.start
+        step = self.step
+        last = self.start + (self.len - 1) * step
+        if step > 0:
+            return sys.maxint if last > sys.maxint - step else last + step
+        minint = -sys.maxint - 1
+        return minint if last < minint - step else last + step
+
 def _toint(space, w_obj):
     # this also supports float arguments.  CPython still does, too.
     # needs a bit more thinking in general...
diff --git a/pypy/module/__builtin__/test/test_functional.py 
b/pypy/module/__builtin__/test/test_functional.py
--- a/pypy/module/__builtin__/test/test_functional.py
+++ b/pypy/module/__builtin__/test/test_functional.py
@@ -188,6 +188,22 @@
         x = xrange(1)
         assert type(reversed(x)) == type(iter(x))
 
+    def test_cpython_issue16029(self):
+        import sys
+        M = min(sys.maxint, sys.maxsize)
+        x = xrange(0, M, M - 1)
+        assert x.__reduce__() == (xrange, (0, M, M - 1))
+        x = xrange(0, -M, 1 - M)
+        assert x.__reduce__() == (xrange, (0, -M - 1, 1 - M))
+
+    def test_cpython_issue16030(self):
+        import sys
+        M = min(sys.maxint, sys.maxsize)
+        x = xrange(0, M, M - 1)
+        assert repr(x) == 'xrange(0, %s, %s)' % (M, M - 1)
+        x = xrange(0, -M, 1 - M)
+        assert repr(x) == 'xrange(0, %s, %s)' % (-M - 1, 1 - M)
+
 
 class AppTestReversed:
     def test_reversed(self):
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to