[pypy-commit] pypy default: On CPython, some functions accept integers of any size and
arigo
noreply at buildbot.pypy.org
Sat Jul 23 11:00:28 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r45894:48020b9e373b
Date: 2011-07-23 11:00 +0200
http://bitbucket.org/pypy/pypy/changeset/48020b9e373b/
Log: On CPython, some functions accept integers of any size and truncate.
This seems to be important at least for crc32() and adler32(), so
fix it for them.
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1284,6 +1284,17 @@
self.wrap("expected a 32-bit integer"))
return value
+ def truncatedint(self, w_obj):
+ # Like space.gateway_int_w(), but return the integer truncated
+ # instead of raising OverflowError. For obscure cases only.
+ try:
+ return self.int_w(w_obj)
+ except OperationError, e:
+ if not e.match(self, self.w_OverflowError):
+ raise
+ from pypy.rlib.rarithmetic import intmask
+ return intmask(self.bigint_w(w_obj).uintmask())
+
def c_filedescriptor_w(self, w_fd):
# This is only used sometimes in CPython, e.g. for os.fsync() but
# not os.close(). It's likely designed for 'select'. It's irregular
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -140,6 +140,9 @@
def visit_c_nonnegint(self, el, app_sig):
self.checked_space_method(el, app_sig)
+ def visit_truncatedint(self, el, app_sig):
+ self.checked_space_method(el, app_sig)
+
def visit__Wrappable(self, el, app_sig):
name = el.__name__
argname = self.orig_arg()
@@ -257,6 +260,9 @@
def visit_c_nonnegint(self, typ):
self.run_args.append("space.c_nonnegint_w(%s)" % (self.scopenext(),))
+ def visit_truncatedint(self, typ):
+ self.run_args.append("space.truncatedint(%s)" % (self.scopenext(),))
+
def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
try:
key = tuple(unwrap_spec)
@@ -387,6 +393,9 @@
def visit_c_nonnegint(self, typ):
self.unwrap.append("space.c_nonnegint_w(%s)" % (self.nextarg(),))
+ def visit_truncatedint(self, typ):
+ self.unwrap.append("space.truncatedint(%s)" % (self.nextarg(),))
+
def make_fastfunc(unwrap_spec, func):
unwrap_info = UnwrapSpec_FastFunc_Unwrap()
unwrap_info.apply_over(unwrap_spec)
diff --git a/pypy/module/binascii/interp_crc32.py b/pypy/module/binascii/interp_crc32.py
--- a/pypy/module/binascii/interp_crc32.py
+++ b/pypy/module/binascii/interp_crc32.py
@@ -61,7 +61,7 @@
crc_32_tab = map(r_uint, crc_32_tab)
- at unwrap_spec(data='bufferstr', oldcrc='c_int')
+ at unwrap_spec(data='bufferstr', oldcrc='truncatedint')
def crc32(space, data, oldcrc=0):
"Compute the CRC-32 incrementally."
diff --git a/pypy/module/binascii/test/test_binascii.py b/pypy/module/binascii/test/test_binascii.py
--- a/pypy/module/binascii/test/test_binascii.py
+++ b/pypy/module/binascii/test/test_binascii.py
@@ -374,6 +374,8 @@
('x', 10000, -1855256896),
('y', 10000, -429115818),
('z', 10000, 2137352172),
+ ('foo', 99999999999999999999999999, -1932704816),
+ ('bar', -99999999999999999999999999, 2000545409),
]:
assert self.binascii.crc32(input, initial) == expected
diff --git a/pypy/module/zlib/interp_zlib.py b/pypy/module/zlib/interp_zlib.py
--- a/pypy/module/zlib/interp_zlib.py
+++ b/pypy/module/zlib/interp_zlib.py
@@ -20,25 +20,15 @@
return intmask((x ^ SIGN_EXTEND2) - SIGN_EXTEND2)
- at unwrap_spec(string='bufferstr')
-def crc32(space, string, w_start = rzlib.CRC32_DEFAULT_START):
+ at unwrap_spec(string='bufferstr', start='truncatedint')
+def crc32(space, string, start = rzlib.CRC32_DEFAULT_START):
"""
crc32(string[, start]) -- Compute a CRC-32 checksum of string.
An optional starting value can be specified. The returned checksum is
an integer.
"""
- if space.is_true(space.isinstance(w_start, space.w_long)):
- num = space.bigint_w(w_start)
- ustart = num.uintmask()
- elif space.is_true(space.isinstance(w_start, space.w_int)):
- start = space.int_w(w_start)
ustart = r_uint(start)
- else:
- raise OperationError(space.w_TypeError,
- space.wrap("crc32() argument 2 must "
- "be integer<k>, not str"))
-
checksum = rzlib.crc32(string, ustart)
# This is, perhaps, a little stupid. zlib returns the checksum unsigned.
@@ -51,7 +41,7 @@
return space.wrap(checksum)
- at unwrap_spec(string='bufferstr', start=r_uint)
+ at unwrap_spec(string='bufferstr', start='truncatedint')
def adler32(space, string, start=rzlib.ADLER32_DEFAULT_START):
"""
adler32(string[, start]) -- Compute an Adler-32 checksum of string.
@@ -59,7 +49,8 @@
An optional starting value can be specified. The returned checksum is
an integer.
"""
- checksum = rzlib.adler32(string, start)
+ ustart = r_uint(start)
+ checksum = rzlib.adler32(string, ustart)
# See comments in crc32() for the following line
checksum = unsigned_to_signed_32bit(checksum)
diff --git a/pypy/module/zlib/test/test_zlib.py b/pypy/module/zlib/test/test_zlib.py
--- a/pypy/module/zlib/test/test_zlib.py
+++ b/pypy/module/zlib/test/test_zlib.py
@@ -78,15 +78,17 @@
def test_crc32_negative_long_start(self):
v = self.zlib.crc32('', -1L)
assert v == -1
+ assert self.zlib.crc32('foo', -99999999999999999999999) == 1611238463
def test_crc32_long_start(self):
import sys
v = self.zlib.crc32('', sys.maxint*2)
assert v == -2
+ assert self.zlib.crc32('foo', 99999999999999999999999) == 1635107045
def test_adler32(self):
"""
- When called with a string, zlib.crc32 should compute its adler 32
+ When called with a string, zlib.adler32() should compute its adler 32
checksum and return it as a signed 32 bit integer.
On 64-bit machines too
(it is a bug in CPython < 2.6 to return unsigned values in this case).
@@ -113,6 +115,9 @@
helloworldsum = self.zlib.adler32(world, hellosum)
assert helloworldsum == self.zlib.adler32(hello + world)
+ assert self.zlib.adler32('foo', -1) == 45547858
+ assert self.zlib.adler32('foo', 99999999999999999999999) == -114818734
+
def test_invalidLevel(self):
"""
More information about the pypy-commit
mailing list