Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r95502:70d98908b3fe
Date: 2018-12-16 08:52 +0100
http://bitbucket.org/pypy/pypy/changeset/70d98908b3fe/

Log:    Update to cffi/f4de3d6b3c34: implement ffi.from_buffer(x,
        require_writable=True)

diff --git a/extra_tests/cffi_tests/cffi0/test_ffi_backend.py 
b/extra_tests/cffi_tests/cffi0/test_ffi_backend.py
--- a/extra_tests/cffi_tests/cffi0/test_ffi_backend.py
+++ b/extra_tests/cffi_tests/cffi0/test_ffi_backend.py
@@ -327,6 +327,16 @@
         assert ffi.typeof(c) is ffi.typeof("char[]")
         ffi.cast("unsigned short *", c)[1] += 500
         assert list(a) == [10000, 20500, 30000]
+        assert c == ffi.from_buffer(a, True)
+        assert c == ffi.from_buffer(a, require_writable=True)
+        #
+        p = ffi.from_buffer(b"abcd")
+        assert p[2] == b"c"
+        #
+        assert p == ffi.from_buffer(b"abcd", False)
+        py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd", 
True)
+        py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd",
+                                                 require_writable=True)
 
     def test_memmove(self):
         ffi = FFI()
diff --git a/extra_tests/cffi_tests/cffi1/test_ffi_obj.py 
b/extra_tests/cffi_tests/cffi1/test_ffi_obj.py
--- a/extra_tests/cffi_tests/cffi1/test_ffi_obj.py
+++ b/extra_tests/cffi_tests/cffi1/test_ffi_obj.py
@@ -244,6 +244,16 @@
     assert ffi.typeof(c) is ffi.typeof("char[]")
     ffi.cast("unsigned short *", c)[1] += 500
     assert list(a) == [10000, 20500, 30000]
+    assert c == ffi.from_buffer(a, True)
+    assert c == ffi.from_buffer(a, require_writable=True)
+    #
+    p = ffi.from_buffer(b"abcd")
+    assert p[2] == b"c"
+    #
+    assert p == ffi.from_buffer(b"abcd", False)
+    py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd", True)
+    py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd",
+                                             require_writable=True)
 
 def test_memmove():
     ffi = _cffi1_backend.FFI()
diff --git a/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py 
b/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py
--- a/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py
+++ b/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py
@@ -1654,6 +1654,16 @@
         assert ffi.typeof(c) is ffi.typeof("char[]")
         ffi.cast("unsigned short *", c)[1] += 500
         assert list(a) == [10000, 20500, 30000]
+        assert c == ffi.from_buffer(a, True)
+        assert c == ffi.from_buffer(a, require_writable=True)
+        #
+        p = ffi.from_buffer(b"abcd")
+        assert p[2] == b"c"
+        #
+        assert p == ffi.from_buffer(b"abcd", False)
+        py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd", 
True)
+        py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd",
+                                                 require_writable=True)
 
     def test_all_primitives(self):
         assert set(PRIMITIVE_TO_INDEX) == set([
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
@@ -341,7 +341,7 @@
    #    """
    #    note that 'buffer' is a type, set on this instance by __init__
 
-    def from_buffer(self, python_buffer):
+    def from_buffer(self, python_buffer, require_writable=False):
         """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
@@ -349,7 +349,8 @@
         but only on objects containing large quantities of raw data
         in some other format, like 'array.array' or numpy arrays.
         """
-        return self._backend.from_buffer(self.BCharA, python_buffer)
+        return self._backend.from_buffer(self.BCharA, python_buffer,
+                                         require_writable)
 
     def memmove(self, dest, src, n):
         """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest.
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
@@ -327,7 +327,8 @@
         return w_ctype.cast(w_ob)
 
 
-    def descr_from_buffer(self, w_python_buffer):
+    @unwrap_spec(require_writable=int)
+    def descr_from_buffer(self, w_python_buffer, require_writable=0):
         """\
 Return a <cdata 'char[]'> that points to the data of the given Python
 object, which must support the buffer interface.  Note that this is
@@ -337,7 +338,8 @@
 'array.array' or numpy arrays."""
         #
         w_ctchara = newtype._new_chara_type(self.space)
-        return func._from_buffer(self.space, w_ctchara, w_python_buffer)
+        return func._from_buffer(self.space, w_ctchara, w_python_buffer,
+                                 require_writable)
 
 
     @unwrap_spec(w_arg=W_CData)
diff --git a/pypy/module/_cffi_backend/func.py 
b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -110,8 +110,8 @@
 def _fetch_as_write_buffer(space, w_x):
     return space.writebuf_w(w_x)
 
-@unwrap_spec(w_ctype=ctypeobj.W_CType)
-def from_buffer(space, w_ctype, w_x):
+@unwrap_spec(w_ctype=ctypeobj.W_CType, require_writable=int)
+def from_buffer(space, w_ctype, w_x, require_writable=0):
     from pypy.module._cffi_backend import ctypearray, ctypeprim
     #
     if (not isinstance(w_ctype, ctypearray.W_CTypeArray) or
@@ -119,13 +119,16 @@
         raise oefmt(space.w_TypeError,
                     "needs 'char[]', got '%s'", w_ctype.name)
     #
-    return _from_buffer(space, w_ctype, w_x)
+    return _from_buffer(space, w_ctype, w_x, require_writable)
 
-def _from_buffer(space, w_ctype, w_x):
+def _from_buffer(space, w_ctype, w_x, require_writable):
     if space.isinstance_w(w_x, space.w_unicode):
         raise oefmt(space.w_TypeError,
-                        "from_buffer() cannot return the address a unicode")
-    buf = _fetch_as_read_buffer(space, w_x)
+                "from_buffer() cannot return the address of a unicode object")
+    if require_writable:
+        buf = _fetch_as_write_buffer(space, w_x)
+    else:
+        buf = _fetch_as_read_buffer(space, w_x)
     if space.isinstance_w(w_x, space.w_bytes):
         _cdata = get_raw_address_of_string(space, w_x)
     else:
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
@@ -3730,6 +3730,18 @@
     check(4 | 8,  "CHB", "GTB")
     check(4 | 16, "CHB", "ROB")
 
+def test_from_buffer_require_writable():
+    BChar = new_primitive_type("char")
+    BCharP = new_pointer_type(BChar)
+    BCharA = new_array_type(BCharP, None)
+    p1 = from_buffer(BCharA, b"foo", False)
+    assert p1 == from_buffer(BCharA, b"foo", False)
+    py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True)
+    ba = bytearray(b"foo")
+    p1 = from_buffer(BCharA, ba, True)
+    p1[0] = b"g"
+    assert ba == b"goo"
+
 def test_memmove():
     Short = new_primitive_type("short")
     ShortA = new_array_type(new_pointer_type(Short), None)
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py 
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -287,6 +287,16 @@
         assert ffi.typeof(c) is ffi.typeof("char[]")
         ffi.cast("unsigned short *", c)[1] += 500
         assert list(a) == [10000, 20500, 30000]
+        assert c == ffi.from_buffer(a, True)
+        assert c == ffi.from_buffer(a, require_writable=True)
+        #
+        p = ffi.from_buffer(b"abcd")
+        assert p[2] == b"c"
+        #
+        assert p == ffi.from_buffer(b"abcd", False)
+        raises((TypeError, BufferError), ffi.from_buffer, b"abcd", True)
+        raises((TypeError, BufferError), ffi.from_buffer, b"abcd",
+                                         require_writable=True)
 
     def test_memmove(self):
         import sys
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to