[pypy-commit] pypy fix-struct-unpack-Q: make sure that we return an int even when we use 'q' on 32bit

antocuni pypy.commits at gmail.com
Mon Oct 31 10:31:15 EDT 2016


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: fix-struct-unpack-Q
Changeset: r87999:08ad056ff621
Date: 2016-10-31 15:29 +0100
http://bitbucket.org/pypy/pypy/changeset/08ad056ff621/

Log:	make sure that we return an int even when we use 'q' on 32bit

diff --git a/pypy/module/struct/formatiterator.py b/pypy/module/struct/formatiterator.py
--- a/pypy/module/struct/formatiterator.py
+++ b/pypy/module/struct/formatiterator.py
@@ -1,4 +1,5 @@
-from rpython.rlib.rarithmetic import r_uint, r_ulonglong, maxint, intmask
+from rpython.rlib.rarithmetic import (r_uint, r_ulonglong, r_longlong,
+                                      maxint, intmask)
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rstring import StringBuilder
@@ -149,13 +150,15 @@
 
     @specialize.argtype(1)
     def appendobj(self, value):
-        if isinstance(value, r_uint) or isinstance(value, r_ulonglong):
-            # unsigned int: space.wrap would wrap it inside a long, but
-            # CPython tries hard to return an int, if it fits
-            if value <= maxint:
-                w_value = self.space.wrap(intmask(value))
-            else:
-                w_value = self.space.wrap(value)
+        # CPython tries hard to return int objects whenever it can, but
+        # space.wrap returns a long if we pass a r_uint, r_ulonglong or
+        # r_longlong. So, we need special care in those cases.
+        is_unsigned = (isinstance(value, r_uint) or
+                       isinstance(value, r_ulonglong))
+        if is_unsigned and value <= maxint:
+            w_value = self.space.wrap(intmask(value))
+        elif isinstance(value, r_longlong) and -maxint-1 <= value <= maxint:
+            w_value = self.space.wrap(intmask(value))
         else:
             # generic type, just use space.wrap
             w_value = self.space.wrap(value)
diff --git a/pypy/module/struct/test/test_struct.py b/pypy/module/struct/test/test_struct.py
--- a/pypy/module/struct/test/test_struct.py
+++ b/pypy/module/struct/test/test_struct.py
@@ -431,9 +431,9 @@
     def test_overflow(self):
         raises(self.struct.error, self.struct.pack, 'i', 1<<65)
 
-    def test_unpack_unsigned(self):
+    def test_unpack_fits_into_int(self):
         import sys
-        for fmt in 'ILQ':
+        for fmt in 'ILQq':
             # check that we return an int, if it fits
             buf = self.struct.pack(fmt, 42)
             val, = self.struct.unpack(fmt, buf)


More information about the pypy-commit mailing list