Modify AsPyRef::as_ref to return PyRef
This commit is contained in:
parent
22687c3712
commit
01fc1405b0
|
@ -165,7 +165,7 @@ where
|
|||
/// Extract reference to instance from `PyObject`
|
||||
impl<'a, T> FromPyObject<'a> for &'a T
|
||||
where
|
||||
T: PyTryFrom,
|
||||
T: PyTryFrom<'a>,
|
||||
{
|
||||
#[inline]
|
||||
default fn extract(ob: &'a PyObjectRef) -> PyResult<&'a T> {
|
||||
|
@ -176,7 +176,7 @@ where
|
|||
/// Extract mutable reference to instance from `PyObject`
|
||||
impl<'a, T> FromPyObject<'a> for &'a mut T
|
||||
where
|
||||
T: PyTryFrom,
|
||||
T: PyTryFrom<'a>,
|
||||
{
|
||||
#[inline]
|
||||
default fn extract(ob: &'a PyObjectRef) -> PyResult<&'a mut T> {
|
||||
|
@ -221,33 +221,35 @@ pub trait PyTryInto<T>: Sized {
|
|||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
/// This trait is similar to `std::convert::TryFrom`
|
||||
pub trait PyTryFrom: Sized {
|
||||
pub trait PyTryFrom<'v>: Sized {
|
||||
/// Cast from a concrete Python object type to PyObject.
|
||||
fn try_from(value: &PyObjectRef) -> Result<&Self, PyDowncastError>;
|
||||
fn try_from<V: Into<&'v PyObjectRef>>(value: V) -> Result<&'v Self, PyDowncastError>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&Self, PyDowncastError>;
|
||||
fn try_from_exact<V: Into<&'v PyObjectRef>>(value: V) -> Result<&'v Self, PyDowncastError>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject.
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut Self, PyDowncastError>;
|
||||
fn try_from_mut<V: Into<&'v PyObjectRef>>(value: V) -> Result<&'v mut Self, PyDowncastError>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut Self, PyDowncastError>;
|
||||
fn try_from_mut_exact<V: Into<&'v PyObjectRef>>(
|
||||
value: V,
|
||||
) -> Result<&'v mut Self, PyDowncastError>;
|
||||
|
||||
/// Cast a PyObjectRef to a specific type of PyObject. The caller must
|
||||
/// have already verified the reference is for this type.
|
||||
unsafe fn try_from_unchecked(value: &PyObjectRef) -> &Self;
|
||||
unsafe fn try_from_unchecked<V: Into<&'v PyObjectRef>>(value: V) -> &'v Self;
|
||||
|
||||
/// Cast a PyObjectRef to a specific type of PyObject. The caller must
|
||||
/// have already verified the reference is for this type.
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
unsafe fn try_from_mut_unchecked(value: &PyObjectRef) -> &mut Self;
|
||||
unsafe fn try_from_mut_unchecked<V: Into<&'v PyObjectRef>>(value: V) -> &'v mut Self;
|
||||
}
|
||||
|
||||
// TryFrom implies TryInto
|
||||
impl<U> PyTryInto<U> for PyObjectRef
|
||||
where
|
||||
U: PyTryFrom,
|
||||
U: for<'v> PyTryFrom<'v>,
|
||||
{
|
||||
type Error = PyDowncastError;
|
||||
|
||||
|
@ -265,11 +267,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> PyTryFrom for T
|
||||
impl<'v, T> PyTryFrom<'v> for T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
fn try_from(value: &PyObjectRef) -> Result<&T, PyDowncastError> {
|
||||
fn try_from<V: Into<&'v PyObjectRef>>(value: V) -> Result<&'v T, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if T::is_instance(value) {
|
||||
Ok(PyTryFrom::try_from_unchecked(value))
|
||||
|
@ -279,7 +282,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&T, PyDowncastError> {
|
||||
fn try_from_exact<V: Into<&'v PyObjectRef>>(value: V) -> Result<&'v T, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if T::is_exact_instance(value) {
|
||||
Ok(PyTryFrom::try_from_unchecked(value))
|
||||
|
@ -289,7 +293,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut T, PyDowncastError> {
|
||||
fn try_from_mut<V: Into<&'v PyObjectRef>>(value: V) -> Result<&'v mut T, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if T::is_instance(value) {
|
||||
Ok(PyTryFrom::try_from_mut_unchecked(value))
|
||||
|
@ -299,7 +304,10 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut T, PyDowncastError> {
|
||||
fn try_from_mut_exact<V: Into<&'v PyObjectRef>>(
|
||||
value: V,
|
||||
) -> Result<&'v mut T, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if T::is_exact_instance(value) {
|
||||
Ok(PyTryFrom::try_from_mut_unchecked(value))
|
||||
|
@ -310,7 +318,8 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_from_unchecked(value: &PyObjectRef) -> &T {
|
||||
unsafe fn try_from_unchecked<V: Into<&'v PyObjectRef>>(value: V) -> &'v T {
|
||||
let value = value.into();
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
value as *const _ as *const u8 as *const T
|
||||
} else {
|
||||
|
@ -320,7 +329,8 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_from_mut_unchecked(value: &PyObjectRef) -> &mut T {
|
||||
unsafe fn try_from_mut_unchecked<V: Into<&'v PyObjectRef>>(value: V) -> &'v mut T {
|
||||
let value = value.into();
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
value as *const _ as *mut u8 as *mut T
|
||||
} else {
|
||||
|
@ -357,8 +367,6 @@ impl<T: IntoPyObject> ReturnTypeIntoPyResult for PyResult<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::PyTryFrom;
|
||||
|
|
|
@ -55,6 +55,15 @@ impl<'a, T> Deref for PyRef<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Into<&'a PyObjectRef> for PyRef<'a, T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
fn into(self) -> &'a PyObjectRef {
|
||||
unsafe { &*(self.as_ptr() as *const PyObjectRef) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PyRefMut<'a, T> {
|
||||
inner: &'a mut T,
|
||||
|
@ -91,18 +100,27 @@ impl<'a, T> DerefMut for PyRefMut<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Into<&'a PyObjectRef> for PyRefMut<'a, T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
fn into(self) -> &'a PyObjectRef {
|
||||
unsafe { &*(self.as_ptr() as *const PyObjectRef) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait implements object reference extraction from python managed pointer.
|
||||
pub trait AsPyRef<T>: Sized {
|
||||
/// Return reference to object.
|
||||
fn as_ref(&self, py: Python) -> &T;
|
||||
fn as_ref(&self, py: Python) -> PyRef<T>;
|
||||
|
||||
/// Return mutable reference to object.
|
||||
fn as_mut(&mut self, py: Python) -> &mut T;
|
||||
fn as_mut(&mut self, py: Python) -> PyRefMut<T>;
|
||||
|
||||
/// Acquire python gil and call closure with object reference.
|
||||
fn with<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(Python, &T) -> R,
|
||||
F: FnOnce(Python, PyRef<T>) -> R,
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
@ -113,7 +131,7 @@ pub trait AsPyRef<T>: Sized {
|
|||
/// Acquire python gil and call closure with mutable object reference.
|
||||
fn with_mut<F, R>(&mut self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(Python, &mut T) -> R,
|
||||
F: FnOnce(Python, PyRefMut<T>) -> R,
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
@ -124,7 +142,7 @@ pub trait AsPyRef<T>: Sized {
|
|||
fn into_py<F, R>(self, f: F) -> R
|
||||
where
|
||||
Self: IntoPyPointer,
|
||||
F: FnOnce(Python, &T) -> R,
|
||||
F: FnOnce(Python, PyRef<T>) -> R,
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
@ -137,7 +155,7 @@ pub trait AsPyRef<T>: Sized {
|
|||
fn into_mut_py<F, R>(mut self, f: F) -> R
|
||||
where
|
||||
Self: IntoPyPointer,
|
||||
F: FnOnce(Python, &mut T) -> R,
|
||||
F: FnOnce(Python, PyRefMut<T>) -> R,
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
@ -307,12 +325,12 @@ where
|
|||
T: PyTypeInfo,
|
||||
{
|
||||
#[inline]
|
||||
fn as_ref(&self, py: Python) -> &T {
|
||||
self.as_ref_dispatch(py)
|
||||
fn as_ref(&self, py: Python) -> PyRef<T> {
|
||||
PyRef::new(self.as_ref_dispatch(py))
|
||||
}
|
||||
#[inline]
|
||||
fn as_mut(&mut self, py: Python) -> &mut T {
|
||||
self.as_mut_dispatch(py)
|
||||
fn as_mut(&mut self, py: Python) -> PyRefMut<T> {
|
||||
PyRefMut::new(self.as_mut_dispatch(py))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::conversion::{
|
|||
};
|
||||
use crate::err::{PyDowncastError, PyErr, PyResult};
|
||||
use crate::ffi;
|
||||
use crate::instance::{AsPyRef, PyObjectWithGIL};
|
||||
use crate::instance::{AsPyRef, PyObjectWithGIL, PyRef, PyRefMut};
|
||||
use crate::python::{IntoPyPointer, Python, ToPyPointer};
|
||||
use crate::pythonrun;
|
||||
use crate::types::{PyDict, PyObjectRef, PyTuple};
|
||||
|
@ -154,7 +154,7 @@ impl PyObject {
|
|||
/// Casts the PyObject to a concrete Python object type.
|
||||
pub fn cast_as<D>(&self, py: Python) -> Result<&D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom,
|
||||
D: for<'v> PyTryFrom<'v>,
|
||||
{
|
||||
D::try_from(self.as_ref(py))
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ impl PyObject {
|
|||
where
|
||||
D: FromPyObject<'p>,
|
||||
{
|
||||
FromPyObject::extract(self.as_ref(py))
|
||||
FromPyObject::extract(self.as_ref(py).into())
|
||||
}
|
||||
|
||||
/// Retrieves an attribute value.
|
||||
|
@ -256,12 +256,12 @@ impl PyObject {
|
|||
|
||||
impl AsPyRef<PyObjectRef> for PyObject {
|
||||
#[inline]
|
||||
fn as_ref(&self, _py: Python) -> &PyObjectRef {
|
||||
unsafe { &*(self as *const _ as *const PyObjectRef) }
|
||||
fn as_ref(&self, _py: Python) -> PyRef<PyObjectRef> {
|
||||
unsafe { PyRef::new(&*(self as *const _ as *const PyObjectRef)) }
|
||||
}
|
||||
#[inline]
|
||||
fn as_mut(&mut self, _py: Python) -> &mut PyObjectRef {
|
||||
unsafe { &mut *(self as *mut _ as *mut PyObjectRef) }
|
||||
fn as_mut(&mut self, _py: Python) -> PyRefMut<PyObjectRef> {
|
||||
unsafe { PyRefMut::new(&mut *(self as *mut _ as *mut PyObjectRef)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ pub trait ObjectProtocol {
|
|||
/// Casts the PyObject to a concrete Python object type.
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom,
|
||||
D: PyTryFrom<'a>,
|
||||
&'a PyObjectRef: std::convert::From<&'a Self>;
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
|
@ -471,10 +471,10 @@ where
|
|||
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom,
|
||||
D: PyTryFrom<'a>,
|
||||
&'a PyObjectRef: std::convert::From<&'a Self>,
|
||||
{
|
||||
D::try_from(self.into())
|
||||
D::try_from(self)
|
||||
}
|
||||
|
||||
fn extract<'a, D>(&'a self) -> PyResult<D>
|
||||
|
|
|
@ -85,12 +85,12 @@ impl<'p> Drop for PyIterator<'p> {
|
|||
mod tests {
|
||||
use indoc::indoc;
|
||||
|
||||
use crate::conversion::{PyTryFrom, ToPyObject};
|
||||
use crate::conversion::ToPyObject;
|
||||
use crate::instance::AsPyRef;
|
||||
use crate::objectprotocol::ObjectProtocol;
|
||||
use crate::python::Python;
|
||||
use crate::pythonrun::GILPool;
|
||||
use crate::types::{PyDict, PyList, PyObjectRef};
|
||||
use crate::types::{PyDict, PyList};
|
||||
use crate::GILGuard;
|
||||
|
||||
#[test]
|
||||
|
@ -98,7 +98,7 @@ mod tests {
|
|||
let gil_guard = Python::acquire_gil();
|
||||
let py = gil_guard.python();
|
||||
let obj = vec![10, 20].to_object(py);
|
||||
let inst = <PyObjectRef as PyTryFrom>::try_from(obj.as_ref(py)).unwrap();
|
||||
let inst = obj.as_ref(py);
|
||||
let mut it = inst.iter().unwrap();
|
||||
assert_eq!(10, it.next().unwrap().unwrap().extract().unwrap());
|
||||
assert_eq!(20, it.next().unwrap().unwrap().extract().unwrap());
|
||||
|
@ -119,7 +119,7 @@ mod tests {
|
|||
{
|
||||
let gil_guard = Python::acquire_gil();
|
||||
let py = gil_guard.python();
|
||||
let inst = <PyObjectRef as PyTryFrom>::try_from(obj.as_ref(py)).unwrap();
|
||||
let inst = obj.as_ref(py);
|
||||
let mut it = inst.iter().unwrap();
|
||||
|
||||
assert_eq!(10, it.next().unwrap().unwrap().extract().unwrap());
|
||||
|
@ -147,7 +147,7 @@ mod tests {
|
|||
|
||||
{
|
||||
let _pool = GILPool::new();
|
||||
let inst = <PyObjectRef as PyTryFrom>::try_from(obj.as_ref(py)).unwrap();
|
||||
let inst = obj.as_ref(py);
|
||||
let mut it = inst.iter().unwrap();
|
||||
|
||||
assert_eq!(10, it.next().unwrap().unwrap().extract().unwrap());
|
||||
|
|
|
@ -275,8 +275,9 @@ where
|
|||
Ok(v)
|
||||
}
|
||||
|
||||
impl PyTryFrom for PySequence {
|
||||
fn try_from(value: &PyObjectRef) -> Result<&PySequence, PyDowncastError> {
|
||||
impl<'v> PyTryFrom<'v> for PySequence {
|
||||
fn try_from<V: Into<&'v PyObjectRef>>(value: V) -> Result<&'v PySequence, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
||||
Ok(<PySequence as PyTryFrom>::try_from_unchecked(value))
|
||||
|
@ -286,11 +287,16 @@ impl PyTryFrom for PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&PySequence, PyDowncastError> {
|
||||
fn try_from_exact<V: Into<&'v PyObjectRef>>(
|
||||
value: V,
|
||||
) -> Result<&'v PySequence, PyDowncastError> {
|
||||
<PySequence as PyTryFrom>::try_from(value)
|
||||
}
|
||||
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut PySequence, PyDowncastError> {
|
||||
fn try_from_mut<V: Into<&'v PyObjectRef>>(
|
||||
value: V,
|
||||
) -> Result<&'v mut PySequence, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
||||
Ok(<PySequence as PyTryFrom>::try_from_mut_unchecked(value))
|
||||
|
@ -300,19 +306,21 @@ impl PyTryFrom for PySequence {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut PySequence, PyDowncastError> {
|
||||
fn try_from_mut_exact<V: Into<&'v PyObjectRef>>(
|
||||
value: V,
|
||||
) -> Result<&'v mut PySequence, PyDowncastError> {
|
||||
<PySequence as PyTryFrom>::try_from_mut(value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_from_unchecked(value: &PyObjectRef) -> &PySequence {
|
||||
let ptr = value as *const _ as *const PySequence;
|
||||
unsafe fn try_from_unchecked<V: Into<&'v PyObjectRef>>(value: V) -> &'v PySequence {
|
||||
let ptr = value.into() as *const _ as *const PySequence;
|
||||
&*ptr
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_from_mut_unchecked(value: &PyObjectRef) -> &mut PySequence {
|
||||
let ptr = value as *const _ as *mut PySequence;
|
||||
unsafe fn try_from_mut_unchecked<V: Into<&'v PyObjectRef>>(value: V) -> &'v mut PySequence {
|
||||
let ptr = value.into() as *const _ as *mut PySequence;
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ mod test {
|
|||
let s = "Hello Python";
|
||||
let py_string = s.to_object(py);
|
||||
|
||||
let s2: &str = FromPyObject::extract(py_string.as_ref(py)).unwrap();
|
||||
let s2: &str = FromPyObject::extract(py_string.as_ref(py).into()).unwrap();
|
||||
assert_eq!(s, s2);
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ impl<'a> Iterator for PyTupleIterator<'a> {
|
|||
if self.index < self.slice.len() {
|
||||
let item = self.slice[self.index].as_ref(self.py);
|
||||
self.index += 1;
|
||||
Some(item)
|
||||
Some(item.into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue