From 49891c0da570bec4963b94978b98bbb679c57d01 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Wed, 4 Sep 2024 16:20:02 -0600 Subject: [PATCH 1/9] add FFI bindings and a compat definition for PyWeakref_GetRef --- pyo3-ffi/src/compat/py_3_13.rs | 33 +++++++++++++++++++++++++++++++++ pyo3-ffi/src/weakrefobject.rs | 3 +++ 2 files changed, 36 insertions(+) diff --git a/pyo3-ffi/src/compat/py_3_13.rs b/pyo3-ffi/src/compat/py_3_13.rs index 94778802987..9482e198b22 100644 --- a/pyo3-ffi/src/compat/py_3_13.rs +++ b/pyo3-ffi/src/compat/py_3_13.rs @@ -50,3 +50,36 @@ compat_function!( Py_XNewRef(PyImport_AddModule(name)) } ); + +compat_function!( + originally_defined_for(Py_3_13); + + #[inline] + pub unsafe fn PyWeakref_GetRef( + _ref: *mut crate::PyObject, + pobj: *mut *mut crate::PyObject, + ) -> std::os::raw::c_int { + use crate::{ + compat::Py_NewRef, PyErr_SetString, PyExc_TypeError, PyWeakref_Check, + PyWeakref_GetObject, Py_None, + }; + + if !_ref.is_null() && PyWeakref_Check(_ref) == 0 { + *pobj = std::ptr::null_mut(); + PyErr_SetString(PyExc_TypeError, c_str!("expected a weakref").as_ptr()); + return -1; + } + let obj = PyWeakref_GetObject(_ref); + if obj.is_null() { + // SystemError if _ref is NULL + *pobj = std::ptr::null_mut(); + return -1; + } + if obj == Py_None() { + *pobj = std::ptr::null_mut(); + return 0; + } + *pobj = Py_NewRef(obj); + 1 + } +); diff --git a/pyo3-ffi/src/weakrefobject.rs b/pyo3-ffi/src/weakrefobject.rs index 7e11a9012e7..a92c2d99751 100644 --- a/pyo3-ffi/src/weakrefobject.rs +++ b/pyo3-ffi/src/weakrefobject.rs @@ -59,4 +59,7 @@ extern "C" { pub fn PyWeakref_NewProxy(ob: *mut PyObject, callback: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyWeakref_GetObject")] pub fn PyWeakref_GetObject(_ref: *mut PyObject) -> *mut PyObject; + #[cfg(Py_3_13)] + #[cfg_attr(PyPy, link_name = "PyPyWeakref_GetRef")] + pub fn PyWeakref_GetRef(_ref: *mut PyObject, pobj: *mut *mut PyObject) -> c_int; } From 806ff8b0c58182872461693b6aaa58abbff26754 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Wed, 4 Sep 2024 16:20:37 -0600 Subject: [PATCH 2/9] implement get_object method of weakref wrappers using PyWeakref_GetRef --- src/types/weakref/anyref.rs | 27 ++++++++++++++++++--------- src/types/weakref/proxy.rs | 11 ++++++++++- src/types/weakref/reference.rs | 11 ++++++++++- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/types/weakref/anyref.rs b/src/types/weakref/anyref.rs index 182bf9f549d..10fabd6e243 100644 --- a/src/types/weakref/anyref.rs +++ b/src/types/weakref/anyref.rs @@ -1,7 +1,10 @@ use crate::err::{DowncastError, PyResult}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::type_object::{PyTypeCheck, PyTypeInfo}; -use crate::types::any::{PyAny, PyAnyMethods}; +use crate::types::{ + any::{PyAny, PyAnyMethods}, + PyNone, +}; use crate::{ffi, Borrowed, Bound}; /// Represents any Python `weakref` reference. @@ -502,7 +505,7 @@ pub trait PyWeakrefMethods<'py> { /// This function returns `Some(Bound<'py, PyAny>)` if the reference still exists, otherwise `None` will be returned. /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). - /// It produces similair results to using [`PyWeakref_GetObject`] in the C api. + /// It produces similar results to using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( @@ -572,7 +575,7 @@ pub trait PyWeakrefMethods<'py> { /// This function returns `Some(Borrowed<'_, 'py, PyAny>)` if the reference still exists, otherwise `None` will be returned. /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). - /// It produces similair results to using [`PyWeakref_GetObject`] in the C api. + /// It produces similar results to using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( @@ -644,7 +647,7 @@ pub trait PyWeakrefMethods<'py> { /// This function returns `Bound<'py, PyAny>`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). - /// It produces similair results to using [`PyWeakref_GetObject`] in the C api. + /// It produces similar results to using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( @@ -695,17 +698,14 @@ pub trait PyWeakrefMethods<'py> { /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`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> { - // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. - self.get_object_borrowed().to_owned() - } + fn get_object(&self) -> Bound<'py, PyAny>; /// Retrieve to a Borrowed object pointed to by the weakref. /// /// This function returns `Borrowed<'py, PyAny>`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). - /// It produces similair results to using [`PyWeakref_GetObject`] in the C api. + /// It produces similar results to using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( @@ -767,6 +767,15 @@ impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakref> { unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } .expect("The 'weakref' weak reference instance should be valid (non-null and actually a weakref reference)") } + + fn get_object(&self) -> Bound<'py, PyAny> { + 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()) }, + } + } } #[cfg(test)] diff --git a/src/types/weakref/proxy.rs b/src/types/weakref/proxy.rs index c902f5d94a5..ccd16cc01fb 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; +use crate::types::{any::PyAny, PyNone}; use crate::{ffi, Borrowed, Bound, ToPyObject}; use super::PyWeakrefMethods; @@ -187,6 +187,15 @@ impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefProxy> { unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } .expect("The 'weakref.ProxyType' (or `weakref.CallableProxyType`) instance should be valid (non-null and actually a weakref reference)") } + + fn get_object(&self) -> Bound<'py, PyAny> { + 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()) }, + } + } } #[cfg(test)] diff --git a/src/types/weakref/reference.rs b/src/types/weakref/reference.rs index deb62465ccc..d63c139ac44 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; +use crate::types::{any::PyAny, PyNone}; use crate::{ffi, Borrowed, Bound, ToPyObject}; #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] @@ -196,6 +196,15 @@ impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefReference> { unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } .expect("The 'weakref.ReferenceType' instance should be valid (non-null and actually a weakref reference)") } + + fn get_object(&self) -> Bound<'py, PyAny> { + 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()) }, + } + } } #[cfg(test)] From e6d792811497b122a68a48c749f42df2638afa59 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Wed, 4 Sep 2024 16:27:31 -0600 Subject: [PATCH 3/9] add changelog --- newsfragments/4528.added.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 newsfragments/4528.added.md diff --git a/newsfragments/4528.added.md b/newsfragments/4528.added.md new file mode 100644 index 00000000000..0991f9a5261 --- /dev/null +++ b/newsfragments/4528.added.md @@ -0,0 +1,2 @@ +* Added bindings for `pyo3_ffi::PyWeakref_GetRef` on Python 3.13 and newer and + `py03_ffi::compat::PyWeakref_GetRef` for older Python versions. From d73b0feadd8079f481e48255555062a1816b34ff Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Thu, 5 Sep 2024 15:40:37 -0600 Subject: [PATCH 4/9] rename _ref argument to reference --- pyo3-ffi/src/compat/py_3_13.rs | 8 ++++---- pyo3-ffi/src/weakrefobject.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyo3-ffi/src/compat/py_3_13.rs b/pyo3-ffi/src/compat/py_3_13.rs index 9482e198b22..9f44ced6f3f 100644 --- a/pyo3-ffi/src/compat/py_3_13.rs +++ b/pyo3-ffi/src/compat/py_3_13.rs @@ -56,7 +56,7 @@ compat_function!( #[inline] pub unsafe fn PyWeakref_GetRef( - _ref: *mut crate::PyObject, + reference: *mut crate::PyObject, pobj: *mut *mut crate::PyObject, ) -> std::os::raw::c_int { use crate::{ @@ -64,14 +64,14 @@ compat_function!( PyWeakref_GetObject, Py_None, }; - if !_ref.is_null() && PyWeakref_Check(_ref) == 0 { + if !reference.is_null() && PyWeakref_Check(reference) == 0 { *pobj = std::ptr::null_mut(); PyErr_SetString(PyExc_TypeError, c_str!("expected a weakref").as_ptr()); return -1; } - let obj = PyWeakref_GetObject(_ref); + let obj = PyWeakref_GetObject(reference); if obj.is_null() { - // SystemError if _ref is NULL + // SystemError if reference is NULL *pobj = std::ptr::null_mut(); return -1; } diff --git a/pyo3-ffi/src/weakrefobject.rs b/pyo3-ffi/src/weakrefobject.rs index a92c2d99751..fd4afa52b2c 100644 --- a/pyo3-ffi/src/weakrefobject.rs +++ b/pyo3-ffi/src/weakrefobject.rs @@ -58,8 +58,8 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPyWeakref_NewProxy")] pub fn PyWeakref_NewProxy(ob: *mut PyObject, callback: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyWeakref_GetObject")] - pub fn PyWeakref_GetObject(_ref: *mut PyObject) -> *mut PyObject; + pub fn PyWeakref_GetObject(reference: *mut PyObject) -> *mut PyObject; #[cfg(Py_3_13)] #[cfg_attr(PyPy, link_name = "PyPyWeakref_GetRef")] - pub fn PyWeakref_GetRef(_ref: *mut PyObject, pobj: *mut *mut PyObject) -> c_int; + pub fn PyWeakref_GetRef(reference: *mut PyObject, pobj: *mut *mut PyObject) -> c_int; } From 835b3e7308d6cfd9befcb9ee7cccdf981d778362 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Thu, 5 Sep 2024 15:44:26 -0600 Subject: [PATCH 5/9] mark PyWeakref_GetObject as deprecated --- pyo3-ffi/src/weakrefobject.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyo3-ffi/src/weakrefobject.rs b/pyo3-ffi/src/weakrefobject.rs index fd4afa52b2c..305dc290fa8 100644 --- a/pyo3-ffi/src/weakrefobject.rs +++ b/pyo3-ffi/src/weakrefobject.rs @@ -58,6 +58,10 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPyWeakref_NewProxy")] pub fn PyWeakref_NewProxy(ob: *mut PyObject, callback: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyWeakref_GetObject")] + #[cfg_attr( + Py_3_13, + deprecated(note = "deprecated since Python 3.13. Use `PyWeakref_GetRef` instead.") + )] pub fn PyWeakref_GetObject(reference: *mut PyObject) -> *mut PyObject; #[cfg(Py_3_13)] #[cfg_attr(PyPy, link_name = "PyPyWeakref_GetRef")] From 8fab6a65b6cd7c88c371bb4a58ca7a44338747fb Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Thu, 5 Sep 2024 16:32:09 -0600 Subject: [PATCH 6/9] mark test as using deprecated API item --- src/types/weakref/anyref.rs | 2 ++ src/types/weakref/proxy.rs | 1 + src/types/weakref/reference.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/src/types/weakref/anyref.rs b/src/types/weakref/anyref.rs index 10fabd6e243..8656f673381 100644 --- a/src/types/weakref/anyref.rs +++ b/src/types/weakref/anyref.rs @@ -758,12 +758,14 @@ pub trait PyWeakrefMethods<'py> { /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref #[track_caller] // TODO: This function is the reason every function tracks caller, however it only panics when the weakref object is not actually a weakreference type. So is it this neccessary? + // TODO: we should deprecate this because it relies on the semantics of a deprecated C API item fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny>; } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakref> { fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny> { // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. + #![allow(deprecated)] unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } .expect("The 'weakref' weak reference instance should be valid (non-null and actually a weakref reference)") } diff --git a/src/types/weakref/proxy.rs b/src/types/weakref/proxy.rs index ccd16cc01fb..f9c2bae6544 100644 --- a/src/types/weakref/proxy.rs +++ b/src/types/weakref/proxy.rs @@ -184,6 +184,7 @@ impl PyWeakrefProxy { impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefProxy> { fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny> { // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. + #![allow(deprecated)] unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } .expect("The 'weakref.ProxyType' (or `weakref.CallableProxyType`) instance should be valid (non-null and actually a weakref reference)") } diff --git a/src/types/weakref/reference.rs b/src/types/weakref/reference.rs index d63c139ac44..7b1c78f0124 100644 --- a/src/types/weakref/reference.rs +++ b/src/types/weakref/reference.rs @@ -193,6 +193,7 @@ impl PyWeakrefReference { impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefReference> { fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny> { // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. + #![allow(deprecated)] unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } .expect("The 'weakref.ReferenceType' instance should be valid (non-null and actually a weakref reference)") } From dd8236dc136b3dff7916e6f590e9e5084de70180 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Thu, 5 Sep 2024 16:38:45 -0600 Subject: [PATCH 7/9] update docs to reference PyWeakref_GetRef semantics --- src/types/weakref/anyref.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/types/weakref/anyref.rs b/src/types/weakref/anyref.rs index 8656f673381..72ba3a56329 100644 --- a/src/types/weakref/anyref.rs +++ b/src/types/weakref/anyref.rs @@ -37,7 +37,7 @@ pub trait PyWeakrefMethods<'py> { /// Upgrade the weakref to a direct Bound object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). - /// In Python it would be equivalent to [`PyWeakref_GetObject`]. + /// In Python it would be equivalent to [`PyWeakref_GetRef`]. /// /// # Example #[cfg_attr( @@ -97,7 +97,7 @@ pub trait PyWeakrefMethods<'py> { /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject + /// [`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_as(&self) -> PyResult>> @@ -194,7 +194,7 @@ pub trait PyWeakrefMethods<'py> { /// Upgrade the weakref to a direct Bound object reference unchecked. The type of the recovered object is not checked before downcasting, this could lead to unexpected behavior. Use only when absolutely certain the type can be guaranteed. The `weakref` may still return `None`. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). - /// In Python it would be equivalent to [`PyWeakref_GetObject`]. + /// In Python it would be equivalent to [`PyWeakref_GetRef`]. /// /// # Safety /// Callers must ensure that the type is valid or risk type confusion. @@ -258,7 +258,7 @@ pub trait PyWeakrefMethods<'py> { /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject + /// [`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 unsafe fn upgrade_as_unchecked(&self) -> Option> { @@ -345,7 +345,7 @@ pub trait PyWeakrefMethods<'py> { /// Upgrade the weakref to a exact direct Bound object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). - /// In Python it would be equivalent to [`PyWeakref_GetObject`]. + /// In Python it would be equivalent to [`PyWeakref_GetRef`]. /// /// # Example #[cfg_attr( @@ -405,7 +405,7 @@ pub trait PyWeakrefMethods<'py> { /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject + /// [`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_as_exact(&self) -> PyResult>> @@ -505,7 +505,7 @@ pub trait PyWeakrefMethods<'py> { /// This function returns `Some(Bound<'py, PyAny>)` if the reference still exists, otherwise `None` will be returned. /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). - /// It produces similar results to using [`PyWeakref_GetObject`] in the C api. + /// It produces similar results to using [`PyWeakref_GetRef`] in the C api. /// /// # Example #[cfg_attr( @@ -556,7 +556,7 @@ pub trait PyWeakrefMethods<'py> { /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject + /// [`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> { @@ -647,7 +647,7 @@ pub trait PyWeakrefMethods<'py> { /// This function returns `Bound<'py, PyAny>`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). - /// It produces similar results to using [`PyWeakref_GetObject`] in the C api. + /// It produces similar results to using [`PyWeakref_GetRef`] in the C api. /// /// # Example #[cfg_attr( @@ -695,7 +695,7 @@ pub trait PyWeakrefMethods<'py> { /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject + /// [`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>; From 77c35c6b10ce33beef625662371f6cb91731c9fe Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Thu, 26 Sep 2024 10:14:34 -0600 Subject: [PATCH 8/9] remove weakref methods that return borrowed references --- newsfragments/4528.removed.md | 7 + src/types/weakref/anyref.rs | 724 ++------------------------------- src/types/weakref/proxy.rs | 399 +----------------- src/types/weakref/reference.rs | 209 ---------- 4 files changed, 32 insertions(+), 1307 deletions(-) create mode 100644 newsfragments/4528.removed.md diff --git a/newsfragments/4528.removed.md b/newsfragments/4528.removed.md new file mode 100644 index 00000000000..79c66b98818 --- /dev/null +++ b/newsfragments/4528.removed.md @@ -0,0 +1,7 @@ +* Removed the `get_object_borrowed`, `upgrade_borrowed`, `upgrade_borrowed_as`, +`upgrade_borrowed_as_unchecked`, `upgrade_borrowed_as_exact` methods of +`PyWeakref` and `PyWeakrefProxy`. These returned borrowed references to weakly +referenced data, and in principle if the GIL is released the last strong +reference could be released, allowing a possible use-after-free error. If you +are using these functions, you should change to the equivalent function that +returns a `Bound<'py, T>` reference. diff --git a/src/types/weakref/anyref.rs b/src/types/weakref/anyref.rs index 72ba3a56329..4a9a61b43e6 100644 --- a/src/types/weakref/anyref.rs +++ b/src/types/weakref/anyref.rs @@ -110,87 +110,6 @@ pub trait PyWeakrefMethods<'py> { .map_err(Into::into) } - /// Upgrade the weakref to a Borrowed object reference. - /// - /// It is named `upgrade_borrowed` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). - /// In Python it would be equivalent to [`PyWeakref_GetObject`]. - /// - /// # Example - #[cfg_attr( - not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), - doc = "```rust,ignore" - )] - #[cfg_attr( - all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), - doc = "```rust" - )] - /// use pyo3::prelude::*; - /// use pyo3::types::PyWeakrefReference; - /// - /// #[pyclass(weakref)] - /// struct Foo { /* fields omitted */ } - /// - /// #[pymethods] - /// impl Foo { - /// fn get_data(&self) -> (&str, u32) { - /// ("Dave", 10) - /// } - /// } - /// - /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { - /// if let Some(data_src) = reference.upgrade_borrowed_as::()? { - /// let data = data_src.borrow(); - /// let (name, score) = data.get_data(); - /// Ok(format!("Processing '{}': score = {}", name, score)) - /// } else { - /// Ok("The supplied data reference is nolonger relavent.".to_owned()) - /// } - /// } - /// - /// # fn main() -> PyResult<()> { - /// Python::with_gil(|py| { - /// let data = Bound::new(py, Foo{})?; - /// let reference = PyWeakrefReference::new(&data)?; - /// - /// assert_eq!( - /// parse_data(reference.as_borrowed())?, - /// "Processing 'Dave': score = 10" - /// ); - /// - /// drop(data); - /// - /// assert_eq!( - /// parse_data(reference.as_borrowed())?, - /// "The supplied data reference is nolonger relavent." - /// ); - /// - /// Ok(()) - /// }) - /// # } - /// ``` - /// - /// # Panics - /// This function panics is the current object is invalid. - /// If used propperly this is never the case. (NonNull and actually a weakref type) - /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject - /// [`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_borrowed_as<'a, T>(&'a self) -> PyResult>> - where - T: PyTypeCheck, - 'py: 'a, - { - // TODO: Replace when Borrowed::downcast exists - match self.upgrade_borrowed() { - None => Ok(None), - Some(object) if T::type_check(&object) => { - Ok(Some(unsafe { object.downcast_unchecked() })) - } - Some(object) => Err(DowncastError::new(&object, T::NAME).into()), - } - } - /// Upgrade the weakref to a direct Bound object reference unchecked. The type of the recovered object is not checked before downcasting, this could lead to unexpected behavior. Use only when absolutely certain the type can be guaranteed. The `weakref` may still return `None`. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). @@ -265,83 +184,6 @@ pub trait PyWeakrefMethods<'py> { Some(self.upgrade()?.downcast_into_unchecked()) } - /// Upgrade the weakref to a Borrowed object reference unchecked. The type of the recovered object is not checked before downcasting, this could lead to unexpected behavior. Use only when absolutely certain the type can be guaranteed. The `weakref` may still return `None`. - /// - /// It is named `upgrade_borrowed` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). - /// In Python it would be equivalent to [`PyWeakref_GetObject`]. - /// - /// # Safety - /// Callers must ensure that the type is valid or risk type confusion. - /// The `weakref` is still allowed to be `None`, if the referenced object has been cleaned up. - /// - /// # Example - #[cfg_attr( - not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), - doc = "```rust,ignore" - )] - #[cfg_attr( - all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), - doc = "```rust" - )] - /// use pyo3::prelude::*; - /// use pyo3::types::PyWeakrefReference; - /// - /// #[pyclass(weakref)] - /// struct Foo { /* fields omitted */ } - /// - /// #[pymethods] - /// impl Foo { - /// fn get_data(&self) -> (&str, u32) { - /// ("Dave", 10) - /// } - /// } - /// - /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> String { - /// if let Some(data_src) = unsafe { reference.upgrade_borrowed_as_unchecked::() } { - /// let data = data_src.borrow(); - /// let (name, score) = data.get_data(); - /// format!("Processing '{}': score = {}", name, score) - /// } else { - /// "The supplied data reference is nolonger relavent.".to_owned() - /// } - /// } - /// - /// # fn main() -> PyResult<()> { - /// Python::with_gil(|py| { - /// let data = Bound::new(py, Foo{})?; - /// let reference = PyWeakrefReference::new(&data)?; - /// - /// assert_eq!( - /// parse_data(reference.as_borrowed()), - /// "Processing 'Dave': score = 10" - /// ); - /// - /// drop(data); - /// - /// assert_eq!( - /// parse_data(reference.as_borrowed()), - /// "The supplied data reference is nolonger relavent." - /// ); - /// - /// Ok(()) - /// }) - /// # } - /// ``` - /// - /// # Panics - /// This function panics is the current object is invalid. - /// If used propperly this is never the case. (NonNull and actually a weakref type) - /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject - /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType - /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref? - unsafe fn upgrade_borrowed_as_unchecked<'a, T>(&'a self) -> Option> - where - 'py: 'a, - { - Some(self.upgrade_borrowed()?.downcast_unchecked()) - } - /// Upgrade the weakref to a exact direct Bound object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). @@ -418,87 +260,6 @@ pub trait PyWeakrefMethods<'py> { .map_err(Into::into) } - /// Upgrade the weakref to a exact Borrowed object reference. - /// - /// It is named `upgrade_borrowed` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). - /// In Python it would be equivalent to [`PyWeakref_GetObject`]. - /// - /// # Example - #[cfg_attr( - not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), - doc = "```rust,ignore" - )] - #[cfg_attr( - all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), - doc = "```rust" - )] - /// use pyo3::prelude::*; - /// use pyo3::types::PyWeakrefReference; - /// - /// #[pyclass(weakref)] - /// struct Foo { /* fields omitted */ } - /// - /// #[pymethods] - /// impl Foo { - /// fn get_data(&self) -> (&str, u32) { - /// ("Dave", 10) - /// } - /// } - /// - /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { - /// if let Some(data_src) = reference.upgrade_borrowed_as_exact::()? { - /// let data = data_src.borrow(); - /// let (name, score) = data.get_data(); - /// Ok(format!("Processing '{}': score = {}", name, score)) - /// } else { - /// Ok("The supplied data reference is nolonger relavent.".to_owned()) - /// } - /// } - /// - /// # fn main() -> PyResult<()> { - /// Python::with_gil(|py| { - /// let data = Bound::new(py, Foo{})?; - /// let reference = PyWeakrefReference::new(&data)?; - /// - /// assert_eq!( - /// parse_data(reference.as_borrowed())?, - /// "Processing 'Dave': score = 10" - /// ); - /// - /// drop(data); - /// - /// assert_eq!( - /// parse_data(reference.as_borrowed())?, - /// "The supplied data reference is nolonger relavent." - /// ); - /// - /// Ok(()) - /// }) - /// # } - /// ``` - /// - /// # Panics - /// This function panics is the current object is invalid. - /// If used propperly this is never the case. (NonNull and actually a weakref type) - /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject - /// [`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_borrowed_as_exact<'a, T>(&'a self) -> PyResult>> - where - T: PyTypeInfo, - 'py: 'a, - { - // TODO: Replace when Borrowed::downcast_exact exists - match self.upgrade_borrowed() { - None => Ok(None), - Some(object) if object.is_exact_instance_of::() => { - Ok(Some(unsafe { object.downcast_unchecked() })) - } - Some(object) => Err(DowncastError::new(&object, T::NAME).into()), - } - } - /// Upgrade the weakref to a Bound [`PyAny`] reference to the target object if possible. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). @@ -569,79 +330,6 @@ pub trait PyWeakrefMethods<'py> { } } - /// Upgrade the weakref to a Borrowed [`PyAny`] reference to the target object if possible. - /// - /// It is named `upgrade_borrowed` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). - /// This function returns `Some(Borrowed<'_, 'py, PyAny>)` if the reference still exists, otherwise `None` will be returned. - /// - /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). - /// It produces similar results to using [`PyWeakref_GetObject`] in the C api. - /// - /// # Example - #[cfg_attr( - not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), - doc = "```rust,ignore" - )] - #[cfg_attr( - all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), - doc = "```rust" - )] - /// use pyo3::prelude::*; - /// use pyo3::types::PyWeakrefReference; - /// - /// #[pyclass(weakref)] - /// struct Foo { /* fields omitted */ } - /// - /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { - /// if let Some(object) = reference.upgrade_borrowed() { - /// Ok(format!("The object '{}' refered by this reference still exists.", object.getattr("__class__")?.getattr("__qualname__")?)) - /// } else { - /// Ok("The object, which this reference refered to, no longer exists".to_owned()) - /// } - /// } - /// - /// # fn main() -> PyResult<()> { - /// Python::with_gil(|py| { - /// let data = Bound::new(py, Foo{})?; - /// let reference = PyWeakrefReference::new(&data)?; - /// - /// assert_eq!( - /// parse_data(reference.as_borrowed())?, - /// "The object 'Foo' refered by this reference still exists." - /// ); - /// - /// drop(data); - /// - /// assert_eq!( - /// parse_data(reference.as_borrowed())?, - /// "The object, which this reference refered to, no longer exists" - /// ); - /// - /// Ok(()) - /// }) - /// # } - /// ``` - /// - /// # Panics - /// This function panics is the current object is invalid. - /// If used propperly this is never the case. (NonNull and actually a weakref type) - /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject - /// [`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_borrowed<'a>(&'a self) -> Option> - where - 'py: 'a, - { - let object = self.get_object_borrowed(); - - if object.is_none() { - None - } else { - Some(object) - } - } - /// Retrieve to a Bound object pointed to by the weakref. /// /// This function returns `Bound<'py, PyAny>`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). @@ -699,77 +387,9 @@ pub trait PyWeakrefMethods<'py> { /// [`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>; - - /// Retrieve to a Borrowed object pointed to by the weakref. - /// - /// This function returns `Borrowed<'py, PyAny>`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). - /// - /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). - /// It produces similar results to using [`PyWeakref_GetObject`] in the C api. - /// - /// # Example - #[cfg_attr( - not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), - doc = "```rust,ignore" - )] - #[cfg_attr( - all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), - doc = "```rust" - )] - /// use pyo3::prelude::*; - /// use pyo3::types::PyWeakrefReference; - /// - /// #[pyclass(weakref)] - /// struct Foo { /* fields omitted */ } - /// - /// fn get_class(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { - /// reference - /// .get_object_borrowed() - /// .getattr("__class__")? - /// .repr() - /// .map(|repr| repr.to_string()) - /// } - /// - /// # fn main() -> PyResult<()> { - /// Python::with_gil(|py| { - /// let object = Bound::new(py, Foo{})?; - /// let reference = PyWeakrefReference::new(&object)?; - /// - /// assert_eq!( - /// get_class(reference.as_borrowed())?, - /// "" - /// ); - /// - /// drop(object); - /// - /// assert_eq!(get_class(reference.as_borrowed())?, ""); - /// - /// Ok(()) - /// }) - /// # } - /// ``` - /// - /// # Panics - /// This function panics is the current object is invalid. - /// If used propperly this is never the case. (NonNull and actually a weakref type) - /// - /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject - /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType - /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref - #[track_caller] - // TODO: This function is the reason every function tracks caller, however it only panics when the weakref object is not actually a weakreference type. So is it this neccessary? - // TODO: we should deprecate this because it relies on the semantics of a deprecated C API item - fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny>; } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakref> { - fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny> { - // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. - #![allow(deprecated)] - unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } - .expect("The 'weakref' weak reference instance should be valid (non-null and actually a weakref reference)") - } - fn get_object(&self) -> Bound<'py, PyAny> { let mut obj: *mut ffi::PyObject = std::ptr::null_mut(); match unsafe { ffi::compat::PyWeakref_GetRef(self.as_ptr(), &mut obj) } { @@ -780,80 +400,35 @@ impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakref> { } } -#[cfg(test)] -mod tests { - use crate::types::any::{PyAny, PyAnyMethods}; - use crate::types::weakref::{PyWeakref, PyWeakrefMethods, PyWeakrefProxy, PyWeakrefReference}; - use crate::{Bound, PyResult, Python}; - - fn new_reference<'py>(object: &Bound<'py, PyAny>) -> PyResult> { - let reference = PyWeakrefReference::new(object)?; - reference.into_any().downcast_into().map_err(Into::into) - } - - fn new_proxy<'py>(object: &Bound<'py, PyAny>) -> PyResult> { - let reference = PyWeakrefProxy::new(object)?; - reference.into_any().downcast_into().map_err(Into::into) - } - - mod python_class { - use super::*; - use crate::ffi; - use crate::{py_result_ext::PyResultExt, types::PyType}; - - fn get_type(py: Python<'_>) -> PyResult> { - py.run(ffi::c_str!("class A:\n pass\n"), None, None)?; - py.eval(ffi::c_str!("A"), None, None) - .downcast_into::() - } - - #[test] - fn test_weakref_upgrade_as() -> PyResult<()> { - fn inner( - create_reference: impl for<'py> FnOnce( - &Bound<'py, PyAny>, - ) - -> PyResult>, - ) -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = create_reference(&object)?; - - { - // This test is a bit weird but ok. - let obj = reference.upgrade_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() - && obj.is_exact_instance(&class))); - } - - drop(object); - - { - // This test is a bit weird but ok. - let obj = reference.upgrade_as::(); +#[cfg(test)] +mod tests { + use crate::types::any::{PyAny, PyAnyMethods}; + use crate::types::weakref::{PyWeakref, PyWeakrefMethods, PyWeakrefProxy, PyWeakrefReference}; + use crate::{Bound, PyResult, Python}; - assert!(obj.is_ok()); - let obj = obj.unwrap(); + fn new_reference<'py>(object: &Bound<'py, PyAny>) -> PyResult> { + let reference = PyWeakrefReference::new(object)?; + reference.into_any().downcast_into().map_err(Into::into) + } - assert!(obj.is_none()); - } + fn new_proxy<'py>(object: &Bound<'py, PyAny>) -> PyResult> { + let reference = PyWeakrefProxy::new(object)?; + reference.into_any().downcast_into().map_err(Into::into) + } - Ok(()) - }) - } + mod python_class { + use super::*; + use crate::ffi; + use crate::{py_result_ext::PyResultExt, types::PyType}; - inner(new_reference)?; - inner(new_proxy) + fn get_type(py: Python<'_>) -> PyResult> { + py.run(ffi::c_str!("class A:\n pass\n"), None, None)?; + py.eval(ffi::c_str!("A"), None, None) + .downcast_into::() } #[test] - fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { + fn test_weakref_upgrade_as() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, @@ -867,7 +442,7 @@ mod tests { { // This test is a bit weird but ok. - let obj = reference.upgrade_borrowed_as::(); + let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); @@ -881,7 +456,7 @@ mod tests { { // This test is a bit weird but ok. - let obj = reference.upgrade_borrowed_as::(); + let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); @@ -936,45 +511,6 @@ mod tests { inner(new_proxy) } - #[test] - fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { - fn inner( - create_reference: impl for<'py> FnOnce( - &Bound<'py, PyAny>, - ) - -> PyResult>, - ) -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = create_reference(&object)?; - - { - // This test is a bit weird but ok. - let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() - && obj.is_exact_instance(&class))); - } - - drop(object); - - { - // This test is a bit weird but ok. - let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - - inner(new_reference)?; - inner(new_proxy) - } - #[test] fn test_weakref_upgrade() -> PyResult<()> { fn inner( @@ -1008,41 +544,6 @@ mod tests { inner(new_proxy, false) } - #[test] - fn test_weakref_upgrade_borrowed() -> PyResult<()> { - fn inner( - create_reference: impl for<'py> FnOnce( - &Bound<'py, PyAny>, - ) - -> PyResult>, - call_retrievable: bool, - ) -> PyResult<()> { - let not_call_retrievable = !call_retrievable; - - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = create_reference(&object)?; - - assert!(not_call_retrievable || reference.call0()?.is(&object)); - assert!(reference.upgrade_borrowed().is_some()); - assert!(reference - .upgrade_borrowed() - .map_or(false, |obj| obj.is(&object))); - - drop(object); - - assert!(not_call_retrievable || reference.call0()?.is_none()); - assert!(reference.upgrade_borrowed().is_none()); - - Ok(()) - }) - } - - inner(new_reference, true)?; - inner(new_proxy, false) - } - #[test] fn test_weakref_get_object() -> PyResult<()> { fn inner( @@ -1075,38 +576,6 @@ mod tests { inner(new_reference, true)?; inner(new_proxy, false) } - - #[test] - fn test_weakref_get_object_borrowed() -> PyResult<()> { - fn inner( - create_reference: impl for<'py> FnOnce( - &Bound<'py, PyAny>, - ) - -> PyResult>, - call_retrievable: bool, - ) -> PyResult<()> { - let not_call_retrievable = !call_retrievable; - - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = create_reference(&object)?; - - assert!(not_call_retrievable || reference.call0()?.is(&object)); - assert!(reference.get_object_borrowed().is(&object)); - - drop(object); - - assert!(not_call_retrievable || reference.call0()?.is_none()); - assert!(reference.get_object_borrowed().is_none()); - - Ok(()) - }) - } - - inner(new_reference, true)?; - inner(new_proxy, false) - } } // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable. @@ -1159,47 +628,6 @@ mod tests { inner(new_proxy) } - #[test] - fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { - fn inner( - create_reference: impl for<'py> FnOnce( - &Bound<'py, PyAny>, - ) - -> PyResult>, - ) -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = create_reference(object.bind(py))?; - - { - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); - } - - drop(object); - - { - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - - inner(new_reference)?; - inner(new_proxy) - } - #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { fn inner( @@ -1235,45 +663,6 @@ mod tests { inner(new_proxy) } - #[test] - fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { - fn inner( - create_reference: impl for<'py> FnOnce( - &Bound<'py, PyAny>, - ) - -> PyResult>, - ) -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = create_reference(object.bind(py))?; - - { - let obj = unsafe { - reference.upgrade_borrowed_as_unchecked::() - }; - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); - } - - drop(object); - - { - let obj = unsafe { - reference.upgrade_borrowed_as_unchecked::() - }; - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - - inner(new_reference)?; - inner(new_proxy) - } - #[test] fn test_weakref_upgrade() -> PyResult<()> { fn inner( @@ -1306,40 +695,6 @@ mod tests { inner(new_proxy, false) } - #[test] - fn test_weakref_upgrade_borrowed() -> PyResult<()> { - fn inner( - create_reference: impl for<'py> FnOnce( - &Bound<'py, PyAny>, - ) - -> PyResult>, - call_retrievable: bool, - ) -> PyResult<()> { - let not_call_retrievable = !call_retrievable; - - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = create_reference(object.bind(py))?; - - assert!(not_call_retrievable || reference.call0()?.is(&object)); - assert!(reference.upgrade_borrowed().is_some()); - assert!(reference - .upgrade_borrowed() - .map_or(false, |obj| obj.is(&object))); - - drop(object); - - assert!(not_call_retrievable || reference.call0()?.is_none()); - assert!(reference.upgrade_borrowed().is_none()); - - Ok(()) - }) - } - - inner(new_reference, true)?; - inner(new_proxy, false) - } - #[test] fn test_weakref_get_object() -> PyResult<()> { fn inner( @@ -1371,36 +726,5 @@ mod tests { inner(new_reference, true)?; inner(new_proxy, false) } - - #[test] - fn test_weakref_get_object_borrowed() -> PyResult<()> { - fn inner( - create_reference: impl for<'py> FnOnce( - &Bound<'py, PyAny>, - ) - -> PyResult>, - call_retrievable: bool, - ) -> PyResult<()> { - let not_call_retrievable = !call_retrievable; - - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = create_reference(object.bind(py))?; - - assert!(not_call_retrievable || reference.call0()?.is(&object)); - assert!(reference.get_object_borrowed().is(&object)); - - drop(object); - - assert!(not_call_retrievable || reference.call0()?.is_none()); - assert!(reference.get_object_borrowed().is_none()); - - Ok(()) - }) - } - - inner(new_reference, true)?; - inner(new_proxy, false) - } } } diff --git a/src/types/weakref/proxy.rs b/src/types/weakref/proxy.rs index f9c2bae6544..798b4b435c7 100644 --- a/src/types/weakref/proxy.rs +++ b/src/types/weakref/proxy.rs @@ -3,7 +3,7 @@ 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::{ffi, Borrowed, Bound, ToPyObject}; +use crate::{ffi, Bound, ToPyObject}; use super::PyWeakrefMethods; @@ -182,13 +182,6 @@ impl PyWeakrefProxy { } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefProxy> { - fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny> { - // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. - #![allow(deprecated)] - unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } - .expect("The 'weakref.ProxyType' (or `weakref.CallableProxyType`) instance should be valid (non-null and actually a weakref reference)") - } - fn get_object(&self) -> Bound<'py, PyAny> { let mut obj: *mut ffi::PyObject = std::ptr::null_mut(); match unsafe { ffi::compat::PyWeakref_GetRef(self.as_ptr(), &mut obj) } { @@ -369,41 +362,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefProxy::new(&object)?; - - { - // This test is a bit weird but ok. - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() - && obj.is_exact_instance(&class))); - } - - drop(object); - - { - // This test is a bit weird but ok. - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { @@ -433,35 +391,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefProxy::new(&object)?; - - { - // This test is a bit weird but ok. - let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() - && obj.is_exact_instance(&class))); - } - - drop(object); - - { - // This test is a bit weird but ok. - let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { @@ -480,26 +409,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefProxy::new(&object)?; - - assert!(reference.upgrade_borrowed().is_some()); - assert!(reference - .upgrade_borrowed() - .map_or(false, |obj| obj.is(&object))); - - drop(object); - - assert!(reference.upgrade_borrowed().is_none()); - - Ok(()) - }) - } - #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { @@ -516,23 +425,6 @@ mod tests { Ok(()) }) } - - #[test] - fn test_weakref_get_object_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefProxy::new(&object)?; - - assert!(reference.get_object_borrowed().is(&object)); - - drop(object); - - assert!(reference.get_object_borrowed().is_none()); - - Ok(()) - }) - } } // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable. @@ -639,37 +531,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefProxy::new(object.bind(py))?; - - { - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); - } - - drop(object); - - { - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { @@ -695,35 +556,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefProxy::new(object.bind(py))?; - - { - let obj = unsafe { - reference.upgrade_borrowed_as_unchecked::() - }; - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); - } - - drop(object); - - { - let obj = unsafe { - reference.upgrade_borrowed_as_unchecked::() - }; - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { @@ -741,25 +573,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefProxy::new(object.bind(py))?; - - assert!(reference.upgrade_borrowed().is_some()); - assert!(reference - .upgrade_borrowed() - .map_or(false, |obj| obj.is(&object))); - - drop(object); - - assert!(reference.upgrade_borrowed().is_none()); - - Ok(()) - }) - } - #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { @@ -775,22 +588,6 @@ mod tests { Ok(()) }) } - - #[test] - fn test_weakref_get_object_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefProxy::new(object.bind(py))?; - - assert!(reference.get_object_borrowed().is(&object)); - - drop(object); - - assert!(reference.get_object_borrowed().is_none()); - - Ok(()) - }) - } } } @@ -902,41 +699,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefProxy::new(&object)?; - - { - // This test is a bit weird but ok. - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() - && obj.is_exact_instance(&class))); - } - - drop(object); - - { - // This test is a bit weird but ok. - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { @@ -966,35 +728,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefProxy::new(&object)?; - - { - // This test is a bit weird but ok. - let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() - && obj.is_exact_instance(&class))); - } - - drop(object); - - { - // This test is a bit weird but ok. - let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { @@ -1013,26 +746,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefProxy::new(&object)?; - - assert!(reference.upgrade_borrowed().is_some()); - assert!(reference - .upgrade_borrowed() - .map_or(false, |obj| obj.is(&object))); - - drop(object); - - assert!(reference.upgrade_borrowed().is_none()); - - Ok(()) - }) - } - #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { @@ -1049,23 +762,6 @@ mod tests { Ok(()) }) } - - #[test] - fn test_weakref_get_object_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefProxy::new(&object)?; - - assert!(reference.get_object_borrowed().is(&object)); - - drop(object); - - assert!(reference.get_object_borrowed().is_none()); - - Ok(()) - }) - } } // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable. @@ -1166,36 +862,6 @@ mod tests { Ok(()) }) } - #[test] - fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefProxy::new(object.bind(py))?; - - { - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); - } - - drop(object); - - { - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_none()); - } - - Ok(()) - }) - } #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { @@ -1221,34 +887,6 @@ mod tests { Ok(()) }) } - #[test] - fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefProxy::new(object.bind(py))?; - - { - let obj = unsafe { - reference.upgrade_borrowed_as_unchecked::() - }; - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); - } - - drop(object); - - { - let obj = unsafe { - reference.upgrade_borrowed_as_unchecked::() - }; - - assert!(obj.is_none()); - } - - Ok(()) - }) - } #[test] fn test_weakref_upgrade() -> PyResult<()> { @@ -1267,25 +905,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefProxy::new(object.bind(py))?; - - assert!(reference.upgrade_borrowed().is_some()); - assert!(reference - .upgrade_borrowed() - .map_or(false, |obj| obj.is(&object))); - - drop(object); - - assert!(reference.upgrade_borrowed().is_none()); - - Ok(()) - }) - } - #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { @@ -1301,22 +920,6 @@ mod tests { Ok(()) }) } - - #[test] - fn test_weakref_get_object_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefProxy::new(object.bind(py))?; - - assert!(reference.get_object_borrowed().is(&object)); - - drop(object); - - assert!(reference.get_object_borrowed().is_none()); - - Ok(()) - }) - } } } } diff --git a/src/types/weakref/reference.rs b/src/types/weakref/reference.rs index 7b1c78f0124..e28bc7264d5 100644 --- a/src/types/weakref/reference.rs +++ b/src/types/weakref/reference.rs @@ -191,13 +191,6 @@ impl PyWeakrefReference { } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefReference> { - fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny> { - // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. - #![allow(deprecated)] - unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } - .expect("The 'weakref.ReferenceType' instance should be valid (non-null and actually a weakref reference)") - } - fn get_object(&self) -> Bound<'py, PyAny> { let mut obj: *mut ffi::PyObject = std::ptr::null_mut(); match unsafe { ffi::compat::PyWeakref_GetRef(self.as_ptr(), &mut obj) } { @@ -344,41 +337,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefReference::new(&object)?; - - { - // This test is a bit weird but ok. - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() - && obj.is_exact_instance(&class))); - } - - drop(object); - - { - // This test is a bit weird but ok. - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { @@ -408,35 +366,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefReference::new(&object)?; - - { - // This test is a bit weird but ok. - let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() - && obj.is_exact_instance(&class))); - } - - drop(object); - - { - // This test is a bit weird but ok. - let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { @@ -457,28 +386,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefReference::new(&object)?; - - assert!(reference.call0()?.is(&object)); - assert!(reference.upgrade_borrowed().is_some()); - assert!(reference - .upgrade_borrowed() - .map_or(false, |obj| obj.is(&object))); - - drop(object); - - assert!(reference.call0()?.is_none()); - assert!(reference.upgrade_borrowed().is_none()); - - Ok(()) - }) - } - #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { @@ -498,25 +405,6 @@ mod tests { Ok(()) }) } - - #[test] - fn test_weakref_get_object_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let class = get_type(py)?; - let object = class.call0()?; - let reference = PyWeakrefReference::new(&object)?; - - assert!(reference.call0()?.is(&object)); - assert!(reference.get_object_borrowed().is(&object)); - - drop(object); - - assert!(reference.call0()?.is_none()); - assert!(reference.get_object_borrowed().is_none()); - - Ok(()) - }) - } } // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable. @@ -598,37 +486,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefReference::new(object.bind(py))?; - - { - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); - } - - drop(object); - - { - let obj = reference.upgrade_borrowed_as::(); - - assert!(obj.is_ok()); - let obj = obj.unwrap(); - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { @@ -654,33 +511,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefReference::new(object.bind(py))?; - - { - let obj = - unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_some()); - assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); - } - - drop(object); - - { - let obj = - unsafe { reference.upgrade_borrowed_as_unchecked::() }; - - assert!(obj.is_none()); - } - - Ok(()) - }) - } - #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { @@ -700,27 +530,6 @@ mod tests { }) } - #[test] - fn test_weakref_upgrade_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefReference::new(object.bind(py))?; - - assert!(reference.call0()?.is(&object)); - assert!(reference.upgrade_borrowed().is_some()); - assert!(reference - .upgrade_borrowed() - .map_or(false, |obj| obj.is(&object))); - - drop(object); - - assert!(reference.call0()?.is_none()); - assert!(reference.upgrade_borrowed().is_none()); - - Ok(()) - }) - } - #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { @@ -739,23 +548,5 @@ mod tests { Ok(()) }) } - - #[test] - fn test_weakref_get_object_borrowed() -> PyResult<()> { - Python::with_gil(|py| { - let object = Py::new(py, WeakrefablePyClass {})?; - let reference = PyWeakrefReference::new(object.bind(py))?; - - assert!(reference.call0()?.is(&object)); - assert!(reference.get_object_borrowed().is(&object)); - - drop(object); - - assert!(reference.call0()?.is_none()); - assert!(reference.get_object_borrowed().is_none()); - - Ok(()) - }) - } } } From b4a4e1200db08e91e67e02e38eb40bf7eb7b6361 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Fri, 27 Sep 2024 08:28:17 -0600 Subject: [PATCH 9/9] fix lints about unused imports --- src/types/weakref/anyref.rs | 4 ++-- src/types/weakref/reference.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/types/weakref/anyref.rs b/src/types/weakref/anyref.rs index 4a9a61b43e6..06d91ea024e 100644 --- a/src/types/weakref/anyref.rs +++ b/src/types/weakref/anyref.rs @@ -1,11 +1,11 @@ -use crate::err::{DowncastError, PyResult}; +use crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::type_object::{PyTypeCheck, PyTypeInfo}; use crate::types::{ any::{PyAny, PyAnyMethods}, PyNone, }; -use crate::{ffi, Borrowed, Bound}; +use crate::{ffi, Bound}; /// Represents any Python `weakref` reference. /// diff --git a/src/types/weakref/reference.rs b/src/types/weakref/reference.rs index e28bc7264d5..cc8bc3d55f5 100644 --- a/src/types/weakref/reference.rs +++ b/src/types/weakref/reference.rs @@ -2,7 +2,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::{ffi, Borrowed, Bound, ToPyObject}; +use crate::{ffi, Bound, ToPyObject}; #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] use crate::type_object::PyTypeCheck;