diff --git a/guide/src/class.md b/guide/src/class.md index 6e13d20f..45e42b89 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -351,7 +351,6 @@ that inherit native types. Even in such cases, you can unsafely get a base class # #[cfg(not(Py_LIMITED_API))] { # use pyo3::prelude::*; use pyo3::types::PyDict; -use pyo3::AsPyPointer; use std::collections::HashMap; #[pyclass(extends=PyDict)] diff --git a/guide/src/class/numeric.md b/guide/src/class/numeric.md index bd6a9a5c..a7ad9c2c 100644 --- a/guide/src/class/numeric.md +++ b/guide/src/class/numeric.md @@ -421,7 +421,6 @@ Let's create that helper function. The signature has to be `fn(&PyAny) -> PyResu use std::os::raw::c_ulong; use pyo3::prelude::*; use pyo3::ffi; -use pyo3::conversion::AsPyPointer; fn wrap(obj: &PyAny) -> Result { let py: Python<'_> = obj.py(); diff --git a/newsfragments/3359.added.md b/newsfragments/3359.added.md new file mode 100644 index 00000000..29ba5b01 --- /dev/null +++ b/newsfragments/3359.added.md @@ -0,0 +1 @@ +Add `as_ptr` and `into_ptr` inherent methods for `Py`, `PyAny`, `PyRef`, and `PyRefMut`. diff --git a/pyo3-macros-backend/src/quotes.rs b/pyo3-macros-backend/src/quotes.rs index b3b51404..3404c271 100644 --- a/pyo3-macros-backend/src/quotes.rs +++ b/pyo3-macros-backend/src/quotes.rs @@ -10,6 +10,6 @@ pub(crate) fn ok_wrap(obj: TokenStream) -> TokenStream { pub(crate) fn map_result_into_ptr(result: TokenStream) -> TokenStream { quote! { - #result.map(_pyo3::IntoPyPointer::into_ptr) + #result.map(_pyo3::PyObject::into_ptr) } } diff --git a/src/buffer.rs b/src/buffer.rs index f9dca60e..2c6ad126 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -18,9 +18,7 @@ // DEALINGS IN THE SOFTWARE. //! `PyBuffer` implementation -use crate::{ - err, exceptions::PyBufferError, ffi, AsPyPointer, FromPyObject, PyAny, PyResult, Python, -}; +use crate::{err, exceptions::PyBufferError, ffi, FromPyObject, PyAny, PyResult, Python}; use std::marker::PhantomData; use std::os::raw; use std::pin::Pin; diff --git a/src/callback.rs b/src/callback.rs index 611b1787..a56b268a 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -3,7 +3,6 @@ use crate::err::{PyErr, PyResult}; use crate::exceptions::PyOverflowError; use crate::ffi::{self, Py_hash_t}; -use crate::IntoPyPointer; use crate::{IntoPy, PyObject, Python}; use std::isize; use std::os::raw::c_int; diff --git a/src/conversion.rs b/src/conversion.rs index 2e9268e2..ba725ef4 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -20,7 +20,6 @@ use std::ptr::NonNull; /// /// ```rust /// use pyo3::prelude::*; -/// use pyo3::AsPyPointer; /// use pyo3::types::PyString; /// use pyo3::ffi; /// @@ -40,7 +39,6 @@ use std::ptr::NonNull; /// /// ```rust,no_run /// # use pyo3::prelude::*; -/// # use pyo3::AsPyPointer; /// # use pyo3::ffi; /// # /// Python::with_gil(|py| { @@ -632,7 +630,7 @@ mod test_no_clone {} #[cfg(test)] mod tests { use crate::types::{IntoPyDict, PyAny, PyDict, PyList}; - use crate::{AsPyPointer, PyObject, Python, ToPyObject}; + use crate::{PyObject, Python, ToPyObject}; use super::PyTryFrom; @@ -676,6 +674,7 @@ mod tests { #[test] fn test_option_as_ptr() { Python::with_gil(|py| { + use crate::AsPyPointer; let mut option: Option = None; assert_eq!(option.as_ptr(), std::ptr::null_mut()); diff --git a/src/conversions/chrono.rs b/src/conversions/chrono.rs index 43fe5809..10bbcd0f 100644 --- a/src/conversions/chrono.rs +++ b/src/conversions/chrono.rs @@ -45,7 +45,7 @@ use crate::types::{ timezone_utc, PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTzInfo, PyTzInfoAccess, PyUnicode, }; -use crate::{AsPyPointer, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject}; +use crate::{FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject}; use chrono::offset::{FixedOffset, Utc}; use chrono::{ DateTime, Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone, Timelike, diff --git a/src/conversions/num_bigint.rs b/src/conversions/num_bigint.rs index 83c8e8a8..0c61c2f0 100644 --- a/src/conversions/num_bigint.rs +++ b/src/conversions/num_bigint.rs @@ -48,8 +48,7 @@ //! ``` use crate::{ - ffi, types::*, AsPyPointer, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, - ToPyObject, + ffi, types::*, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject, }; use num_bigint::{BigInt, BigUint}; diff --git a/src/conversions/num_complex.rs b/src/conversions/num_complex.rs index 59e9b096..a6d76d0f 100644 --- a/src/conversions/num_complex.rs +++ b/src/conversions/num_complex.rs @@ -94,8 +94,7 @@ //! assert result == [complex(1,-1), complex(-2,0)] //! ``` use crate::{ - ffi, types::PyComplex, AsPyPointer, FromPyObject, PyAny, PyErr, PyObject, PyResult, Python, - ToPyObject, + ffi, types::PyComplex, FromPyObject, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; use num_complex::Complex; use std::os::raw::c_double; diff --git a/src/conversions/std/array.rs b/src/conversions/std/array.rs index 0cbf3eb6..302a4554 100644 --- a/src/conversions/std/array.rs +++ b/src/conversions/std/array.rs @@ -1,4 +1,3 @@ -use crate::conversion::{AsPyPointer, IntoPyPointer}; use crate::types::PySequence; use crate::{exceptions, PyErr}; use crate::{ diff --git a/src/conversions/std/num.rs b/src/conversions/std/num.rs index 3427942e..1f3bf673 100644 --- a/src/conversions/std/num.rs +++ b/src/conversions/std/num.rs @@ -1,8 +1,7 @@ #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ - exceptions, ffi, AsPyPointer, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, - ToPyObject, + exceptions, ffi, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; use std::convert::TryFrom; use std::num::{ diff --git a/src/conversions/std/osstr.rs b/src/conversions/std/osstr.rs index f91822a8..b2c14386 100644 --- a/src/conversions/std/osstr.rs +++ b/src/conversions/std/osstr.rs @@ -1,7 +1,5 @@ use crate::types::PyString; -use crate::{ - ffi, AsPyPointer, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject, -}; +use crate::{ffi, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject}; use std::borrow::Cow; use std::ffi::{OsStr, OsString}; #[cfg(not(windows))] diff --git a/src/conversions/std/path.rs b/src/conversions/std/path.rs index 0685e491..cc579e49 100644 --- a/src/conversions/std/path.rs +++ b/src/conversions/std/path.rs @@ -1,6 +1,5 @@ use crate::{ - ffi, AsPyPointer, FromPyObject, FromPyPointer, IntoPy, PyAny, PyObject, PyResult, Python, - ToPyObject, + ffi, FromPyObject, FromPyPointer, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject, }; use std::borrow::Cow; use std::ffi::OsString; diff --git a/src/err/err_state.rs b/src/err/err_state.rs index a7408efd..2a32387b 100644 --- a/src/err/err_state.rs +++ b/src/err/err_state.rs @@ -2,7 +2,7 @@ use crate::{ exceptions::{PyBaseException, PyTypeError}, ffi, types::{PyTraceback, PyType}, - AsPyPointer, IntoPy, IntoPyPointer, Py, PyAny, PyObject, PyTypeInfo, Python, + IntoPy, Py, PyAny, PyObject, PyTypeInfo, Python, }; #[derive(Clone)] @@ -118,12 +118,20 @@ impl PyErrState { ptype, pvalue, ptraceback, - } => (ptype.into_ptr(), pvalue.into_ptr(), ptraceback.into_ptr()), + } => ( + ptype.into_ptr(), + pvalue.map_or(std::ptr::null_mut(), Py::into_ptr), + ptraceback.map_or(std::ptr::null_mut(), Py::into_ptr), + ), PyErrState::Normalized(PyErrStateNormalized { ptype, pvalue, ptraceback, - }) => (ptype.into_ptr(), pvalue.into_ptr(), ptraceback.into_ptr()), + }) => ( + ptype.into_ptr(), + pvalue.into_ptr(), + ptraceback.map_or(std::ptr::null_mut(), Py::into_ptr), + ), } } diff --git a/src/err/mod.rs b/src/err/mod.rs index a824a383..2b6e0140 100644 --- a/src/err/mod.rs +++ b/src/err/mod.rs @@ -5,7 +5,7 @@ use crate::{ exceptions::{self, PyBaseException}, ffi, }; -use crate::{AsPyPointer, IntoPy, IntoPyPointer, Py, PyAny, PyObject, Python, ToPyObject}; +use crate::{IntoPy, Py, PyAny, PyObject, Python, ToPyObject}; use std::borrow::Cow; use std::cell::UnsafeCell; use std::ffi::CString; @@ -443,7 +443,7 @@ impl PyErr { self.get_type(py).as_ptr(), self.value(py).as_ptr(), self.traceback(py) - .map_or(std::ptr::null_mut(), PyTraceback::as_ptr), + .map_or(std::ptr::null_mut(), |traceback| traceback.as_ptr()), ) } } @@ -642,7 +642,7 @@ impl PyErr { // PyException_SetCause _steals_ a reference to cause, so must use .into_ptr() ffi::PyException_SetCause( value.as_ptr(), - cause.map_or(std::ptr::null_mut(), IntoPyPointer::into_ptr), + cause.map_or(std::ptr::null_mut(), Py::into_ptr), ); } } diff --git a/src/exceptions.rs b/src/exceptions.rs index 64a3a6f0..187c71b0 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -42,7 +42,6 @@ macro_rules! impl_exception_boilerplate { impl ::std::error::Error for $name { fn source(&self) -> ::std::option::Option<&(dyn ::std::error::Error + 'static)> { unsafe { - use $crate::AsPyPointer; let cause: &$crate::exceptions::PyBaseException = self .py() .from_owned_ptr_or_opt($crate::ffi::PyException_GetCause(self.as_ptr()))?; @@ -101,7 +100,6 @@ macro_rules! import_exception { impl $name { fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { use $crate::sync::GILOnceCell; - use $crate::AsPyPointer; static TYPE_OBJECT: GILOnceCell<$crate::Py<$crate::types::PyType>> = GILOnceCell::new(); @@ -240,7 +238,6 @@ macro_rules! create_exception_type_object { impl $name { fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { use $crate::sync::GILOnceCell; - use $crate::AsPyPointer; static TYPE_OBJECT: GILOnceCell<$crate::Py<$crate::types::PyType>> = GILOnceCell::new(); diff --git a/src/ffi/tests.rs b/src/ffi/tests.rs index 14f76cb4..b4f423ca 100644 --- a/src/ffi/tests.rs +++ b/src/ffi/tests.rs @@ -1,5 +1,5 @@ use crate::ffi::*; -use crate::{AsPyPointer, Python}; +use crate::Python; #[cfg(not(Py_LIMITED_API))] use crate::{ @@ -256,7 +256,7 @@ fn test_get_tzinfo() { crate::Python::with_gil(|py| { use crate::types::{PyDateTime, PyTime}; - use crate::{AsPyPointer, PyAny}; + use crate::PyAny; let utc = timezone_utc(py); diff --git a/src/gil.rs b/src/gil.rs index 69b511c9..d346ad95 100644 --- a/src/gil.rs +++ b/src/gil.rs @@ -507,7 +507,7 @@ fn decrement_gil_count() { #[cfg(test)] mod tests { use super::{gil_is_acquired, GILPool, GIL_COUNT, OWNED_OBJECTS, POOL}; - use crate::{ffi, gil, AsPyPointer, IntoPyPointer, PyObject, Python, ToPyObject}; + use crate::{ffi, gil, PyObject, Python, ToPyObject}; #[cfg(not(target_arch = "wasm32"))] use parking_lot::{const_mutex, Condvar, Mutex}; use std::ptr::NonNull; diff --git a/src/impl_/extract_argument.rs b/src/impl_/extract_argument.rs index 7da1b745..437ece48 100644 --- a/src/impl_/extract_argument.rs +++ b/src/impl_/extract_argument.rs @@ -697,7 +697,7 @@ fn push_parameter_list(msg: &mut String, parameter_names: &[&str]) { mod tests { use crate::{ types::{IntoPyDict, PyTuple}, - AsPyPointer, PyAny, Python, ToPyObject, + PyAny, Python, ToPyObject, }; use super::{push_parameter_list, FunctionDescription, NoVarargs, NoVarkeywords}; diff --git a/src/impl_/pyclass/lazy_type_object.rs b/src/impl_/pyclass/lazy_type_object.rs index 0e606b58..af52033a 100644 --- a/src/impl_/pyclass/lazy_type_object.rs +++ b/src/impl_/pyclass/lazy_type_object.rs @@ -12,7 +12,7 @@ use crate::{ pyclass::{create_type_object, PyClassTypeObject}, sync::{GILOnceCell, GILProtected}, types::PyType, - AsPyPointer, IntoPyPointer, PyClass, PyErr, PyMethodDefType, PyObject, PyResult, Python, + PyClass, PyErr, PyMethodDefType, PyObject, PyResult, Python, }; use super::PyClassItemsIter; diff --git a/src/impl_/trampoline.rs b/src/impl_/trampoline.rs index 1fcdebc2..5ae75e0f 100644 --- a/src/impl_/trampoline.rs +++ b/src/impl_/trampoline.rs @@ -11,7 +11,7 @@ use std::{ use crate::{ callback::PyCallbackOutput, ffi, impl_::panic::PanicTrap, methods::IPowModulo, - panic::PanicException, types::PyModule, GILPool, IntoPyPointer, Py, PyResult, Python, + panic::PanicException, types::PyModule, GILPool, Py, PyResult, Python, }; #[inline] diff --git a/src/instance.rs b/src/instance.rs index 8ae94b37..3a5e2b40 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -356,6 +356,34 @@ where } } +impl Py { + /// Returns the raw FFI pointer represented by self. + /// + /// # Safety + /// + /// Callers are responsible for ensuring that the pointer does not outlive self. + /// + /// The reference is borrowed; callers should not decrease the reference count + /// when they are finished with the pointer. + #[inline] + pub fn as_ptr(&self) -> *mut ffi::PyObject { + self.0.as_ptr() + } + + /// Returns an owned raw FFI pointer represented by self. + /// + /// # Safety + /// + /// The reference is owned; when finished the caller should either transfer ownership + /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). + #[inline] + pub fn into_ptr(self) -> *mut ffi::PyObject { + let ptr = self.0.as_ptr(); + std::mem::forget(self); + ptr + } +} + impl Py where T: PyClass, @@ -897,7 +925,7 @@ impl IntoPy for Py { } } -impl AsPyPointer for Py { +impl crate::AsPyPointer for Py { /// Gets the underlying FFI pointer, returns a borrowed pointer. #[inline] fn as_ptr(&self) -> *mut ffi::PyObject { diff --git a/src/marker.rs b/src/marker.rs index 4dd51000..ff96bae2 100644 --- a/src/marker.rs +++ b/src/marker.rs @@ -120,10 +120,7 @@ use crate::gil::{GILGuard, GILPool, SuspendGIL}; use crate::impl_::not_send::NotSend; use crate::types::{PyAny, PyDict, PyModule, PyString, PyType}; use crate::version::PythonVersionInfo; -use crate::{ - ffi, AsPyPointer, FromPyPointer, IntoPy, IntoPyPointer, Py, PyNativeType, PyObject, PyTryFrom, - PyTypeInfo, -}; +use crate::{ffi, FromPyPointer, IntoPy, Py, PyNativeType, PyObject, PyTryFrom, PyTypeInfo}; use std::ffi::{CStr, CString}; use std::marker::PhantomData; use std::os::raw::c_int; @@ -628,9 +625,9 @@ impl<'py> Python<'py> { } let globals = globals - .map(AsPyPointer::as_ptr) + .map(|dict| dict.as_ptr()) .unwrap_or_else(|| ffi::PyModule_GetDict(mptr)); - let locals = locals.map(AsPyPointer::as_ptr).unwrap_or(globals); + let locals = locals.map(|dict| dict.as_ptr()).unwrap_or(globals); let code_obj = ffi::Py_CompileString(code.as_ptr(), "\0".as_ptr() as _, start); if code_obj.is_null() { diff --git a/src/pycell.rs b/src/pycell.rs index 54a83676..3e53b172 100644 --- a/src/pycell.rs +++ b/src/pycell.rs @@ -603,7 +603,6 @@ impl fmt::Debug for PyCell { /// /// fn format(slf: PyRef<'_, Self>) -> String { /// // We can get *mut ffi::PyObject from PyRef -/// use pyo3::AsPyPointer; /// let refcnt = unsafe { pyo3::ffi::Py_REFCNT(slf.as_ptr()) }; /// // We can get &Self::BaseType by as_ref /// let basename = slf.as_ref().basename; @@ -638,6 +637,32 @@ where } } +impl<'p, T: PyClass> PyRef<'p, T> { + /// Returns the raw FFI pointer represented by self. + /// + /// # Safety + /// + /// Callers are responsible for ensuring that the pointer does not outlive self. + /// + /// The reference is borrowed; callers should not decrease the reference count + /// when they are finished with the pointer. + #[inline] + pub fn as_ptr(&self) -> *mut ffi::PyObject { + self.inner.as_ptr() + } + + /// Returns an owned raw FFI pointer represented by self. + /// + /// # Safety + /// + /// The reference is owned; when finished the caller should either transfer ownership + /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). + #[inline] + pub fn into_ptr(self) -> *mut ffi::PyObject { + self.inner.into_ptr() + } +} + impl<'p, T, U> PyRef<'p, T> where T: PyClass, @@ -771,6 +796,32 @@ where } } +impl<'p, T: PyClass> PyRefMut<'p, T> { + /// Returns the raw FFI pointer represented by self. + /// + /// # Safety + /// + /// Callers are responsible for ensuring that the pointer does not outlive self. + /// + /// The reference is borrowed; callers should not decrease the reference count + /// when they are finished with the pointer. + #[inline] + pub fn as_ptr(&self) -> *mut ffi::PyObject { + self.inner.as_ptr() + } + + /// Returns an owned raw FFI pointer represented by self. + /// + /// # Safety + /// + /// The reference is owned; when finished the caller should either transfer ownership + /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). + #[inline] + pub fn into_ptr(self) -> *mut ffi::PyObject { + self.inner.into_ptr() + } +} + impl<'p, T, U> PyRefMut<'p, T> where T: PyClass, @@ -1041,4 +1092,29 @@ mod tests { cell.swap(cell2); }) } + + #[test] + fn test_as_ptr() { + Python::with_gil(|py| { + let cell = PyCell::new(py, SomeClass(0)).unwrap(); + let ptr = cell.as_ptr(); + + assert_eq!(cell.borrow().as_ptr(), ptr); + assert_eq!(cell.borrow_mut().as_ptr(), ptr); + }) + } + + #[test] + fn test_into_ptr() { + Python::with_gil(|py| { + let cell = PyCell::new(py, SomeClass(0)).unwrap(); + let ptr = cell.as_ptr(); + + assert_eq!(cell.borrow().into_ptr(), ptr); + unsafe { ffi::Py_DECREF(ptr) }; + + assert_eq!(cell.borrow_mut().into_ptr(), ptr); + unsafe { ffi::Py_DECREF(ptr) }; + }) + } } diff --git a/src/pyclass.rs b/src/pyclass.rs index 84d1902e..5dd2d227 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -1,7 +1,7 @@ //! `PyClass` and related traits. use crate::{ - callback::IntoPyCallbackOutput, ffi, impl_::pyclass::PyClassImpl, IntoPy, IntoPyPointer, - PyCell, PyObject, PyResult, PyTypeInfo, Python, + callback::IntoPyCallbackOutput, ffi, impl_::pyclass::PyClassImpl, IntoPy, PyCell, PyObject, + PyResult, PyTypeInfo, Python, }; use std::{cmp::Ordering, os::raw::c_int}; diff --git a/src/pyclass_init.rs b/src/pyclass_init.rs index 534e5fed..63761f43 100644 --- a/src/pyclass_init.rs +++ b/src/pyclass_init.rs @@ -1,7 +1,7 @@ //! Contains initialization utilities for `#[pyclass]`. use crate::callback::IntoPyCallbackOutput; use crate::impl_::pyclass::{PyClassBaseType, PyClassDict, PyClassThreadChecker, PyClassWeakRef}; -use crate::{ffi, IntoPyPointer, Py, PyCell, PyClass, PyErr, PyResult, Python}; +use crate::{ffi, Py, PyCell, PyClass, PyErr, PyResult, Python}; use crate::{ ffi::PyTypeObject, pycell::{ diff --git a/src/type_object.rs b/src/type_object.rs index 3098b072..f867dcca 100644 --- a/src/type_object.rs +++ b/src/type_object.rs @@ -1,7 +1,7 @@ //! Python type object information use crate::types::{PyAny, PyType}; -use crate::{ffi, AsPyPointer, PyNativeType, Python}; +use crate::{ffi, PyNativeType, Python}; /// `T: PyLayout` represents that `T` is a concrete representation of `U` in the Python heap. /// E.g., `PyCell` is a concrete representation of all `pyclass`es, and `ffi::PyObject` diff --git a/src/types/any.rs b/src/types/any.rs index d4678fd8..0192bfa3 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -1,5 +1,5 @@ use crate::class::basic::CompareOp; -use crate::conversion::{AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, PyTryFrom, ToPyObject}; +use crate::conversion::{AsPyPointer, FromPyObject, IntoPy, PyTryFrom, ToPyObject}; use crate::err::{PyDowncastError, PyErr, PyResult}; use crate::exceptions::{PyAttributeError, PyTypeError}; use crate::type_object::PyTypeInfo; @@ -36,7 +36,7 @@ use std::os::raw::c_int; #[repr(transparent)] pub struct PyAny(UnsafeCell); -impl crate::AsPyPointer for PyAny { +impl AsPyPointer for PyAny { #[inline] fn as_ptr(&self) -> *mut ffi::PyObject { self.0.get() @@ -511,12 +511,11 @@ impl PyAny { let py = self.py(); let args = args.into_py(py); - let kwargs = kwargs.into_ptr(); + let kwargs = kwargs.map_or(std::ptr::null_mut(), |kwargs| kwargs.as_ptr()); unsafe { let return_value = ffi::PyObject_Call(self.as_ptr(), args.as_ptr(), kwargs); let ret = py.from_owned_ptr_or_err(return_value); - ffi::Py_XDECREF(kwargs); ret } } @@ -632,12 +631,11 @@ impl PyAny { let callee = self.getattr(name)?; let args: Py = args.into_py(py); - let kwargs = kwargs.into_ptr(); + let kwargs = kwargs.map_or(std::ptr::null_mut(), |kwargs| kwargs.as_ptr()); unsafe { let result_ptr = ffi::PyObject_Call(callee.as_ptr(), args.as_ptr(), kwargs); let result = py.from_owned_ptr_or_err(result_ptr); - ffi::Py_XDECREF(kwargs); result } } @@ -1065,6 +1063,31 @@ impl PyAny { PyNativeType::py(self) } + /// Returns the raw FFI pointer represented by self. + /// + /// # Safety + /// + /// Callers are responsible for ensuring that the pointer does not outlive self. + /// + /// The reference is borrowed; callers should not decrease the reference count + /// when they are finished with the pointer. + #[inline] + pub fn as_ptr(&self) -> *mut ffi::PyObject { + self as *const PyAny as *mut ffi::PyObject + } + + /// Returns an owned raw FFI pointer represented by self. + /// + /// # Safety + /// + /// The reference is owned; when finished the caller should either transfer ownership + /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). + #[inline] + pub fn into_ptr(&self) -> *mut ffi::PyObject { + // Safety: self.as_ptr() returns a valid non-null pointer + unsafe { ffi::_Py_NewRef(self.as_ptr()) } + } + /// Return a proxy object that delegates method calls to a parent or sibling class of type. /// /// This is equivalent to the Python expression `super()` diff --git a/src/types/boolobject.rs b/src/types/boolobject.rs index 270eadee..1f42db90 100644 --- a/src/types/boolobject.rs +++ b/src/types/boolobject.rs @@ -1,8 +1,6 @@ #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; -use crate::{ - ffi, AsPyPointer, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject, -}; +use crate::{ffi, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject}; /// Represents a Python `bool`. #[repr(transparent)] diff --git a/src/types/bytes.rs b/src/types/bytes.rs index a215ce92..ef26abf0 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -1,4 +1,4 @@ -use crate::{ffi, AsPyPointer, FromPyObject, IntoPy, Py, PyAny, PyResult, Python, ToPyObject}; +use crate::{ffi, FromPyObject, IntoPy, Py, PyAny, PyResult, Python, ToPyObject}; use std::borrow::Cow; use std::ops::Index; use std::os::raw::c_char; diff --git a/src/types/capsule.rs b/src/types/capsule.rs index 55484dce..f97320eb 100644 --- a/src/types/capsule.rs +++ b/src/types/capsule.rs @@ -1,5 +1,5 @@ use crate::Python; -use crate::{ffi, AsPyPointer, PyAny}; +use crate::{ffi, PyAny}; use crate::{pyobject_native_type_core, PyErr, PyResult}; use std::ffi::{CStr, CString}; use std::os::raw::{c_char, c_int, c_void}; diff --git a/src/types/complex.rs b/src/types/complex.rs index fec137a6..b722508b 100644 --- a/src/types/complex.rs +++ b/src/types/complex.rs @@ -1,4 +1,4 @@ -use crate::{ffi, AsPyPointer, PyAny, Python}; +use crate::{ffi, PyAny, Python}; use std::os::raw::c_double; /// Represents a Python [`complex`](https://docs.python.org/3/library/functions.html#complex) object. diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 2fb75ecb..a2f9f5ce 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -21,7 +21,7 @@ use crate::ffi::{ }; use crate::instance::PyNativeType; use crate::types::PyTuple; -use crate::{AsPyPointer, IntoPy, Py, PyAny, Python}; +use crate::{IntoPy, Py, PyAny, Python}; use std::os::raw::c_int; fn ensure_datetime_api(_py: Python<'_>) -> &'static PyDateTime_CAPI { diff --git a/src/types/dict.rs b/src/types/dict.rs index 1d3ac185..3dacae1d 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -2,9 +2,7 @@ use super::PyMapping; use crate::err::{self, PyErr, PyResult}; use crate::ffi::Py_ssize_t; use crate::types::{PyAny, PyList}; -#[cfg(not(PyPy))] -use crate::IntoPyPointer; -use crate::{ffi, AsPyPointer, PyObject, Python, ToPyObject}; +use crate::{ffi, PyObject, Python, ToPyObject}; /// Represents a Python `dict`. #[repr(transparent)] diff --git a/src/types/floatob.rs b/src/types/floatob.rs index 4ac425d7..252c5757 100644 --- a/src/types/floatob.rs +++ b/src/types/floatob.rs @@ -1,8 +1,7 @@ #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ - ffi, AsPyPointer, FromPyObject, IntoPy, PyAny, PyErr, PyNativeType, PyObject, PyResult, Python, - ToPyObject, + ffi, FromPyObject, IntoPy, PyAny, PyErr, PyNativeType, PyObject, PyResult, Python, ToPyObject, }; use std::os::raw::c_double; diff --git a/src/types/frozenset.rs b/src/types/frozenset.rs index 560f762e..d27e87ef 100644 --- a/src/types/frozenset.rs +++ b/src/types/frozenset.rs @@ -4,7 +4,7 @@ use crate::{ err::{self, PyErr, PyResult}, Py, PyObject, }; -use crate::{ffi, AsPyPointer, PyAny, Python, ToPyObject}; +use crate::{ffi, PyAny, Python, ToPyObject}; use std::ptr; diff --git a/src/types/function.rs b/src/types/function.rs index 46949704..f40f0189 100644 --- a/src/types/function.rs +++ b/src/types/function.rs @@ -5,7 +5,6 @@ use crate::{ ffi, impl_::pymethods::{self, PyMethodDef}, types::{PyCapsule, PyDict, PyTuple}, - AsPyPointer, }; use std::cell::UnsafeCell; use std::ffi::CStr; diff --git a/src/types/iterator.rs b/src/types/iterator.rs index 7b411bde..6bacb438 100644 --- a/src/types/iterator.rs +++ b/src/types/iterator.rs @@ -1,4 +1,4 @@ -use crate::{ffi, AsPyPointer, IntoPyPointer, Py, PyAny, PyErr, PyNativeType, PyResult, Python}; +use crate::{ffi, AsPyPointer, Py, PyAny, PyErr, PyNativeType, PyResult, Python}; use crate::{PyDowncastError, PyTryFrom}; /// A Python iterator object. diff --git a/src/types/list.rs b/src/types/list.rs index b5bbf70f..71261ba6 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -5,7 +5,7 @@ use crate::err::{self, PyResult}; use crate::ffi::{self, Py_ssize_t}; use crate::internal_tricks::get_ssize_index; use crate::types::{PySequence, PyTuple}; -use crate::{AsPyPointer, IntoPyPointer, Py, PyAny, PyObject, Python, ToPyObject}; +use crate::{Py, PyAny, PyObject, Python, ToPyObject}; /// Represents a Python `list`. #[repr(transparent)] diff --git a/src/types/mapping.rs b/src/types/mapping.rs index b947f619..22e86d61 100644 --- a/src/types/mapping.rs +++ b/src/types/mapping.rs @@ -2,7 +2,7 @@ use crate::err::{PyDowncastError, PyResult}; use crate::sync::GILOnceCell; use crate::type_object::PyTypeInfo; use crate::types::{PyAny, PyDict, PySequence, PyType}; -use crate::{ffi, AsPyPointer, IntoPyPointer, Py, PyNativeType, PyTryFrom, Python, ToPyObject}; +use crate::{ffi, Py, PyNativeType, PyTryFrom, Python, ToPyObject}; /// Represents a reference to a Python object supporting the mapping protocol. #[repr(transparent)] diff --git a/src/types/mod.rs b/src/types/mod.rs index eb862655..4d8b0513 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -114,7 +114,6 @@ macro_rules! pyobject_native_type_base( { #[inline] fn to_object(&self, py: $crate::Python<'_>) -> $crate::PyObject { - use $crate::AsPyPointer; unsafe { $crate::PyObject::from_borrowed_ptr(py, self.as_ptr()) } } } @@ -156,7 +155,6 @@ macro_rules! pyobject_native_type_named ( impl<$($generics,)*> $crate::IntoPy<$crate::Py<$name>> for &'_ $name { #[inline] fn into_py(self, py: $crate::Python<'_>) -> $crate::Py<$name> { - use $crate::AsPyPointer; unsafe { $crate::Py::from_borrowed_ptr(py, self.as_ptr()) } } } @@ -164,7 +162,6 @@ macro_rules! pyobject_native_type_named ( impl<$($generics,)*> ::std::convert::From<&'_ $name> for $crate::Py<$name> { #[inline] fn from(other: &$name) -> Self { - use $crate::AsPyPointer; use $crate::PyNativeType; unsafe { $crate::Py::from_borrowed_ptr(other.py(), other.as_ptr()) } } @@ -205,7 +202,6 @@ macro_rules! pyobject_native_type_info( $( #[inline] fn is_type_of(ptr: &$crate::PyAny) -> bool { - use $crate::AsPyPointer; #[allow(unused_unsafe)] unsafe { $checkfunction(ptr.as_ptr()) > 0 } } diff --git a/src/types/module.rs b/src/types/module.rs index 02881a0e..5f9ed1f6 100644 --- a/src/types/module.rs +++ b/src/types/module.rs @@ -4,7 +4,7 @@ use crate::exceptions; use crate::ffi; use crate::pyclass::PyClass; use crate::types::{PyAny, PyCFunction, PyDict, PyList, PyString}; -use crate::{AsPyPointer, IntoPy, Py, PyObject, Python}; +use crate::{IntoPy, Py, PyObject, Python}; use std::ffi::{CStr, CString}; use std::str; diff --git a/src/types/sequence.rs b/src/types/sequence.rs index e56c7a31..4772d7f1 100644 --- a/src/types/sequence.rs +++ b/src/types/sequence.rs @@ -7,8 +7,8 @@ use crate::sync::GILOnceCell; use crate::type_object::PyTypeInfo; use crate::types::{PyAny, PyList, PyString, PyTuple, PyType}; use crate::{ffi, PyNativeType, PyObject, ToPyObject}; -use crate::{AsPyPointer, IntoPyPointer, Py, Python}; use crate::{FromPyObject, PyTryFrom}; +use crate::{Py, Python}; /// Represents a reference to a Python object supporting the sequence protocol. #[repr(transparent)] @@ -388,7 +388,7 @@ impl Py { #[cfg(test)] mod tests { use crate::types::{PyList, PySequence, PyTuple}; - use crate::{AsPyPointer, Py, PyObject, Python, ToPyObject}; + use crate::{Py, PyObject, Python, ToPyObject}; fn get_object() -> PyObject { // Convenience function for getting a single unique object diff --git a/src/types/set.rs b/src/types/set.rs index b6176fee..e10979c2 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -4,7 +4,7 @@ use crate::{ err::{self, PyErr, PyResult}, Py, }; -use crate::{ffi, AsPyPointer, PyAny, PyObject, Python, ToPyObject}; +use crate::{ffi, PyAny, PyObject, Python, ToPyObject}; use std::ptr; /// Represents a Python `set` diff --git a/src/types/slice.rs b/src/types/slice.rs index c0bcc555..53e4f4af 100644 --- a/src/types/slice.rs +++ b/src/types/slice.rs @@ -1,6 +1,6 @@ use crate::err::{PyErr, PyResult}; use crate::ffi::{self, Py_ssize_t}; -use crate::{AsPyPointer, PyAny, PyObject, Python, ToPyObject}; +use crate::{PyAny, PyObject, Python, ToPyObject}; use std::os::raw::c_long; /// Represents a Python `slice`. diff --git a/src/types/string.rs b/src/types/string.rs index 9c4139b9..44272101 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -1,7 +1,7 @@ #[cfg(not(Py_LIMITED_API))] use crate::exceptions::PyUnicodeDecodeError; use crate::types::PyBytes; -use crate::{ffi, AsPyPointer, PyAny, PyResult, Python}; +use crate::{ffi, PyAny, PyResult, Python}; use std::borrow::Cow; use std::os::raw::c_char; use std::str; diff --git a/src/types/traceback.rs b/src/types/traceback.rs index 6b6dd312..67e0e564 100644 --- a/src/types/traceback.rs +++ b/src/types/traceback.rs @@ -1,7 +1,7 @@ use crate::err::{error_on_minusone, PyResult}; use crate::ffi; use crate::types::PyString; -use crate::{AsPyPointer, PyAny}; +use crate::PyAny; /// Represents a Python traceback. #[repr(transparent)] diff --git a/src/types/tuple.rs b/src/types/tuple.rs index ddaec423..0165061a 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -8,8 +8,7 @@ use crate::internal_tricks::get_ssize_index; use crate::types::PyList; use crate::types::PySequence; use crate::{ - exceptions, AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, Py, PyAny, PyErr, PyObject, - PyResult, Python, ToPyObject, + exceptions, FromPyObject, IntoPy, Py, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; #[inline] diff --git a/src/types/typeobject.rs b/src/types/typeobject.rs index 105d6ef0..67eeb566 100644 --- a/src/types/typeobject.rs +++ b/src/types/typeobject.rs @@ -1,5 +1,5 @@ use crate::err::{self, PyResult}; -use crate::{ffi, AsPyPointer, PyAny, PyTypeInfo, Python}; +use crate::{ffi, PyAny, PyTypeInfo, Python}; /// Represents a reference to a Python `type object`. #[repr(transparent)] diff --git a/tests/test_buffer.rs b/tests/test_buffer.rs index 7a5dc41d..3e5d59f3 100644 --- a/tests/test_buffer.rs +++ b/tests/test_buffer.rs @@ -1,7 +1,7 @@ #![cfg(feature = "macros")] #![cfg(any(not(Py_LIMITED_API), Py_3_11))] -use pyo3::{buffer::PyBuffer, exceptions::PyBufferError, ffi, prelude::*, AsPyPointer}; +use pyo3::{buffer::PyBuffer, exceptions::PyBufferError, ffi, prelude::*}; use std::{ ffi::CStr, os::raw::{c_int, c_void}, diff --git a/tests/test_buffer_protocol.rs b/tests/test_buffer_protocol.rs index a9c0ff8e..b7e69662 100644 --- a/tests/test_buffer_protocol.rs +++ b/tests/test_buffer_protocol.rs @@ -6,7 +6,6 @@ use pyo3::exceptions::PyBufferError; use pyo3::ffi; use pyo3::prelude::*; use pyo3::types::IntoPyDict; -use pyo3::AsPyPointer; use std::ffi::CString; use std::os::raw::{c_int, c_void}; use std::ptr; diff --git a/tests/test_datetime.rs b/tests/test_datetime.rs index 37b2d060..32163abe 100644 --- a/tests/test_datetime.rs +++ b/tests/test_datetime.rs @@ -36,7 +36,7 @@ fn _get_subclasses<'p>( macro_rules! assert_check_exact { ($check_func:ident, $check_func_exact:ident, $obj: expr) => { unsafe { - use pyo3::{ffi::*, AsPyPointer}; + use pyo3::ffi::*; assert!($check_func(($obj).as_ptr()) != 0); assert!($check_func_exact(($obj).as_ptr()) != 0); } @@ -46,7 +46,7 @@ macro_rules! assert_check_exact { macro_rules! assert_check_only { ($check_func:ident, $check_func_exact:ident, $obj: expr) => { unsafe { - use pyo3::{ffi::*, AsPyPointer}; + use pyo3::ffi::*; assert!($check_func(($obj).as_ptr()) != 0); assert!($check_func_exact(($obj).as_ptr()) == 0); } diff --git a/tests/test_exceptions.rs b/tests/test_exceptions.rs index c0cf57a9..d49a6d8c 100644 --- a/tests/test_exceptions.rs +++ b/tests/test_exceptions.rs @@ -101,7 +101,7 @@ fn test_exception_nosegfault() { #[cfg(Py_3_8)] fn test_write_unraisable() { use common::UnraisableCapture; - use pyo3::{exceptions::PyRuntimeError, ffi, AsPyPointer}; + use pyo3::{exceptions::PyRuntimeError, ffi}; Python::with_gil(|py| { let capture = UnraisableCapture::install(py); diff --git a/tests/test_gc.rs b/tests/test_gc.rs index c84d6784..ec824f20 100644 --- a/tests/test_gc.rs +++ b/tests/test_gc.rs @@ -3,7 +3,7 @@ use pyo3::class::PyTraverseError; use pyo3::class::PyVisit; use pyo3::prelude::*; -use pyo3::{py_run, AsPyPointer, PyCell, PyTryInto}; +use pyo3::{py_run, PyCell, PyTryInto}; use std::cell::Cell; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; diff --git a/tests/test_sequence.rs b/tests/test_sequence.rs index 8dcbbe19..247ae8dc 100644 --- a/tests/test_sequence.rs +++ b/tests/test_sequence.rs @@ -2,7 +2,7 @@ use pyo3::exceptions::{PyIndexError, PyValueError}; use pyo3::types::{IntoPyDict, PyList, PyMapping, PySequence}; -use pyo3::{ffi, prelude::*, AsPyPointer}; +use pyo3::{ffi, prelude::*}; use pyo3::py_run;