diff --git a/newsfragments/5404.added.md b/newsfragments/5404.added.md new file mode 100644 index 00000000000..0d6d8492826 --- /dev/null +++ b/newsfragments/5404.added.md @@ -0,0 +1 @@ +Implement `PyTypeInfo` on `PyWeakrefReference` when using the stable ABI \ No newline at end of file diff --git a/src/types/weakref/reference.rs b/src/types/weakref/reference.rs index bf76fd706c7..492da7888b4 100644 --- a/src/types/weakref/reference.rs +++ b/src/types/weakref/reference.rs @@ -1,11 +1,16 @@ use crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; +#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] +use crate::sync::PyOnceLock; use crate::types::any::PyAny; -use crate::{ffi, Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt}; - #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] -use crate::type_object::PyTypeCheck; +use crate::types::typeobject::PyTypeMethods; +#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] +use crate::types::PyType; +#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] +use crate::Py; +use crate::{ffi, Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt}; use super::PyWeakrefMethods; @@ -16,7 +21,7 @@ use super::PyWeakrefMethods; pub struct PyWeakrefReference(PyAny); #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] -pyobject_subclassable_native_type!(PyWeakrefReference, crate::ffi::PyWeakReference); +pyobject_subclassable_native_type!(PyWeakrefReference, ffi::PyWeakReference); #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] pyobject_native_type!( @@ -30,18 +35,17 @@ pyobject_native_type!( // When targeting alternative or multiple interpreters, it is better to not use the internal API. #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] -pyobject_native_type_named!(PyWeakrefReference); - -#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] -impl PyTypeCheck for PyWeakrefReference { - const NAME: &'static str = "weakref.ReferenceType"; - #[cfg(feature = "experimental-inspect")] - const PYTHON_TYPE: &'static str = "weakref.ReferenceType"; - - fn type_check(object: &Bound<'_, PyAny>) -> bool { - unsafe { ffi::PyWeakref_CheckRef(object.as_ptr()) > 0 } - } -} +pyobject_native_type_core!( + PyWeakrefReference, + |py| { + static TYPE: PyOnceLock> = PyOnceLock::new(); + TYPE.import(py, "weakref", "ref") + .unwrap() + .as_type_ptr() + }, + #module=Some("weakref"), + #checkfunction=ffi::PyWeakref_CheckRef +); impl PyWeakrefReference { /// Constructs a new Weak Reference (`weakref.ref`/`weakref.ReferenceType`) for the given object. @@ -238,7 +242,7 @@ mod tests { mod python_class { use super::*; - use crate::ffi; + use crate::{ffi, PyTypeInfo}; use crate::{py_result_ext::PyResultExt, types::PyType}; use std::ptr; @@ -372,6 +376,18 @@ mod tests { Ok(()) }) } + + #[test] + fn test_type_object() -> PyResult<()> { + Python::attach(|py| { + let class = get_type(py)?; + let object = class.call0()?; + let reference = PyWeakrefReference::new(&object)?; + + assert!(reference.is_instance(&PyWeakrefReference::type_object(py))?); + Ok(()) + }) + } } // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable.