Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit