deprecate the use of `PyCell` in favor of `Bound` and `Py` (#3916)
* deprecate the use of `PyCell` in favor of `Bound` and `Py` * update `FromPyObject` for `T: PyClass + Clone` impl * move `PyCell` deprecation to the `gil-refs` feature gate and add a migration note
This commit is contained in:
parent
00eb014623
commit
70a7aa808d
|
@ -1230,6 +1230,7 @@ struct MyClass {
|
|||
|
||||
impl pyo3::types::DerefToPyAny for MyClass {}
|
||||
|
||||
# #[allow(deprecated)]
|
||||
unsafe impl pyo3::type_object::HasPyGilRef for MyClass {
|
||||
type AsRefTarget = pyo3::PyCell<Self>;
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ For a `&PyAny` object reference `any` where the underlying object is a `#[pyclas
|
|||
let obj: &PyAny = Py::new(py, MyClass {})?.into_ref(py);
|
||||
|
||||
// To &PyCell<MyClass> with PyAny::downcast
|
||||
# #[allow(deprecated)]
|
||||
let _: &PyCell<MyClass> = obj.downcast()?;
|
||||
|
||||
// To Py<PyAny> (aka PyObject) with .into()
|
||||
|
|
|
@ -1281,6 +1281,7 @@ fn impl_pytypeinfo(
|
|||
};
|
||||
|
||||
quote! {
|
||||
#[allow(deprecated)]
|
||||
unsafe impl _pyo3::type_object::HasPyGilRef for #cls {
|
||||
type AsRefTarget = _pyo3::PyCell<Self>;
|
||||
}
|
||||
|
|
|
@ -6,9 +6,7 @@ use crate::pyclass::boolean_struct::False;
|
|||
use crate::type_object::PyTypeInfo;
|
||||
use crate::types::any::PyAnyMethods;
|
||||
use crate::types::PyTuple;
|
||||
use crate::{
|
||||
ffi, gil, Bound, Py, PyAny, PyCell, PyClass, PyNativeType, PyObject, PyRef, PyRefMut, Python,
|
||||
};
|
||||
use crate::{ffi, gil, Bound, Py, PyAny, PyClass, PyNativeType, PyObject, PyRef, PyRefMut, Python};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// Returns a borrowed pointer to a Python object.
|
||||
|
@ -265,7 +263,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'py, T> FromPyObject<'py> for &'py PyCell<T>
|
||||
#[allow(deprecated)]
|
||||
impl<'py, T> FromPyObject<'py> for &'py crate::PyCell<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
|
@ -278,9 +277,9 @@ impl<T> FromPyObject<'_> for T
|
|||
where
|
||||
T: PyClass + Clone,
|
||||
{
|
||||
fn extract(obj: &PyAny) -> PyResult<Self> {
|
||||
let cell: &PyCell<Self> = obj.downcast()?;
|
||||
Ok(unsafe { cell.try_borrow_unguarded()?.clone() })
|
||||
fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
|
||||
let bound = obj.downcast::<Self>()?;
|
||||
Ok(bound.try_borrow()?.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,7 +388,7 @@ mod implementations {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'v, T> PyTryFrom<'v> for PyCell<T>
|
||||
impl<'v, T> PyTryFrom<'v> for crate::PyCell<T>
|
||||
where
|
||||
T: 'v + PyClass,
|
||||
{
|
||||
|
|
|
@ -240,7 +240,7 @@ mod tests {
|
|||
let array: [Foo; 8] = [Foo, Foo, Foo, Foo, Foo, Foo, Foo, Foo];
|
||||
let pyobject = array.into_py(py);
|
||||
let list = pyobject.downcast_bound::<PyList>(py).unwrap();
|
||||
let _cell: &crate::PyCell<Foo> = list.get_item(4).unwrap().extract().unwrap();
|
||||
let _bound = list.get_item(4).unwrap().downcast::<Foo>().unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ use crate::pycell::{PyBorrowError, PyBorrowMutError};
|
|||
use crate::pyclass::boolean_struct::False;
|
||||
use crate::types::{any::PyAnyMethods, PyModule, PyType};
|
||||
use crate::{
|
||||
ffi, Borrowed, Bound, DowncastError, Py, PyAny, PyCell, PyClass, PyClassInitializer, PyErr,
|
||||
PyObject, PyRef, PyRefMut, PyResult, PyTraverseError, PyTypeCheck, PyVisit, Python,
|
||||
ffi, Borrowed, Bound, DowncastError, Py, PyAny, PyClass, PyClassInitializer, PyErr, PyObject,
|
||||
PyRef, PyRefMut, PyResult, PyTraverseError, PyTypeCheck, PyVisit, Python,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CStr;
|
||||
|
@ -518,7 +518,8 @@ impl<'a> From<BoundRef<'a, 'a, PyModule>> for &'a PyModule {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'py, T: PyClass> From<BoundRef<'a, 'py, T>> for &'a PyCell<T> {
|
||||
#[allow(deprecated)]
|
||||
impl<'a, 'py, T: PyClass> From<BoundRef<'a, 'py, T>> for &'a crate::PyCell<T> {
|
||||
#[inline]
|
||||
fn from(bound: BoundRef<'a, 'py, T>) -> Self {
|
||||
bound.0.as_gil_ref()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::err::{self, PyDowncastError, PyErr, PyResult};
|
||||
use crate::impl_::pycell::PyClassObject;
|
||||
use crate::pycell::{PyBorrowError, PyBorrowMutError, PyCell};
|
||||
use crate::pycell::{PyBorrowError, PyBorrowMutError};
|
||||
use crate::pyclass::boolean_struct::{False, True};
|
||||
use crate::type_object::HasPyGilRef;
|
||||
use crate::types::{any::PyAnyMethods, string::PyStringMethods, typeobject::PyTypeMethods};
|
||||
|
@ -1698,11 +1698,12 @@ impl<T> std::convert::From<Bound<'_, T>> for Py<T> {
|
|||
}
|
||||
|
||||
// `&PyCell<T>` can be converted to `Py<T>`
|
||||
impl<T> std::convert::From<&PyCell<T>> for Py<T>
|
||||
#[allow(deprecated)]
|
||||
impl<T> std::convert::From<&crate::PyCell<T>> for Py<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
fn from(cell: &PyCell<T>) -> Self {
|
||||
fn from(cell: &crate::PyCell<T>) -> Self {
|
||||
cell.as_borrowed().to_owned().unbind()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,7 +315,9 @@ pub use crate::gil::GILPool;
|
|||
pub use crate::gil::{prepare_freethreaded_python, with_embedded_python_interpreter};
|
||||
pub use crate::instance::{Borrowed, Bound, Py, PyNativeType, PyObject};
|
||||
pub use crate::marker::Python;
|
||||
pub use crate::pycell::{PyCell, PyRef, PyRefMut};
|
||||
#[allow(deprecated)]
|
||||
pub use crate::pycell::PyCell;
|
||||
pub use crate::pycell::{PyRef, PyRefMut};
|
||||
pub use crate::pyclass::PyClass;
|
||||
pub use crate::pyclass_init::PyClassInitializer;
|
||||
pub use crate::type_object::{PyTypeCheck, PyTypeInfo};
|
||||
|
|
|
@ -14,7 +14,9 @@ pub use crate::conversion::{PyTryFrom, PyTryInto};
|
|||
pub use crate::err::{PyErr, PyResult};
|
||||
pub use crate::instance::{Borrowed, Bound, Py, PyObject};
|
||||
pub use crate::marker::Python;
|
||||
pub use crate::pycell::{PyCell, PyRef, PyRefMut};
|
||||
#[allow(deprecated)]
|
||||
pub use crate::pycell::PyCell;
|
||||
pub use crate::pycell::{PyRef, PyRefMut};
|
||||
pub use crate::pyclass_init::PyClassInitializer;
|
||||
pub use crate::types::{PyAny, PyModule};
|
||||
pub use crate::PyNativeType;
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
//! ) -> *mut pyo3::ffi::PyObject {
|
||||
//! use :: pyo3 as _pyo3;
|
||||
//! _pyo3::impl_::trampoline::noargs(_slf, _args, |py, _slf| {
|
||||
//! # #[allow(deprecated)]
|
||||
//! # #[allow(deprecated)]
|
||||
//! let _cell = py
|
||||
//! .from_borrowed_ptr::<_pyo3::PyAny>(_slf)
|
||||
//! .downcast::<_pyo3::PyCell<Number>>()?;
|
||||
|
@ -154,6 +154,7 @@
|
|||
//! # pub struct Number {
|
||||
//! # inner: u32,
|
||||
//! # }
|
||||
//! # #[allow(deprecated)]
|
||||
//! #[pyfunction]
|
||||
//! fn swap_numbers(a: &PyCell<Number>, b: &PyCell<Number>) {
|
||||
//! // Check that the pointers are unequal
|
||||
|
@ -250,13 +251,22 @@ use self::impl_::{PyClassObject, PyClassObjectLayout};
|
|||
/// ```
|
||||
/// For more information on how, when and why (not) to use `PyCell` please see the
|
||||
/// [module-level documentation](self).
|
||||
#[cfg_attr(
|
||||
not(feature = "gil-refs"),
|
||||
deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyCell` was merged into `Bound`, use that instead; see the migration guide for more info"
|
||||
)
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct PyCell<T: PyClassImpl>(PyClassObject<T>);
|
||||
|
||||
#[allow(deprecated)]
|
||||
unsafe impl<T: PyClass> PyNativeType for PyCell<T> {
|
||||
type AsRefSource = T;
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass> PyCell<T> {
|
||||
/// Makes a new `PyCell` on the Python heap and return the reference to it.
|
||||
///
|
||||
|
@ -478,9 +488,12 @@ impl<T: PyClass> PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
unsafe impl<T: PyClassImpl> PyLayout<T> for PyCell<T> {}
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass> PySizedLayout<T> for PyCell<T> {}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> PyTypeCheck for PyCell<T>
|
||||
where
|
||||
T: PyClass,
|
||||
|
@ -492,18 +505,21 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
unsafe impl<T: PyClass> AsPyPointer for PyCell<T> {
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
(self as *const _) as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass> ToPyObject for &PyCell<T> {
|
||||
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass> AsRef<PyAny> for PyCell<T> {
|
||||
fn as_ref(&self) -> &PyAny {
|
||||
#[allow(deprecated)]
|
||||
|
@ -513,6 +529,7 @@ impl<T: PyClass> AsRef<PyAny> for PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass> Deref for PyCell<T> {
|
||||
type Target = PyAny;
|
||||
|
||||
|
@ -524,6 +541,7 @@ impl<T: PyClass> Deref for PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T: PyClass + fmt::Debug> fmt::Debug for PyCell<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.try_borrow() {
|
||||
|
@ -748,6 +766,7 @@ impl<T: PyClass> IntoPy<PyObject> for &'_ PyRef<'_, T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<'a, T: PyClass> std::convert::TryFrom<&'a PyCell<T>> for crate::PyRef<'a, T> {
|
||||
type Error = PyBorrowError;
|
||||
fn try_from(cell: &'a crate::PyCell<T>) -> Result<Self, Self::Error> {
|
||||
|
@ -905,6 +924,7 @@ unsafe impl<'a, T: PyClass<Frozen = False>> AsPyPointer for PyRefMut<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<'a, T: PyClass<Frozen = False>> std::convert::TryFrom<&'a PyCell<T>>
|
||||
for crate::PyRefMut<'a, T>
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! `PyClass` and related traits.
|
||||
use crate::{
|
||||
callback::IntoPyCallbackOutput, ffi, impl_::pyclass::PyClassImpl, IntoPy, PyCell, PyObject,
|
||||
PyResult, PyTypeInfo, Python,
|
||||
callback::IntoPyCallbackOutput, ffi, impl_::pyclass::PyClassImpl, IntoPy, PyObject, PyResult,
|
||||
PyTypeInfo, Python,
|
||||
};
|
||||
use std::{cmp::Ordering, os::raw::c_int};
|
||||
|
||||
|
@ -15,7 +15,8 @@ pub use self::gc::{PyTraverseError, PyVisit};
|
|||
///
|
||||
/// The `#[pyclass]` attribute implements this trait for your Rust struct -
|
||||
/// you shouldn't implement this trait directly.
|
||||
pub trait PyClass: PyTypeInfo<AsRefTarget = PyCell<Self>> + PyClassImpl {
|
||||
#[allow(deprecated)]
|
||||
pub trait PyClass: PyTypeInfo<AsRefTarget = crate::PyCell<Self>> + PyClassImpl {
|
||||
/// Whether the pyclass is frozen.
|
||||
///
|
||||
/// This can be enabled via `#[pyclass(frozen)]`.
|
||||
|
|
|
@ -62,7 +62,7 @@ impl PySuper {
|
|||
/// (SubClass {}, BaseClass::new())
|
||||
/// }
|
||||
///
|
||||
/// fn method(self_: &PyCell<Self>) -> PyResult<&PyAny> {
|
||||
/// fn method<'py>(self_: &Bound<'py, Self>) -> PyResult<Bound<'py, PyAny>> {
|
||||
/// let super_ = self_.py_super()?;
|
||||
/// super_.call_method("method", (), None)
|
||||
/// }
|
||||
|
|
|
@ -24,11 +24,11 @@ struct TestBufferClass {
|
|||
#[pymethods]
|
||||
impl TestBufferClass {
|
||||
unsafe fn __getbuffer__(
|
||||
slf: &PyCell<Self>,
|
||||
slf: Bound<'_, Self>,
|
||||
view: *mut ffi::Py_buffer,
|
||||
flags: c_int,
|
||||
) -> PyResult<()> {
|
||||
fill_view_from_readonly_data(view, flags, &slf.borrow().vec, slf)
|
||||
fill_view_from_readonly_data(view, flags, &slf.borrow().vec, slf.into_any())
|
||||
}
|
||||
|
||||
unsafe fn __releasebuffer__(&self, view: *mut ffi::Py_buffer) {
|
||||
|
@ -105,12 +105,12 @@ fn test_releasebuffer_unraisable_error() {
|
|||
#[pymethods]
|
||||
impl ReleaseBufferError {
|
||||
unsafe fn __getbuffer__(
|
||||
slf: &PyCell<Self>,
|
||||
slf: Bound<'_, Self>,
|
||||
view: *mut ffi::Py_buffer,
|
||||
flags: c_int,
|
||||
) -> PyResult<()> {
|
||||
static BUF_BYTES: &[u8] = b"hello world";
|
||||
fill_view_from_readonly_data(view, flags, BUF_BYTES, slf)
|
||||
fill_view_from_readonly_data(view, flags, BUF_BYTES, slf.into_any())
|
||||
}
|
||||
|
||||
unsafe fn __releasebuffer__(&self, _view: *mut ffi::Py_buffer) -> PyResult<()> {
|
||||
|
@ -145,7 +145,7 @@ unsafe fn fill_view_from_readonly_data(
|
|||
view: *mut ffi::Py_buffer,
|
||||
flags: c_int,
|
||||
data: &[u8],
|
||||
owner: &PyAny,
|
||||
owner: Bound<'_, PyAny>,
|
||||
) -> PyResult<()> {
|
||||
if view.is_null() {
|
||||
return Err(PyBufferError::new_err("View is null"));
|
||||
|
|
|
@ -23,7 +23,7 @@ fn empty_class_with_new() {
|
|||
assert!(typeobj
|
||||
.call((), None)
|
||||
.unwrap()
|
||||
.downcast::<PyCell<EmptyClassWithNew>>()
|
||||
.downcast::<EmptyClassWithNew>()
|
||||
.is_ok());
|
||||
|
||||
// Calling with arbitrary args or kwargs is not ok
|
||||
|
@ -52,7 +52,7 @@ fn unit_class_with_new() {
|
|||
assert!(typeobj
|
||||
.call((), None)
|
||||
.unwrap()
|
||||
.downcast::<PyCell<UnitClassWithNew>>()
|
||||
.downcast::<UnitClassWithNew>()
|
||||
.is_ok());
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,15 +18,18 @@ struct Reader {
|
|||
|
||||
#[pymethods]
|
||||
impl Reader {
|
||||
fn clone_ref(slf: &PyCell<Self>) -> &PyCell<Self> {
|
||||
fn clone_ref<'a, 'py>(slf: &'a Bound<'py, Self>) -> &'a Bound<'py, Self> {
|
||||
slf
|
||||
}
|
||||
fn clone_ref_with_py<'py>(slf: &'py PyCell<Self>, _py: Python<'py>) -> &'py PyCell<Self> {
|
||||
fn clone_ref_with_py<'a, 'py>(
|
||||
slf: &'a Bound<'py, Self>,
|
||||
_py: Python<'py>,
|
||||
) -> &'a Bound<'py, Self> {
|
||||
slf
|
||||
}
|
||||
fn get_iter(slf: &PyCell<Self>, keys: Py<PyBytes>) -> Iter {
|
||||
fn get_iter(slf: &Bound<'_, Self>, keys: Py<PyBytes>) -> Iter {
|
||||
Iter {
|
||||
reader: slf.into(),
|
||||
reader: slf.clone().unbind(),
|
||||
keys,
|
||||
idx: 0,
|
||||
}
|
||||
|
|
|
@ -29,14 +29,14 @@ impl SubClass {
|
|||
(SubClass {}, BaseClass::new())
|
||||
}
|
||||
|
||||
fn method(self_: &PyCell<Self>) -> PyResult<&PyAny> {
|
||||
fn method<'py>(self_: &Bound<'py, Self>) -> PyResult<Bound<'py, PyAny>> {
|
||||
let super_ = self_.py_super()?;
|
||||
super_.call_method("method", (), None)
|
||||
}
|
||||
|
||||
fn method_super_new(self_: &PyCell<Self>) -> PyResult<&PyAny> {
|
||||
fn method_super_new<'py>(self_: &Bound<'py, Self>) -> PyResult<Bound<'py, PyAny>> {
|
||||
#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))]
|
||||
let super_ = PySuper::new(self_.get_type(), self_)?;
|
||||
let super_ = PySuper::new_bound(&self_.get_type(), self_)?;
|
||||
super_.call_method("method", (), None)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -367,7 +367,7 @@ fn test_methods() {
|
|||
let _ = a;
|
||||
}
|
||||
#[pyo3(text_signature = "($self, b)")]
|
||||
fn pyself_method(_this: &PyCell<Self>, b: i32) {
|
||||
fn pyself_method(_this: &Bound<'_, Self>, b: i32) {
|
||||
let _ = b;
|
||||
}
|
||||
#[classmethod]
|
||||
|
|
|
@ -124,7 +124,7 @@ impl PickleSupport {
|
|||
}
|
||||
|
||||
pub fn __reduce__<'py>(
|
||||
slf: &'py PyCell<Self>,
|
||||
slf: &Bound<'py, Self>,
|
||||
py: Python<'py>,
|
||||
) -> PyResult<(PyObject, Bound<'py, PyTuple>, PyObject)> {
|
||||
let cls = slf.to_object(py).getattr(py, "__class__")?;
|
||||
|
|
|
@ -29,7 +29,7 @@ fn py_get_of_mutable_class_fails(class: Py<MutableBase>) {
|
|||
class.get();
|
||||
}
|
||||
|
||||
fn pyclass_get_of_mutable_class_fails(class: &PyCell<MutableBase>) {
|
||||
fn pyclass_get_of_mutable_class_fails(class: &Bound<'_, MutableBase>) {
|
||||
class.get();
|
||||
}
|
||||
|
||||
|
|
|
@ -67,11 +67,11 @@ error[E0271]: type mismatch resolving `<MutableBase as PyClass>::Frozen == True`
|
|||
33 | class.get();
|
||||
| ^^^ expected `True`, found `False`
|
||||
|
|
||||
note: required by a bound in `pyo3::PyCell::<T>::get`
|
||||
--> src/pycell.rs
|
||||
note: required by a bound in `pyo3::Bound::<'py, T>::get`
|
||||
--> src/instance.rs
|
||||
|
|
||||
| pub fn get(&self) -> &T
|
||||
| --- required by a bound in this associated function
|
||||
| where
|
||||
| T: PyClass<Frozen = True> + Sync,
|
||||
| ^^^^^^^^^^^^^ required by this bound in `PyCell::<T>::get`
|
||||
| ^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::get`
|
||||
|
|
|
@ -8,15 +8,15 @@ struct NotThreadSafe {
|
|||
|
||||
fn main() {
|
||||
let obj = Python::with_gil(|py| {
|
||||
PyCell::new(py, NotThreadSafe { data: Rc::new(5) })
|
||||
Bound::new(py, NotThreadSafe { data: Rc::new(5) })
|
||||
.unwrap()
|
||||
.to_object(py)
|
||||
.unbind(py)
|
||||
});
|
||||
|
||||
std::thread::spawn(move || {
|
||||
Python::with_gil(|py| {
|
||||
// Uh oh, moved Rc to a new thread!
|
||||
let c: &PyCell<NotThreadSafe> = obj.as_ref(py).downcast().unwrap();
|
||||
let c = obj.bind(py).downcast::<NotThreadSafe>().unwrap();
|
||||
|
||||
assert_eq!(*c.borrow().data, 5);
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue