Merge pull request #3514 from messense/memoryview

Add `PyMemoryView` type
This commit is contained in:
David Hewitt 2023-10-15 15:08:50 +00:00 committed by GitHub
commit f12f928bd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 75 additions and 4 deletions

View file

@ -0,0 +1 @@
Add `PyMemoryView` type.

View file

@ -29,7 +29,10 @@ extern "C" {
size: Py_ssize_t,
flags: c_int,
) -> *mut PyObject;
// skipped non-limited PyMemoryView_FromBuffer
#[cfg(any(Py_3_11, not(Py_LIMITED_API)))]
#[cfg_attr(PyPy, link_name = "PyPyMemoryView_FromBuffer")]
pub fn PyMemoryView_FromBuffer(view: *const crate::Py_buffer) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyMemoryView_GetContiguous")]
pub fn PyMemoryView_GetContiguous(
base: *mut PyObject,
buffertype: c_int,

View file

@ -3,7 +3,7 @@
//! Objects related to PyBuffer and PyStr
use pyo3::buffer::PyBuffer;
use pyo3::prelude::*;
use pyo3::types::{PyBytes, PyString};
use pyo3::types::{PyBytes, PyMemoryView, PyString};
/// This is for confirming that PyBuffer does not cause memory leak
#[pyclass]
@ -41,8 +41,16 @@ impl BytesExtractor {
}
}
#[pyfunction]
fn return_memoryview(py: Python<'_>) -> PyResult<&PyMemoryView> {
let bytes: &PyAny = PyBytes::new(py, b"hello world").into();
let memoryview = TryInto::try_into(bytes)?;
Ok(memoryview)
}
#[pymodule]
pub fn buf_and_str(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<BytesExtractor>()?;
m.add_function(wrap_pyfunction!(return_memoryview, m)?)?;
Ok(())
}

View file

@ -1,4 +1,4 @@
from pyo3_pytests.buf_and_str import BytesExtractor
from pyo3_pytests.buf_and_str import BytesExtractor, return_memoryview
def test_extract_bytes():
@ -27,3 +27,10 @@ def test_extract_buffer():
arr = bytearray(b'\\(-"-;) A message written in bytes')
assert extractor.from_buffer(arr) == len(arr)
def test_return_memoryview():
view = return_memoryview()
assert view.readonly
assert view.contiguous
assert view.tobytes() == b"hello world"

View file

@ -241,10 +241,20 @@ impl PyByteArray {
}
}
impl<'py> TryFrom<&'py PyAny> for &'py PyByteArray {
type Error = crate::PyErr;
/// Creates a new Python `bytearray` object from another Python object that
/// implements the buffer protocol.
fn try_from(value: &'py PyAny) -> Result<Self, Self::Error> {
PyByteArray::from(value)
}
}
#[cfg(test)]
mod tests {
use crate::exceptions;
use crate::types::PyByteArray;
use crate::{exceptions, PyAny};
use crate::{PyObject, Python};
#[test]
@ -322,6 +332,17 @@ mod tests {
});
}
#[test]
fn test_try_from() {
Python::with_gil(|py| {
let src = b"Hello Python";
let bytearray: &PyAny = PyByteArray::new(py, src).into();
let bytearray: &PyByteArray = TryInto::try_into(bytearray).unwrap();
assert_eq!(src, unsafe { bytearray.as_bytes() });
});
}
#[test]
fn test_resize() {
Python::with_gil(|py| {

29
src/types/memoryview.rs Normal file
View file

@ -0,0 +1,29 @@
use crate::err::PyResult;
use crate::{ffi, AsPyPointer, PyAny};
/// Represents a Python `memoryview`.
#[repr(transparent)]
pub struct PyMemoryView(PyAny);
pyobject_native_type_core!(PyMemoryView, pyobject_native_static_type_object!(ffi::PyMemoryView_Type), #checkfunction=ffi::PyMemoryView_Check);
impl PyMemoryView {
/// Creates a new Python `memoryview` object from another Python object that
/// implements the buffer protocol.
pub fn from(src: &PyAny) -> PyResult<&PyMemoryView> {
unsafe {
src.py()
.from_owned_ptr_or_err(ffi::PyMemoryView_FromObject(src.as_ptr()))
}
}
}
impl<'py> TryFrom<&'py PyAny> for &'py PyMemoryView {
type Error = crate::PyErr;
/// Creates a new Python `memoryview` object from another Python object that
/// implements the buffer protocol.
fn try_from(value: &'py PyAny) -> Result<Self, Self::Error> {
PyMemoryView::from(value)
}
}

View file

@ -27,6 +27,7 @@ pub use self::function::PyFunction;
pub use self::iterator::PyIterator;
pub use self::list::PyList;
pub use self::mapping::PyMapping;
pub use self::memoryview::PyMemoryView;
pub use self::module::PyModule;
pub use self::none::PyNone;
pub use self::notimplemented::PyNotImplemented;
@ -289,6 +290,7 @@ mod function;
mod iterator;
pub(crate) mod list;
mod mapping;
mod memoryview;
mod module;
mod none;
mod notimplemented;