diff --git a/src/types/weakref/anyref.rs b/src/types/weakref/anyref.rs index 06d91ea024e..53a3a50188c 100644 --- a/src/types/weakref/anyref.rs +++ b/src/types/weakref/anyref.rs @@ -5,7 +5,7 @@ use crate::types::{ any::{PyAny, PyAnyMethods}, PyNone, }; -use crate::{ffi, Bound}; +use crate::{ffi, Bound, Python}; /// Represents any Python `weakref` reference. /// @@ -315,20 +315,12 @@ pub trait PyWeakrefMethods<'py> { /// /// # Panics /// This function panics is the current object is invalid. - /// If used propperly this is never the case. (NonNull and actually a weakref type) + /// If used properly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetRef`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetRef /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref - fn upgrade(&self) -> Option> { - let object = self.get_object(); - - if object.is_none() { - None - } else { - Some(object) - } - } + fn upgrade(&self) -> Option>; /// Retrieve to a Bound object pointed to by the weakref. /// @@ -386,16 +378,25 @@ pub trait PyWeakrefMethods<'py> { /// [`PyWeakref_GetRef`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetRef /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref - fn get_object(&self) -> Bound<'py, PyAny>; + #[deprecated(since = "0.23.0", note = "Use `upgrade` instead")] + fn get_object(&self) -> Bound<'py, PyAny> { + self.upgrade().unwrap_or_else(|| { + // Safety: upgrade() returns `Bound<'py, PyAny>` with a lifetime `'py` if it exists, we + // can safely assume the same lifetime here. + PyNone::get(unsafe { Python::assume_gil_acquired() }) + .to_owned() + .into_any() + }) + } } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakref> { - fn get_object(&self) -> Bound<'py, PyAny> { + fn upgrade(&self) -> Option> { let mut obj: *mut ffi::PyObject = std::ptr::null_mut(); match unsafe { ffi::compat::PyWeakref_GetRef(self.as_ptr(), &mut obj) } { std::os::raw::c_int::MIN..=-1 => panic!("The 'weakref' weak reference instance should be valid (non-null and actually a weakref reference)"), - 0 => PyNone::get(self.py()).to_owned().into_any(), - 1..=std::os::raw::c_int::MAX => unsafe { obj.assume_owned(self.py()) }, + 0 => None, + 1..=std::os::raw::c_int::MAX => Some(unsafe { obj.assume_owned(self.py()) }), } } } @@ -545,6 +546,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_weakref_get_object() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( @@ -696,6 +698,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_weakref_get_object() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( diff --git a/src/types/weakref/proxy.rs b/src/types/weakref/proxy.rs index 798b4b435c7..6e72d5504e0 100644 --- a/src/types/weakref/proxy.rs +++ b/src/types/weakref/proxy.rs @@ -2,7 +2,7 @@ use crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; use crate::type_object::PyTypeCheck; -use crate::types::{any::PyAny, PyNone}; +use crate::types::any::PyAny; use crate::{ffi, Bound, ToPyObject}; use super::PyWeakrefMethods; @@ -182,12 +182,12 @@ impl PyWeakrefProxy { } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefProxy> { - fn get_object(&self) -> Bound<'py, PyAny> { + fn upgrade(&self) -> Option> { let mut obj: *mut ffi::PyObject = std::ptr::null_mut(); match unsafe { ffi::compat::PyWeakref_GetRef(self.as_ptr(), &mut obj) } { std::os::raw::c_int::MIN..=-1 => panic!("The 'weakref.ProxyType' (or `weakref.CallableProxyType`) instance should be valid (non-null and actually a weakref reference)"), - 0 => PyNone::get(self.py()).to_owned().into_any(), - 1..=std::os::raw::c_int::MAX => unsafe { obj.assume_owned(self.py()) }, + 0 => None, + 1..=std::os::raw::c_int::MAX => Some(unsafe { obj.assume_owned(self.py()) }), } } } @@ -273,7 +273,7 @@ mod tests { let reference = PyWeakrefProxy::new(&object)?; assert!(!reference.is(&object)); - assert!(reference.get_object().is(&object)); + assert!(reference.upgrade().unwrap().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!( @@ -301,7 +301,7 @@ mod tests { drop(object); - assert!(reference.get_object().is_none()); + assert!(reference.upgrade().is_none()); assert!(reference .getattr("__class__") .err() @@ -416,11 +416,11 @@ mod tests { let object = class.call0()?; let reference = PyWeakrefProxy::new(&object)?; - assert!(reference.get_object().is(&object)); + assert!(reference.upgrade().unwrap().is(&object)); drop(object); - assert!(reference.get_object().is_none()); + assert!(reference.upgrade().is_none()); Ok(()) }) @@ -444,7 +444,7 @@ mod tests { let reference = PyWeakrefProxy::new(&object)?; assert!(!reference.is(&object)); - assert!(reference.get_object().is(&object)); + assert!(reference.upgrade().unwrap().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!( reference.get_type().to_string(), @@ -474,7 +474,7 @@ mod tests { drop(object); - assert!(reference.get_object().is_none()); + assert!(reference.upgrade().is_none()); assert!(reference .getattr("__class__") .err() @@ -574,6 +574,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; @@ -623,7 +624,7 @@ mod tests { let reference = PyWeakrefProxy::new(&object)?; assert!(!reference.is(&object)); - assert!(reference.get_object().is(&object)); + assert!(reference.upgrade().unwrap().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.get_type().to_string(), CLASS_NAME); @@ -640,7 +641,7 @@ mod tests { drop(object); - assert!(reference.get_object().is_none()); + assert!(reference.upgrade().is_none()); assert!(reference .getattr("__class__") .err() @@ -747,6 +748,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; @@ -788,7 +790,7 @@ mod tests { let reference = PyWeakrefProxy::new(&object)?; assert!(!reference.is(&object)); - assert!(reference.get_object().is(&object)); + assert!(reference.upgrade().unwrap().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.get_type().to_string(), CLASS_NAME); @@ -808,7 +810,7 @@ mod tests { drop(object); - assert!(reference.get_object().is_none()); + assert!(reference.upgrade().is_none()); assert!(reference .getattr("__class__") .err() @@ -906,6 +908,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; diff --git a/src/types/weakref/reference.rs b/src/types/weakref/reference.rs index cc8bc3d55f5..c13b30631c7 100644 --- a/src/types/weakref/reference.rs +++ b/src/types/weakref/reference.rs @@ -1,7 +1,7 @@ use crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; -use crate::types::{any::PyAny, PyNone}; +use crate::types::any::PyAny; use crate::{ffi, Bound, ToPyObject}; #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] @@ -191,12 +191,12 @@ impl PyWeakrefReference { } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefReference> { - fn get_object(&self) -> Bound<'py, PyAny> { + fn upgrade(&self) -> Option> { let mut obj: *mut ffi::PyObject = std::ptr::null_mut(); match unsafe { ffi::compat::PyWeakref_GetRef(self.as_ptr(), &mut obj) } { std::os::raw::c_int::MIN..=-1 => panic!("The 'weakref.ReferenceType' instance should be valid (non-null and actually a weakref reference)"), - 0 => PyNone::get(self.py()).to_owned().into_any(), - 1..=std::os::raw::c_int::MAX => unsafe { obj.assume_owned(self.py()) }, + 0 => None, + 1..=std::os::raw::c_int::MAX => Some(unsafe { obj.assume_owned(self.py()) }), } } } @@ -268,7 +268,7 @@ mod tests { let reference = PyWeakrefReference::new(&object)?; assert!(!reference.is(&object)); - assert!(reference.get_object().is(&object)); + assert!(reference.upgrade().unwrap().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.get_type().to_string(), CLASS_NAME); @@ -287,7 +287,7 @@ mod tests { drop(object); - assert!(reference.get_object().is_none()); + assert!(reference.upgrade().is_none()); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.getattr("__class__")?.to_string(), CLASS_NAME); check_repr(&reference, None)?; @@ -387,6 +387,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; @@ -423,7 +424,7 @@ mod tests { let reference = PyWeakrefReference::new(&object)?; assert!(!reference.is(&object)); - assert!(reference.get_object().is(&object)); + assert!(reference.upgrade().unwrap().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.get_type().to_string(), CLASS_NAME); @@ -440,7 +441,7 @@ mod tests { drop(object); - assert!(reference.get_object().is_none()); + assert!(reference.upgrade().is_none()); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.getattr("__class__")?.to_string(), CLASS_NAME); check_repr(&reference, None)?; @@ -531,6 +532,7 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?;