Introduce FromPyPointer for slf: PyRef/PyRefMut
This commit is contained in:
parent
515c7beac0
commit
b2e01066f0
|
@ -27,35 +27,7 @@ pub enum FnType {
|
|||
FnCall,
|
||||
FnClass,
|
||||
FnStatic,
|
||||
PySelf(PySelfType),
|
||||
}
|
||||
|
||||
/// For fn(slf: &PyRef<Self>) support
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum PySelfType {
|
||||
Py,
|
||||
PyRef,
|
||||
PyRefMut,
|
||||
}
|
||||
|
||||
impl PySelfType {
|
||||
fn from_args<'a>(args: &[FnArg<'a>]) -> Option<Self> {
|
||||
let arg = args.iter().next()?;
|
||||
let path = match arg.ty {
|
||||
syn::Type::Path(p) => p,
|
||||
_ => return None,
|
||||
};
|
||||
let last_seg = match path.path.segments.last()? {
|
||||
syn::punctuated::Pair::Punctuated(t, _) => t,
|
||||
syn::punctuated::Pair::End(t) => t,
|
||||
};
|
||||
match &*last_seg.ident.to_string() {
|
||||
"Py" => Some(PySelfType::Py),
|
||||
"PyRef" => Some(PySelfType::PyRef),
|
||||
"PyRefMut" => Some(PySelfType::PyRefMut),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
PySelf(syn::Type),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
|
@ -148,14 +120,10 @@ impl<'a> FnSpec<'a> {
|
|||
let ty = get_return_info(&sig.decl.output);
|
||||
|
||||
if fn_type == FnType::Fn && !has_self {
|
||||
if let Some(pyslf) = PySelfType::from_args(&arguments) {
|
||||
fn_type = FnType::PySelf(pyslf);
|
||||
arguments.remove(0);
|
||||
} else {
|
||||
panic!(
|
||||
"Static method needs an attribute #[staticmethod] or PyRef/PyRefMut as the 1st arg"
|
||||
);
|
||||
if arguments.len() == 0 {
|
||||
panic!("Static method needs an attribute #[staticmethod]");
|
||||
}
|
||||
fn_type = FnType::PySelf(arguments.remove(0).ty.to_owned());
|
||||
}
|
||||
|
||||
Ok(FnSpec {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use crate::method::{FnArg, FnSpec, FnType, PySelfType};
|
||||
use crate::method::{FnArg, FnSpec, FnType};
|
||||
use crate::utils;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
|
@ -18,11 +18,11 @@ pub fn gen_py_method(
|
|||
|
||||
match spec.tp {
|
||||
FnType::Fn => impl_py_method_def(name, doc, &spec, &impl_wrap(cls, name, &spec, true)),
|
||||
FnType::PySelf(pyslf) => impl_py_method_def(
|
||||
FnType::PySelf(ref self_ty) => impl_py_method_def(
|
||||
name,
|
||||
doc,
|
||||
&spec,
|
||||
&impl_wrap_pyslf(cls, name, &spec, pyslf, true),
|
||||
&impl_wrap_pyslf(cls, name, &spec, self_ty, true),
|
||||
),
|
||||
FnType::FnNew => impl_py_method_def_new(name, doc, &impl_wrap_new(cls, name, &spec)),
|
||||
FnType::FnInit => impl_py_method_def_init(name, doc, &impl_wrap_init(cls, name, &spec)),
|
||||
|
@ -55,7 +55,7 @@ pub fn impl_wrap(
|
|||
) -> TokenStream {
|
||||
let body = impl_call(cls, name, &spec);
|
||||
let slf = quote! {
|
||||
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
|
||||
let _slf: &mut #cls = pyo3::FromPyPointer::from_borrowed_ptr(_py, _slf);
|
||||
};
|
||||
impl_wrap_common(cls, name, spec, noargs, slf, body)
|
||||
}
|
||||
|
@ -64,23 +64,15 @@ pub fn impl_wrap_pyslf(
|
|||
cls: &syn::Type,
|
||||
name: &syn::Ident,
|
||||
spec: &FnSpec<'_>,
|
||||
slftype: PySelfType,
|
||||
self_ty: &syn::Type,
|
||||
noargs: bool,
|
||||
) -> TokenStream {
|
||||
let names = get_arg_names(spec);
|
||||
let body = quote! {
|
||||
#cls::#name(_slf, #(#names),*)
|
||||
};
|
||||
let slf = match slftype {
|
||||
PySelfType::Py => quote! {
|
||||
let _slf = pyo3::Py::<#cls>::from_borrowed_ptr(_slf);
|
||||
},
|
||||
PySelfType::PyRef => quote! {
|
||||
let _slf = pyo3::PyRef::<#cls>::from_borrowed_ptr(_py, _slf);
|
||||
},
|
||||
PySelfType::PyRefMut => quote! {
|
||||
let _slf = pyo3::PyRefMut::<#cls>::from_borrowed_ptr(_py, _slf);
|
||||
},
|
||||
let slf = quote! {
|
||||
let _slf: #self_ty = pyo3::FromPyPointer::from_borrowed_ptr(_py, _slf);
|
||||
};
|
||||
impl_wrap_common(cls, name, spec, noargs, slf, body)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
//! Conversions between various states of rust and python types and their wrappers.
|
||||
|
||||
use crate::err::{PyDowncastError, PyResult};
|
||||
use crate::ffi;
|
||||
use crate::err::{self, PyDowncastError, PyResult};
|
||||
use crate::object::PyObject;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::types::PyAny;
|
||||
use crate::types::PyTuple;
|
||||
use crate::Py;
|
||||
use crate::Python;
|
||||
use crate::{ffi, gil, Py, Python};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// This trait represents that, **we can do zero-cost conversion from the object to FFI pointer**.
|
||||
///
|
||||
|
@ -432,6 +430,65 @@ impl FromPy<()> for Py<PyTuple> {
|
|||
}
|
||||
}
|
||||
|
||||
pub unsafe trait FromPyPointer<'p>: Sized {
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self>;
|
||||
unsafe fn from_owned_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> Self {
|
||||
match Self::from_owned_ptr_or_opt(py, ptr) {
|
||||
Some(s) => s,
|
||||
None => err::panic_after_error(),
|
||||
}
|
||||
}
|
||||
unsafe fn from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> Self {
|
||||
Self::from_owned_ptr_or_panic(py, ptr)
|
||||
}
|
||||
unsafe fn from_owned_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyResult<Self> {
|
||||
match Self::from_owned_ptr_or_opt(py, ptr) {
|
||||
Some(s) => Ok(s),
|
||||
None => Err(err::PyErr::fetch(py)),
|
||||
}
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self>;
|
||||
unsafe fn from_borrowed_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> Self {
|
||||
match Self::from_borrowed_ptr_or_opt(py, ptr) {
|
||||
Some(s) => s,
|
||||
None => err::panic_after_error(),
|
||||
}
|
||||
}
|
||||
unsafe fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> Self {
|
||||
Self::from_borrowed_ptr_or_panic(py, ptr)
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyResult<Self> {
|
||||
match Self::from_borrowed_ptr_or_opt(py, ptr) {
|
||||
Some(s) => Ok(s),
|
||||
None => Err(err::PyErr::fetch(py)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| py.unchecked_downcast(gil::register_owned(py, p)))
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| py.unchecked_downcast(gil::register_borrowed(py, p)))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p mut T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| py.unchecked_mut_downcast(gil::register_owned(py, p)))
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| py.unchecked_mut_downcast(gil::register_borrowed(py, p)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::types::PyList;
|
||||
|
|
|
@ -8,10 +8,10 @@ use crate::objectprotocol::ObjectProtocol;
|
|||
use crate::type_object::PyTypeCreate;
|
||||
use crate::type_object::{PyTypeInfo, PyTypeObject};
|
||||
use crate::types::PyAny;
|
||||
use crate::AsPyPointer;
|
||||
use crate::IntoPyPointer;
|
||||
use crate::Python;
|
||||
use crate::{FromPyObject, IntoPyObject, PyTryFrom, ToPyObject};
|
||||
use crate::{
|
||||
AsPyPointer, FromPyObject, FromPyPointer, IntoPyObject, IntoPyPointer, PyTryFrom, Python,
|
||||
ToPyObject,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
@ -72,23 +72,16 @@ impl<'a, T: PyTypeInfo> PyRef<'a, T> {
|
|||
pub(crate) fn from_ref(r: &'a T) -> Self {
|
||||
PyRef(r, PhantomData)
|
||||
}
|
||||
pub unsafe fn from_owned_ptr(py: Python<'a>, ptr: *mut ffi::PyObject) -> Self {
|
||||
Self::from_ref(py.from_owned_ptr(ptr))
|
||||
}
|
||||
pub unsafe fn from_borrowed_ptr(py: Python<'a>, ptr: *mut ffi::PyObject) -> Self {
|
||||
Self::from_ref(py.from_borrowed_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> PyRef<'a, T>
|
||||
impl<'p, T> PyRef<'p, T>
|
||||
where
|
||||
T: PyTypeInfo + PyTypeObject + PyTypeCreate,
|
||||
{
|
||||
pub fn new(py: Python, value: T) -> PyResult<PyRef<T>> {
|
||||
pub fn new(py: Python<'p>, value: T) -> PyResult<PyRef<T>> {
|
||||
let obj = T::create(py)?;
|
||||
obj.init(value);
|
||||
let ref_ = unsafe { py.from_owned_ptr(obj.into_ptr()) };
|
||||
Ok(PyRef::from_ref(ref_))
|
||||
unsafe { Self::from_owned_ptr_or_err(py, obj.into_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,6 +113,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for PyRef<'p, T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
FromPyPointer::from_owned_ptr_or_opt(py, ptr).map(Self::from_ref)
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
FromPyPointer::from_borrowed_ptr_or_opt(py, ptr).map(Self::from_ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutable version of [`PyRef`](struct.PyRef.html).
|
||||
/// # Example
|
||||
/// ```
|
||||
|
@ -150,23 +155,16 @@ impl<'a, T: PyTypeInfo> PyRefMut<'a, T> {
|
|||
pub(crate) fn from_mut(t: &'a mut T) -> Self {
|
||||
PyRefMut(t, PhantomData)
|
||||
}
|
||||
pub unsafe fn from_owned_ptr(py: Python<'a>, ptr: *mut ffi::PyObject) -> Self {
|
||||
Self::from_mut(py.mut_from_owned_ptr(ptr))
|
||||
}
|
||||
pub unsafe fn from_borrowed_ptr(py: Python<'a>, ptr: *mut ffi::PyObject) -> Self {
|
||||
Self::from_mut(py.mut_from_borrowed_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> PyRefMut<'a, T>
|
||||
impl<'p, T> PyRefMut<'p, T>
|
||||
where
|
||||
T: PyTypeInfo + PyTypeObject + PyTypeCreate,
|
||||
{
|
||||
pub fn new(py: Python, value: T) -> PyResult<PyRefMut<T>> {
|
||||
pub fn new(py: Python<'p>, value: T) -> PyResult<PyRefMut<T>> {
|
||||
let obj = T::create(py)?;
|
||||
obj.init(value);
|
||||
let ref_ = unsafe { py.mut_from_owned_ptr(obj.into_ptr()) };
|
||||
Ok(PyRefMut::from_mut(ref_))
|
||||
unsafe { Self::from_owned_ptr_or_err(py, obj.into_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,6 +204,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for PyRefMut<'p, T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
FromPyPointer::from_owned_ptr_or_opt(py, ptr).map(Self::from_mut)
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
FromPyPointer::from_borrowed_ptr_or_opt(py, ptr).map(Self::from_mut)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait implements object reference extraction from python managed pointer.
|
||||
pub trait AsPyRef<T: PyTypeInfo>: Sized {
|
||||
/// Return reference to object.
|
||||
|
|
|
@ -119,8 +119,8 @@
|
|||
|
||||
pub use crate::class::*;
|
||||
pub use crate::conversion::{
|
||||
AsPyPointer, FromPy, FromPyObject, IntoPy, IntoPyObject, IntoPyPointer, PyTryFrom, PyTryInto,
|
||||
ToBorrowedObject, ToPyObject,
|
||||
AsPyPointer, FromPy, FromPyObject, FromPyPointer, IntoPy, IntoPyObject, IntoPyPointer,
|
||||
PyTryFrom, PyTryInto, ToBorrowedObject, ToPyObject,
|
||||
};
|
||||
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult};
|
||||
pub use crate::gil::{init_once, GILGuard, GILPool};
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::object::PyObject;
|
|||
use crate::type_object::{PyTypeInfo, PyTypeObject};
|
||||
use crate::types::{PyAny, PyDict, PyModule, PyType};
|
||||
use crate::AsPyPointer;
|
||||
use crate::{IntoPyPointer, PyTryFrom};
|
||||
use crate::{FromPyPointer, IntoPyPointer, PyTryFrom};
|
||||
use std::ffi::CString;
|
||||
use std::marker::PhantomData;
|
||||
use std::os::raw::c_int;
|
||||
|
@ -193,7 +193,7 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
impl<'p> Python<'p> {
|
||||
unsafe fn unchecked_downcast<T: PyTypeInfo>(self, ob: &PyAny) -> &'p T {
|
||||
pub(crate) unsafe fn unchecked_downcast<T: PyTypeInfo>(self, ob: &PyAny) -> &'p T {
|
||||
if T::OFFSET == 0 {
|
||||
&*(ob as *const _ as *const T)
|
||||
} else {
|
||||
|
@ -203,7 +203,7 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
#[allow(clippy::cast_ref_to_mut)] // FIXME
|
||||
unsafe fn unchecked_mut_downcast<T: PyTypeInfo>(self, ob: &PyAny) -> &'p mut T {
|
||||
pub(crate) unsafe fn unchecked_mut_downcast<T: PyTypeInfo>(self, ob: &PyAny) -> &'p mut T {
|
||||
if T::OFFSET == 0 {
|
||||
&mut *(ob as *const _ as *mut T)
|
||||
} else {
|
||||
|
@ -244,13 +244,7 @@ impl<'p> Python<'p> {
|
|||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
match NonNull::new(ptr) {
|
||||
Some(p) => {
|
||||
let p = gil::register_owned(self, p);
|
||||
self.unchecked_downcast(p)
|
||||
}
|
||||
None => crate::err::panic_after_error(),
|
||||
}
|
||||
FromPyPointer::from_owned_ptr(self, ptr)
|
||||
}
|
||||
|
||||
/// Register `ffi::PyObject` pointer in release pool,
|
||||
|
@ -259,13 +253,7 @@ impl<'p> Python<'p> {
|
|||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
match NonNull::new(ptr) {
|
||||
Some(p) => {
|
||||
let p = gil::register_owned(self, p);
|
||||
self.unchecked_mut_downcast(p)
|
||||
}
|
||||
None => crate::err::panic_after_error(),
|
||||
}
|
||||
FromPyPointer::from_owned_ptr(self, ptr)
|
||||
}
|
||||
|
||||
/// Register owned `ffi::PyObject` pointer in release pool.
|
||||
|
@ -275,13 +263,7 @@ impl<'p> Python<'p> {
|
|||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
match NonNull::new(ptr) {
|
||||
Some(p) => {
|
||||
let p = gil::register_owned(self, p);
|
||||
Ok(self.unchecked_downcast(p))
|
||||
}
|
||||
None => Err(PyErr::fetch(self)),
|
||||
}
|
||||
FromPyPointer::from_owned_ptr_or_err(self, ptr)
|
||||
}
|
||||
|
||||
/// Register owned `ffi::PyObject` pointer in release pool.
|
||||
|
@ -291,10 +273,7 @@ impl<'p> Python<'p> {
|
|||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
NonNull::new(ptr).map(|p| {
|
||||
let p = gil::register_owned(self, p);
|
||||
self.unchecked_downcast(p)
|
||||
})
|
||||
FromPyPointer::from_owned_ptr_or_opt(self, ptr)
|
||||
}
|
||||
|
||||
/// Register borrowed `ffi::PyObject` pointer in release pool.
|
||||
|
@ -304,13 +283,7 @@ impl<'p> Python<'p> {
|
|||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
match NonNull::new(ptr) {
|
||||
Some(p) => {
|
||||
let p = gil::register_borrowed(self, p);
|
||||
self.unchecked_downcast(p)
|
||||
}
|
||||
None => crate::err::panic_after_error(),
|
||||
}
|
||||
FromPyPointer::from_borrowed_ptr(self, ptr)
|
||||
}
|
||||
|
||||
/// Register borrowed `ffi::PyObject` pointer in release pool.
|
||||
|
@ -320,13 +293,7 @@ impl<'p> Python<'p> {
|
|||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
match NonNull::new(ptr) {
|
||||
Some(p) => {
|
||||
let p = gil::register_borrowed(self, p);
|
||||
self.unchecked_mut_downcast(p)
|
||||
}
|
||||
None => crate::err::panic_after_error(),
|
||||
}
|
||||
FromPyPointer::from_borrowed_ptr(self, ptr)
|
||||
}
|
||||
|
||||
/// Register borrowed `ffi::PyObject` pointer in release pool.
|
||||
|
@ -336,13 +303,7 @@ impl<'p> Python<'p> {
|
|||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
match NonNull::new(ptr) {
|
||||
Some(p) => {
|
||||
let p = gil::register_borrowed(self, p);
|
||||
Ok(self.unchecked_downcast(p))
|
||||
}
|
||||
None => Err(PyErr::fetch(self)),
|
||||
}
|
||||
FromPyPointer::from_borrowed_ptr_or_err(self, ptr)
|
||||
}
|
||||
|
||||
/// Register borrowed `ffi::PyObject` pointer in release pool.
|
||||
|
@ -352,10 +313,7 @@ impl<'p> Python<'p> {
|
|||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
NonNull::new(ptr).map(|p| {
|
||||
let p = gil::register_borrowed(self, p);
|
||||
self.unchecked_downcast(p)
|
||||
})
|
||||
FromPyPointer::from_borrowed_ptr_or_opt(self, ptr)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
|
|
@ -20,7 +20,7 @@ impl Reader {
|
|||
fn get_optional(&self, test: Option<i32>) -> PyResult<i32> {
|
||||
Ok(test.unwrap_or(10))
|
||||
}
|
||||
fn get_iter(slf: PyRef<Self>, keys: Py<PyBytes>) -> PyResult<Iter> {
|
||||
fn get_iter(slf: PyRef<Reader>, keys: Py<PyBytes>) -> PyResult<Iter> {
|
||||
Ok(Iter {
|
||||
reader: slf.into(),
|
||||
keys: keys,
|
||||
|
|
Loading…
Reference in a new issue