Rework Py methods and documentation
This commit is contained in:
parent
20959ecc92
commit
be239d405f
|
@ -190,7 +190,7 @@ pub fn add_fn_to_module(
|
|||
};
|
||||
|
||||
let function = unsafe {
|
||||
pyo3::PyObject::from_owned_ptr_or_panic(
|
||||
pyo3::PyObject::from_owned_ptr(
|
||||
py,
|
||||
pyo3::ffi::PyCFunction_New(
|
||||
Box::into_raw(Box::new(_def.as_method_def())),
|
||||
|
|
231
src/instance.rs
231
src/instance.rs
|
@ -115,64 +115,6 @@ where
|
|||
}
|
||||
|
||||
impl<T> Py<T> {
|
||||
/// For internal conversions
|
||||
pub(crate) unsafe fn from_not_null(ptr: NonNull<ffi::PyObject>) -> Self {
|
||||
Self(ptr, PhantomData)
|
||||
}
|
||||
|
||||
/// Creates a `Py<T>` instance for the given FFI pointer.
|
||||
///
|
||||
/// This moves ownership over the pointer into the `Py<T>`.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(_py: Python, ptr: *mut ffi::PyObject) -> Py<T> {
|
||||
debug_assert!(
|
||||
!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0,
|
||||
format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr))
|
||||
);
|
||||
Py(NonNull::new_unchecked(ptr), PhantomData)
|
||||
}
|
||||
|
||||
/// Creates a `Py<T>` instance for the given FFI pointer.
|
||||
///
|
||||
/// Panics if the pointer is NULL.
|
||||
/// Undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_panic(_py: Python, ptr: *mut ffi::PyObject) -> Py<T> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => Py(nonnull_ptr, PhantomData),
|
||||
None => {
|
||||
crate::err::panic_after_error(_py);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct `Py<T>` from the result of a Python FFI call that
|
||||
///
|
||||
/// Returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is NULL.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Py<T>> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => Ok(Py(nonnull_ptr, PhantomData)),
|
||||
None => Err(PyErr::fetch(py)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `Py<T>` instance for the given Python FFI pointer.
|
||||
///
|
||||
/// Calls `Py_INCREF()` on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(_py: Python, ptr: *mut ffi::PyObject) -> Py<T> {
|
||||
debug_assert!(
|
||||
!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0,
|
||||
format!("REFCNT: {:?} - {:?}", ptr, ffi::Py_REFCNT(ptr))
|
||||
);
|
||||
ffi::Py_INCREF(ptr);
|
||||
Py(NonNull::new_unchecked(ptr), PhantomData)
|
||||
}
|
||||
|
||||
/// Gets the reference count of the `ffi::PyObject` pointer.
|
||||
#[inline]
|
||||
pub fn get_refcnt(&self, _py: Python) -> isize {
|
||||
|
@ -185,47 +127,6 @@ impl<T> Py<T> {
|
|||
unsafe { Py::from_borrowed_ptr(py, self.0.as_ptr()) }
|
||||
}
|
||||
|
||||
/// Returns the inner pointer without decreasing the refcount.
|
||||
///
|
||||
/// This will eventually move into its own trait.
|
||||
pub(crate) fn into_non_null(self) -> NonNull<ffi::PyObject> {
|
||||
let pointer = self.0;
|
||||
mem::forget(self);
|
||||
pointer
|
||||
}
|
||||
|
||||
/// Constructs a `PyObject` from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `None` if the pointer is NULL.
|
||||
pub unsafe fn from_owned_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => Some(Py(nonnull_ptr, PhantomData)),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `PyObject` instance for the given Python FFI pointer.
|
||||
/// Calls `Py_INCREF()` on the ptr.
|
||||
/// Returns `Err(PyErr)` if the pointer is NULL.
|
||||
pub unsafe fn from_borrowed_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Self> {
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(Self::from_borrowed_ptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `PyObject` instance for the given Python FFI pointer.
|
||||
/// Calls `Py_INCREF()` on the ptr.
|
||||
/// Returns `None` if the pointer is NULL.
|
||||
pub unsafe fn from_borrowed_ptr_or_opt(py: Python, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Self::from_borrowed_ptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the object is considered to be None.
|
||||
///
|
||||
/// This is equivalent to the Python expression `self is None`.
|
||||
|
@ -245,16 +146,6 @@ impl<T> Py<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
///
|
||||
/// This can cast only to native Python types, not types implemented in Rust.
|
||||
pub fn cast_as<'p, D>(&'p self, py: Python<'p>) -> Result<&'p D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom<'p>,
|
||||
{
|
||||
D::try_from(unsafe { py.from_borrowed_ptr::<PyAny>(self.as_ptr()) })
|
||||
}
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
///
|
||||
/// This is a wrapper function around `FromPyObject::extract()`.
|
||||
|
@ -355,6 +246,113 @@ impl<T> Py<T> {
|
|||
pub fn call_method0(&self, py: Python, name: &str) -> PyResult<PyObject> {
|
||||
self.call_method(py, name, (), None)
|
||||
}
|
||||
|
||||
/// Create a `Py<T>` instance by taking ownership of the given FFI pointer.
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` must be a pointer to a Python object of type T.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `ptr` is null.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(py: Python, ptr: *mut ffi::PyObject) -> Py<T> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => Py(nonnull_ptr, PhantomData),
|
||||
None => crate::err::panic_after_error(py),
|
||||
}
|
||||
}
|
||||
|
||||
/// Deprecated alias for [`from_owned_ptr`](#method.from_owned_ptr).
|
||||
#[inline]
|
||||
#[deprecated = "this is a deprecated alias for Py::from_owned_ptr"]
|
||||
pub unsafe fn from_owned_ptr_or_panic(py: Python, ptr: *mut ffi::PyObject) -> Py<T> {
|
||||
Py::from_owned_ptr(py, ptr)
|
||||
}
|
||||
|
||||
/// Create a `Py<T>` instance by taking ownership of the given FFI pointer.
|
||||
///
|
||||
/// If `ptr` is null then the current Python exception is fetched as a `PyErr`.
|
||||
///
|
||||
/// # Safety
|
||||
/// If non-null, `ptr` must be a pointer to a Python object of type T.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Py<T>> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => Ok(Py(nonnull_ptr, PhantomData)),
|
||||
None => Err(PyErr::fetch(py)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `Py<T>` instance by taking ownership of the given FFI pointer.
|
||||
///
|
||||
/// If `ptr` is null then `None` is returned.
|
||||
///
|
||||
/// # Safety
|
||||
/// If non-null, `ptr` must be a pointer to a Python object of type T.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => Some(Py(nonnull_ptr, PhantomData)),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `Py<T>` instance by creating a new reference from the given FFI pointer.
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` must be a pointer to a Python object of type T.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `ptr` is null.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(py: Python, ptr: *mut ffi::PyObject) -> Py<T> {
|
||||
match Self::from_borrowed_ptr_or_opt(py, ptr) {
|
||||
Some(slf) => slf,
|
||||
None => crate::err::panic_after_error(py),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `Py<T>` instance by creating a new reference from the given FFI pointer.
|
||||
///
|
||||
/// If `ptr` is null then the current Python exception is fetched as a `PyErr`.
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` must be a pointer to a Python object of type T.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Self> {
|
||||
Self::from_borrowed_ptr_or_opt(py, ptr).ok_or_else(|| PyErr::fetch(py))
|
||||
}
|
||||
|
||||
/// Create a `Py<T>` instance by creating a new reference from the given FFI pointer.
|
||||
///
|
||||
/// If `ptr` is null then `None` is returned.
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` must be a pointer to a Python object of type T.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|nonnull_ptr| {
|
||||
ffi::Py_INCREF(ptr);
|
||||
Py(nonnull_ptr, PhantomData)
|
||||
})
|
||||
}
|
||||
|
||||
/// For internal conversions.
|
||||
///
|
||||
/// # Safety
|
||||
/// `ptr` must point to a Python object of type T.
|
||||
#[inline]
|
||||
unsafe fn from_non_null(ptr: NonNull<ffi::PyObject>) -> Self {
|
||||
Self(ptr, PhantomData)
|
||||
}
|
||||
|
||||
/// Returns the inner pointer without decreasing the refcount.
|
||||
#[inline]
|
||||
fn into_non_null(self) -> NonNull<ffi::PyObject> {
|
||||
let pointer = self.0;
|
||||
mem::forget(self);
|
||||
pointer
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves `&'py` types from `Py<T>` or `PyObject`.
|
||||
|
@ -421,7 +419,7 @@ impl<T> IntoPy<PyObject> for Py<T> {
|
|||
/// Consumes `self` without calling `Py_DECREF()`.
|
||||
#[inline]
|
||||
fn into_py(self, _py: Python) -> PyObject {
|
||||
unsafe { PyObject::from_not_null(self.into_non_null()) }
|
||||
unsafe { PyObject::from_non_null(self.into_non_null()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -566,6 +564,19 @@ impl<T> std::fmt::Debug for Py<T> {
|
|||
/// See the documentation for [`Py`](struct.Py.html).
|
||||
pub type PyObject = Py<PyAny>;
|
||||
|
||||
impl PyObject {
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
///
|
||||
/// This can cast only to native Python types, not types implemented in Rust. For a more
|
||||
/// flexible alternative, see [`Py::extract`](struct.Py.html#method.extract).
|
||||
pub fn cast_as<'p, D>(&'p self, py: Python<'p>) -> Result<&'p D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom<'p>,
|
||||
{
|
||||
D::try_from(unsafe { py.from_borrowed_ptr::<PyAny>(self.as_ptr()) })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Py, PyObject};
|
||||
|
|
|
@ -149,7 +149,7 @@ mod complex_conversion {
|
|||
unsafe {
|
||||
let raw_obj =
|
||||
ffi::PyComplex_FromDoubles(self.re as c_double, self.im as c_double);
|
||||
PyObject::from_owned_ptr_or_panic(py, raw_obj)
|
||||
PyObject::from_owned_ptr(py, raw_obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ where
|
|||
let obj = e.to_object(py).into_ptr();
|
||||
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
|
||||
}
|
||||
PyObject::from_owned_ptr_or_panic(py, ptr)
|
||||
PyObject::from_owned_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ where
|
|||
let obj = e.into_py(py).into_ptr();
|
||||
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
|
||||
}
|
||||
PyObject::from_owned_ptr_or_panic(py, ptr)
|
||||
PyObject::from_owned_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,17 +62,13 @@ macro_rules! int_fits_c_long {
|
|||
impl ToPyObject for $rust_type {
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))]
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
unsafe {
|
||||
PyObject::from_owned_ptr_or_panic(py, ffi::PyLong_FromLong(*self as c_long))
|
||||
}
|
||||
unsafe { PyObject::from_owned_ptr(py, ffi::PyLong_FromLong(*self as c_long)) }
|
||||
}
|
||||
}
|
||||
impl IntoPy<PyObject> for $rust_type {
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))]
|
||||
fn into_py(self, py: Python) -> PyObject {
|
||||
unsafe {
|
||||
PyObject::from_owned_ptr_or_panic(py, ffi::PyLong_FromLong(self as c_long))
|
||||
}
|
||||
unsafe { PyObject::from_owned_ptr(py, ffi::PyLong_FromLong(self as c_long)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,13 +97,13 @@ macro_rules! int_convert_u64_or_i64 {
|
|||
impl ToPyObject for $rust_type {
|
||||
#[inline]
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
unsafe { PyObject::from_owned_ptr_or_panic(py, $pylong_from_ll_or_ull(*self)) }
|
||||
unsafe { PyObject::from_owned_ptr(py, $pylong_from_ll_or_ull(*self)) }
|
||||
}
|
||||
}
|
||||
impl IntoPy<PyObject> for $rust_type {
|
||||
#[inline]
|
||||
fn into_py(self, py: Python) -> PyObject {
|
||||
unsafe { PyObject::from_owned_ptr_or_panic(py, $pylong_from_ll_or_ull(self)) }
|
||||
unsafe { PyObject::from_owned_ptr(py, $pylong_from_ll_or_ull(self)) }
|
||||
}
|
||||
}
|
||||
impl<'source> FromPyObject<'source> for $rust_type {
|
||||
|
@ -194,7 +190,7 @@ mod int128_conversion {
|
|||
IS_LITTLE_ENDIAN,
|
||||
$is_signed,
|
||||
);
|
||||
PyObject::from_owned_ptr_or_panic(py, obj)
|
||||
PyObject::from_owned_ptr(py, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +274,7 @@ mod int128_conversion {
|
|||
super::IS_LITTLE_ENDIAN,
|
||||
0,
|
||||
);
|
||||
let obj = PyObject::from_owned_ptr_or_panic(py, obj);
|
||||
let obj = PyObject::from_owned_ptr(py, obj);
|
||||
let err = obj.extract::<u128>(py).unwrap_err();
|
||||
assert!(err.is_instance::<exceptions::PyOverflowError>(py));
|
||||
}
|
||||
|
@ -319,7 +315,7 @@ mod bigint_conversion {
|
|||
1,
|
||||
$is_signed,
|
||||
);
|
||||
PyObject::from_owned_ptr_or_panic(py, obj)
|
||||
PyObject::from_owned_ptr(py, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
|
|||
unsafe {
|
||||
let ptr = ffi::PyTuple_New($length);
|
||||
$(ffi::PyTuple_SetItem(ptr, $n, self.$n.to_object(py).into_ptr());)+
|
||||
PyObject::from_owned_ptr_or_panic(py, ptr)
|
||||
PyObject::from_owned_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
|
|||
unsafe {
|
||||
let ptr = ffi::PyTuple_New($length);
|
||||
$(ffi::PyTuple_SetItem(ptr, $n, self.$n.into_py(py).into_ptr());)+
|
||||
PyObject::from_owned_ptr_or_panic(py, ptr)
|
||||
PyObject::from_owned_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
|
|||
unsafe {
|
||||
let ptr = ffi::PyTuple_New($length);
|
||||
$(ffi::PyTuple_SetItem(ptr, $n, self.$n.into_py(py).into_ptr());)+
|
||||
Py::from_owned_ptr_or_panic(py, ptr)
|
||||
Py::from_owned_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue