support for readonly buffers (#863) (#1466)

This commit is contained in:
Sebastian Koslowski
2019-11-24 08:33:05 +01:00
committed by Wenzel Jakob
parent bd24155b8b
commit dc65d66171
6 changed files with 83 additions and 13 deletions

View File

@@ -180,7 +180,7 @@ public:
}
}
}
catch (const std::out_of_range &) {}
catch (const std::out_of_range&) {}
if (!t1) throw std::runtime_error("Unknown class passed to ConstructorStats::get()");
auto &cs1 = get(*t1);
// If we have both a t1 and t2 match, one is probably the trampoline class; return whichever

View File

@@ -166,4 +166,30 @@ TEST_SUBMODULE(buffers, m) {
.def_readwrite("value", (int32_t DerivedBuffer::*) &DerivedBuffer::value)
.def_buffer(&DerivedBuffer::get_buffer_info);
struct BufferReadOnly {
const uint8_t value = 0;
BufferReadOnly(uint8_t value): value(value) {}
py::buffer_info get_buffer_info() {
return py::buffer_info(&value, 1);
}
};
py::class_<BufferReadOnly>(m, "BufferReadOnly", py::buffer_protocol())
.def(py::init<uint8_t>())
.def_buffer(&BufferReadOnly::get_buffer_info);
struct BufferReadOnlySelect {
uint8_t value = 0;
bool readonly = false;
py::buffer_info get_buffer_info() {
return py::buffer_info(&value, 1, readonly);
}
};
py::class_<BufferReadOnlySelect>(m, "BufferReadOnlySelect", py::buffer_protocol())
.def(py::init<>())
.def_readwrite("value", &BufferReadOnlySelect::value)
.def_readwrite("readonly", &BufferReadOnlySelect::readonly)
.def_buffer(&BufferReadOnlySelect::get_buffer_info);
}

View File

@@ -1,8 +1,14 @@
import io
import struct
import sys
import pytest
from pybind11_tests import buffers as m
from pybind11_tests import ConstructorStats
PY3 = sys.version_info[0] >= 3
pytestmark = pytest.requires_numpy
with pytest.suppress(ImportError):
@@ -85,3 +91,28 @@ def test_pointer_to_member_fn():
buf.value = 0x12345678
value = struct.unpack('i', bytearray(buf))[0]
assert value == 0x12345678
@pytest.unsupported_on_pypy
def test_readonly_buffer():
buf = m.BufferReadOnly(0x64)
view = memoryview(buf)
assert view[0] == 0x64 if PY3 else b'd'
assert view.readonly
@pytest.unsupported_on_pypy
def test_selective_readonly_buffer():
buf = m.BufferReadOnlySelect()
memoryview(buf)[0] = 0x64 if PY3 else b'd'
assert buf.value == 0x64
io.BytesIO(b'A').readinto(buf)
assert buf.value == ord(b'A')
buf.readonly = True
with pytest.raises(TypeError):
memoryview(buf)[0] = 0 if PY3 else b'\0'
with pytest.raises(TypeError):
io.BytesIO(b'1').readinto(buf)