Author: Jason Chu <[email protected]>
Branch: py3k-struct
Changeset: r62518:70bd50f9f372
Date: 2013-03-19 15:38 -0700
http://bitbucket.org/pypy/pypy/changeset/70bd50f9f372/
Log: Don't accept floats in struct pack/unpack as per py3k test
Python 2 used to accept things like floats as arguments to
struct.pack/unpack. This was done away with in Python 3, for good
reason.
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
@@ -3,7 +3,6 @@
from rpython.rlib.rstring import StringBuilder
from rpython.rlib.rstruct.error import StructError
from rpython.rlib.rstruct.formatiterator import FormatIterator
-from rpython.rlib.rstruct.standardfmttable import PACK_ACCEPTS_BROKEN_INPUT
from pypy.interpreter.error import OperationError
@@ -45,68 +44,39 @@
self.args_index += 1
return w_obj
- if PACK_ACCEPTS_BROKEN_INPUT:
- # permissive version - accepts float arguments too
+ # accepts objects with __index__es
- def accept_int_arg(self):
- return self._accept_integral("int_w")
+ def accept_int_arg(self):
+ return self._accept_integral("int_w")
- def accept_uint_arg(self):
- return self._accept_integral("uint_w")
+ def accept_uint_arg(self):
+ return self._accept_integral("uint_w")
- def accept_longlong_arg(self):
- return self._accept_integral("r_longlong_w")
+ def accept_longlong_arg(self):
+ return self._accept_integral("r_longlong_w")
- def accept_ulonglong_arg(self):
- return self._accept_integral("r_ulonglong_w")
+ def accept_ulonglong_arg(self):
+ return self._accept_integral("r_ulonglong_w")
- @specialize.arg(1)
- def _accept_integral(self, meth):
- space = self.space
- w_obj = self.accept_obj_arg()
- if space.isinstance_w(w_obj, space.w_int):
- w_index = w_obj
- else:
- w_index = None
- w_index_method = space.lookup(w_obj, "__index__")
- if w_index_method is not None:
- try:
- w_index = space.index(w_obj)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- pass
- if w_index is None:
- w_index = self._maybe_float(w_obj)
- return getattr(space, meth)(w_index)
-
- def _maybe_float(self, w_obj):
- space = self.space
- if space.is_true(space.isinstance(w_obj, space.w_float)):
- msg = "struct: integer argument expected, got float"
- else:
- msg = "integer argument expected, got non-integer"
- space.warn(space.wrap(msg), space.w_DeprecationWarning)
- return space.int(w_obj) # wrapped float -> wrapped int or long
-
- else:
- # strict version
-
- def accept_int_arg(self):
- w_obj = self.accept_obj_arg()
- return self.space.int_w(w_obj)
-
- def accept_uint_arg(self):
- w_obj = self.accept_obj_arg()
- return self.space.uint_w(w_obj)
-
- def accept_longlong_arg(self):
- w_obj = self.accept_obj_arg()
- return self.space.r_longlong_w(w_obj)
-
- def accept_ulonglong_arg(self):
- w_obj = self.accept_obj_arg()
- return self.space.r_ulonglong_w(w_obj)
+ @specialize.arg(1)
+ def _accept_integral(self, meth):
+ space = self.space
+ w_obj = self.accept_obj_arg()
+ if space.isinstance_w(w_obj, space.w_int):
+ w_index = w_obj
+ else:
+ w_index = None
+ w_index_method = space.lookup(w_obj, "__index__")
+ if w_index_method is not None:
+ try:
+ w_index = space.index(w_obj)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ pass
+ if w_index is None:
+ raise StructError("required argument is not an integer")
+ return getattr(space, meth)(w_index)
def accept_bool_arg(self):
w_obj = self.accept_obj_arg()
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
@@ -61,17 +61,6 @@
assert self.struct.unpack("i", self.struct.pack("i", X()))[0] == 3
- def test_deprecation_warning(self):
- import warnings
- for code in 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q':
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- raises(TypeError, self.struct.pack, code, 3j)
- assert len(w) == 1
- assert str(w[0].message) == "integer argument expected, got
non-integer"
- assert w[0].category is DeprecationWarning
-
-
def test_pack_standard_little(self):
"""
Check packing with the '<' format specifier.
@@ -412,7 +401,26 @@
b'spam and eggs')
raises(self.struct.error, self.struct.unpack_from, '14s42', store, 0)
-
+ def test_1530559(self):
+ # Native 'q' packing isn't available on systems that don't have the C
+ # long long type.
+ try:
+ self.struct.pack('q', 5)
+ except self.struct.error:
+ HAVE_LONG_LONG = False
+ else:
+ HAVE_LONG_LONG = True
+ integer_codes = ('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q')
+ for byteorder in '', '@', '=', '<', '>', '!':
+ for code in integer_codes:
+ if (byteorder in ('', '@') and code in ('q', 'Q') and
+ not HAVE_LONG_LONG):
+ continue
+ format = byteorder + code
+ raises(self.struct.error, self.struct.pack, format, 1.0)
+ raises(self.struct.error, self.struct.pack, format, 1.5)
+ raises(self.struct.error, self.struct.pack, 'P', 1.0)
+ raises(self.struct.error, self.struct.pack, 'P', 1.5)
class AppTestStructBuffer(object):
spaceconfig = dict(usemodules=['struct', '__pypy__'])
diff --git a/rpython/rlib/rstruct/standardfmttable.py
b/rpython/rlib/rstruct/standardfmttable.py
--- a/rpython/rlib/rstruct/standardfmttable.py
+++ b/rpython/rlib/rstruct/standardfmttable.py
@@ -13,12 +13,6 @@
from rpython.rlib.rstruct.error import StructError, StructOverflowError
from rpython.rlib.unroll import unrolling_iterable
-# In the CPython struct module, pack() unconsistently accepts inputs
-# that are out-of-range or floats instead of ints. Should we emulate
-# this? Let's use a flag for now:
-
-PACK_ACCEPTS_BROKEN_INPUT = True
-
# ____________________________________________________________
def pack_pad(fmtiter, count):
@@ -100,10 +94,7 @@
return min, max, accept_method
def make_int_packer(size, signed, cpython_checks_range, _memo={}):
- if cpython_checks_range:
- check_range = True
- else:
- check_range = not PACK_ACCEPTS_BROKEN_INPUT
+ check_range = True
key = (size, signed, check_range)
try:
return _memo[key]
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit