Author: Armin Rigo <ar...@tunes.org>
Branch: py3.5-newtext
Changeset: r90148:2d5c0f6653b6
Date: 2017-02-15 13:33 +0100
http://bitbucket.org/pypy/pypy/changeset/2d5c0f6653b6/

Log:    CPython 3.x accepts both bytes or unicodes as the format
        specification of the struct module

diff --git a/pypy/module/struct/interp_struct.py 
b/pypy/module/struct/interp_struct.py
--- a/pypy/module/struct/interp_struct.py
+++ b/pypy/module/struct/interp_struct.py
@@ -32,8 +32,15 @@
     return fmtiter.totalsize
 
 
-@unwrap_spec(format='text')
-def calcsize(space, format):
+def text_or_bytes_w(space, w_input):
+    # why does CPython do this??
+    if space.isinstance_w(w_input, space.w_bytes):
+        return space.bytes_w(w_input)
+    else:
+        return space.text_w(w_input)
+
+def calcsize(space, w_format):
+    format = text_or_bytes_w(space, w_format)
     return space.newint(_calcsize(space, format))
 
 
@@ -52,14 +59,21 @@
     return fmtiter.result.build()
 
 
-@unwrap_spec(format='text')
-def pack(space, format, args_w):
+def pack(space, w_format, args_w):
+    format = text_or_bytes_w(space, w_format)
+    return do_pack(space, format, args_w)
+
+def do_pack(space, format, args_w):
     return space.newbytes(_pack(space, format, args_w))
 
 
+@unwrap_spec(offset=int)
+def pack_into(space, w_format, w_buffer, offset, args_w):
+    format = text_or_bytes_w(space, w_format)
+    return do_pack_into(space, format, w_buffer, offset, args_w)
+
 # XXX inefficient
-@unwrap_spec(format='text', offset=int)
-def pack_into(space, format, w_buffer, offset, args_w):
+def do_pack_into(space, format, w_buffer, offset, args_w):
     res = _pack(space, format, args_w)
     buf = space.getarg_w('w*', w_buffer)
     if offset < 0:
@@ -83,14 +97,21 @@
     return space.newtuple(fmtiter.result_w[:])
 
 
-@unwrap_spec(format='text')
-def unpack(space, format, w_str):
+def unpack(space, w_format, w_str):
+    format = text_or_bytes_w(space, w_format)
+    return do_unpack(space, format, w_str)
+
+def do_unpack(space, format, w_str):
     buf = space.getarg_w('s*', w_str)
     return _unpack(space, format, buf)
 
 
-@unwrap_spec(format='text', offset=int)
-def unpack_from(space, format, w_buffer, offset=0):
+@unwrap_spec(offset=int)
+def unpack_from(space, w_format, w_buffer, offset=0):
+    format = text_or_bytes_w(space, w_format)
+    return do_unpack_from(space, format, w_buffer, offset)
+
+def do_unpack_from(space, format, w_buffer, offset=0):
     size = _calcsize(space, format)
     buf = space.buffer_w(w_buffer, space.BUF_SIMPLE)
     if offset < 0:
@@ -146,25 +167,25 @@
         self.format = format
         self.size = _calcsize(space, format)
 
-    @unwrap_spec(format='text')
-    def descr__new__(space, w_subtype, format):
+    def descr__new__(space, w_subtype, w_format):
+        format = text_or_bytes_w(space, w_format)
         self = space.allocate_instance(W_Struct, w_subtype)
         W_Struct.__init__(self, space, format)
         return self
 
     def descr_pack(self, space, args_w):
-        return pack(space, jit.promote_string(self.format), args_w)
+        return do_pack(space, jit.promote_string(self.format), args_w)
 
     @unwrap_spec(offset=int)
     def descr_pack_into(self, space, w_buffer, offset, args_w):
-        return pack_into(space, jit.promote_string(self.format), w_buffer, 
offset, args_w)
+        return do_pack_into(space, jit.promote_string(self.format), w_buffer, 
offset, args_w)
 
     def descr_unpack(self, space, w_str):
-        return unpack(space, jit.promote_string(self.format), w_str)
+        return do_unpack(space, jit.promote_string(self.format), w_str)
 
     @unwrap_spec(offset=int)
     def descr_unpack_from(self, space, w_buffer, offset=0):
-        return unpack_from(space, jit.promote_string(self.format), w_buffer, 
offset)
+        return do_unpack_from(space, jit.promote_string(self.format), 
w_buffer, offset)
 
     def descr_iter_unpack(self, space, w_buffer):
         return W_UnpackIter(space, self, w_buffer)
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
@@ -530,6 +530,16 @@
                 format = byteorder+code
                 t = run_not_int_test(format)
 
+    def test_struct_with_bytes_as_format_string(self):
+        # why??
+        assert self.struct.calcsize(b'!ii') == 8
+        b = memoryview(bytearray(8))
+        self.struct.iter_unpack(b'ii', b)
+        self.struct.pack(b"ii", 45, 56)
+        self.struct.pack_into(b"ii", b, 0, 45, 56)
+        self.struct.unpack(b"ii", b"X" * 8)
+        assert self.struct.unpack_from(b"ii", b) == (45, 56)
+
 
 class AppTestStructBuffer(object):
     spaceconfig = dict(usemodules=['struct', '__pypy__'])
@@ -561,6 +571,7 @@
         assert self.struct.unpack_from("ii", b, 2) == (17, 42)
         b[:sz] = self.struct.pack("ii", 18, 43)
         assert self.struct.unpack_from("ii", b) == (18, 43)
+        self.struct.Struct(b"ii")
 
 
 class AppTestFastPath(object):
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to