support for readonly buffers (#863) (#1466)
diff --git a/tests/constructor_stats.h b/tests/constructor_stats.h
index f026e70..431e5ac 100644
--- a/tests/constructor_stats.h
+++ b/tests/constructor_stats.h
@@ -180,7 +180,7 @@
}
}
}
- 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
diff --git a/tests/test_buffers.cpp b/tests/test_buffers.cpp
index 433dfee..1bc67ff 100644
--- a/tests/test_buffers.cpp
+++ b/tests/test_buffers.cpp
@@ -166,4 +166,30 @@
.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);
+
}
diff --git a/tests/test_buffers.py b/tests/test_buffers.py
index f006552..bf7aaed 100644
--- a/tests/test_buffers.py
+++ b/tests/test_buffers.py
@@ -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 @@
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)