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