[pypy-commit] pypy cpyext-ext: update to cffi/847bbc0297f8

arigo pypy.commits at gmail.com
Fri Jun 3 08:33:18 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-ext
Changeset: r84896:b16aa9a51698
Date: 2016-06-03 14:33 +0200
http://bitbucket.org/pypy/pypy/changeset/b16aa9a51698/

Log:	update to cffi/847bbc0297f8

diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -332,8 +332,8 @@
     def from_buffer(self, python_buffer):
         """Return a <cdata 'char[]'> that points to the data of the
         given Python object, which must support the buffer interface.
-        Note that this is not meant to be used on the built-in types str,
-        unicode, or bytearray (you can build 'char[]' arrays explicitly)
+        Note that this is not meant to be used on the built-in types
+        str or unicode (you can build 'char[]' arrays explicitly)
         but only on objects containing large quantities of raw data
         in some other format, like 'array.array' or numpy arrays.
         """
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -814,7 +814,7 @@
             try:
                 if ftype.is_integer_type() or fbitsize >= 0:
                     # accept all integers, but complain on float or double
-                    prnt("  (void)((p->%s) << 1);  /* check that '%s.%s' is "
+                    prnt("  (void)((p->%s) | 0);  /* check that '%s.%s' is "
                          "an integer */" % (fname, cname, fname))
                     continue
                 # only accept exactly the type declared, except that '[]'
@@ -991,7 +991,7 @@
             prnt('static int %s(unsigned long long *o)' % funcname)
             prnt('{')
             prnt('  int n = (%s) <= 0;' % (name,))
-            prnt('  *o = (unsigned long long)((%s) << 0);'
+            prnt('  *o = (unsigned long long)((%s) | 0);'
                  '  /* check that %s is an integer */' % (name, name))
             if check_value is not None:
                 if check_value > 0:
@@ -1250,7 +1250,7 @@
 
     def _emit_bytecode_UnknownIntegerType(self, tp, index):
         s = ('_cffi_prim_int(sizeof(%s), (\n'
-             '           ((%s)-1) << 0 /* check that %s is an integer type */\n'
+             '           ((%s)-1) | 0 /* check that %s is an integer type */\n'
              '         ) <= 0)' % (tp.name, tp.name, tp.name))
         self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s)
 
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -243,6 +243,9 @@
     def unicode_w(self, space):
         self._typed_unwrap_error(space, "unicode")
 
+    def bytearray_list_of_chars_w(self, space):
+        self._typed_unwrap_error(space, "bytearray")
+
     def int_w(self, space, allow_conversion=True):
         # note that W_IntObject.int_w has a fast path and W_FloatObject.int_w
         # raises w_TypeError
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -225,20 +225,29 @@
                     rffi.c_memcpy(target, source, ctitemsize * length)
                 return
         #
-        # A fast path for <char[]>[0:N] = "somestring".
+        # A fast path for <char[]>[0:N] = "somestring" or some bytearray.
         from pypy.module._cffi_backend import ctypeprim
         space = self.space
-        if (space.isinstance_w(w_value, space.w_str) and
-                isinstance(ctitem, ctypeprim.W_CTypePrimitiveChar)):
-            from rpython.rtyper.annlowlevel import llstr
-            from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
-            value = space.str_w(w_value)
-            if len(value) != length:
-                raise oefmt(space.w_ValueError,
-                            "need a string of length %d, got %d",
-                            length, len(value))
-            copy_string_to_raw(llstr(value), target, 0, length)
-            return
+        if isinstance(ctitem, ctypeprim.W_CTypePrimitive) and ctitem.size == 1:
+            if space.isinstance_w(w_value, space.w_str):
+                from rpython.rtyper.annlowlevel import llstr
+                from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
+                value = space.str_w(w_value)
+                if len(value) != length:
+                    raise oefmt(space.w_ValueError,
+                                "need a string of length %d, got %d",
+                                length, len(value))
+                copy_string_to_raw(llstr(value), target, 0, length)
+                return
+            if space.isinstance_w(w_value, space.w_bytearray):
+                value = w_value.bytearray_list_of_chars_w(space)
+                if len(value) != length:
+                    raise oefmt(space.w_ValueError,
+                                "need a bytearray of length %d, got %d",
+                                length, len(value))
+                for i in range(length):
+                    target[i] = value[i]
+                return
         #
         w_iter = space.iter(w_value)
         for i in range(length):
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -43,9 +43,6 @@
         else:
             return 'NULL'
 
-    def is_char_ptr_or_array(self):
-        return False
-
     def is_unichar_ptr_or_array(self):
         return False
 
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -29,9 +29,6 @@
         self.ctitem = ctitem
         self.can_cast_anything = could_cast_anything and ctitem.cast_anything
 
-    def is_char_ptr_or_array(self):
-        return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveChar)
-
     def is_unichar_ptr_or_array(self):
         return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveUniChar)
 
diff --git a/pypy/module/_cffi_backend/ffi_obj.py b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -347,7 +347,7 @@
         """\
 Return a <cdata 'char[]'> that points to the data of the given Python
 object, which must support the buffer interface.  Note that this is
-not meant to be used on the built-in types str, unicode, or bytearray
+not meant to be used on the built-in types str or unicode
 (you can build 'char[]' arrays explicitly) but only on objects
 containing large quantities of raw data in some other format, like
 'array.array' or numpy arrays."""
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -2686,10 +2686,19 @@
     BCharArray = new_array_type(
         new_pointer_type(new_primitive_type("char")), None)
     py.test.raises(TypeError, newp, BCharArray, bytearray(b"foo"))
-    p = newp(BCharArray, 4)
-    buffer(p)[:] = bytearray(b"foo\x00")
-    assert len(p) == 4
-    assert list(p) == [b"f", b"o", b"o", b"\x00"]
+    p = newp(BCharArray, 5)
+    buffer(p)[:] = bytearray(b"foo.\x00")
+    assert len(p) == 5
+    assert list(p) == [b"f", b"o", b"o", b".", b"\x00"]
+    p[1:3] = bytearray(b"XY")
+    assert list(p) == [b"f", b"X", b"Y", b".", b"\x00"]
+
+def test_string_assignment_to_byte_array():
+    BByteArray = new_array_type(
+        new_pointer_type(new_primitive_type("unsigned char")), None)
+    p = newp(BByteArray, 5)
+    p[0:3] = bytearray(b"XYZ")
+    assert list(p) == [ord("X"), ord("Y"), ord("Z"), 0, 0]
 
 # XXX hack
 if sys.version_info >= (3,):
@@ -3317,13 +3326,12 @@
     cast(p, c)[1] += 500
     assert list(a) == [10000, 20500, 30000]
 
-def test_from_buffer_not_str_unicode_bytearray():
+def test_from_buffer_not_str_unicode():
     BChar = new_primitive_type("char")
     BCharP = new_pointer_type(BChar)
     BCharA = new_array_type(BCharP, None)
     py.test.raises(TypeError, from_buffer, BCharA, b"foo")
     py.test.raises(TypeError, from_buffer, BCharA, u+"foo")
-    py.test.raises(TypeError, from_buffer, BCharA, bytearray(b"foo"))
     try:
         from __builtin__ import buffer
     except ImportError:
@@ -3331,16 +3339,27 @@
     else:
         py.test.raises(TypeError, from_buffer, BCharA, buffer(b"foo"))
         py.test.raises(TypeError, from_buffer, BCharA, buffer(u+"foo"))
-        py.test.raises(TypeError, from_buffer, BCharA,
-                       buffer(bytearray(b"foo")))
     try:
         from __builtin__ import memoryview
     except ImportError:
         pass
     else:
         py.test.raises(TypeError, from_buffer, BCharA, memoryview(b"foo"))
-        py.test.raises(TypeError, from_buffer, BCharA,
-                       memoryview(bytearray(b"foo")))
+
+def test_from_buffer_bytearray():
+    a = bytearray(b"xyz")
+    BChar = new_primitive_type("char")
+    BCharP = new_pointer_type(BChar)
+    BCharA = new_array_type(BCharP, None)
+    p = from_buffer(BCharA, a)
+    assert typeof(p) is BCharA
+    assert len(p) == 3
+    assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>"
+    assert p[2] == b"z"
+    p[2] = b"."
+    assert a[2] == ord(".")
+    a[2] = ord("?")
+    assert p[2] == b"?"
 
 def test_from_buffer_more_cases():
     try:
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -45,6 +45,9 @@
     def charbuf_w(self, space):
         return ''.join(self.data)
 
+    def bytearray_list_of_chars_w(self, space):
+        return self.data
+
     def nonmovable_carray(self, space):
         return BytearrayBuffer(self.data, False).get_raw_address()
 


More information about the pypy-commit mailing list