feature gate deprecated APIs for `Py` (#4142)
This commit is contained in:
parent
261d27d197
commit
dc9a41521a
|
@ -177,9 +177,11 @@ What happens to the memory when the last `Py<PyAny>` is dropped and its
|
||||||
reference count reaches zero? It depends whether or not we are holding the GIL.
|
reference count reaches zero? It depends whether or not we are holding the GIL.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
# #![allow(unused_imports)]
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::types::PyString;
|
# use pyo3::types::PyString;
|
||||||
# fn main() -> PyResult<()> {
|
# fn main() -> PyResult<()> {
|
||||||
|
# #[cfg(feature = "gil-refs")]
|
||||||
Python::with_gil(|py| -> PyResult<()> {
|
Python::with_gil(|py| -> PyResult<()> {
|
||||||
#[allow(deprecated)] // py.eval() is part of the GIL Refs API
|
#[allow(deprecated)] // py.eval() is part of the GIL Refs API
|
||||||
let hello: Py<PyString> = py.eval("\"Hello World!\"", None, None)?.extract()?;
|
let hello: Py<PyString> = py.eval("\"Hello World!\"", None, None)?.extract()?;
|
||||||
|
@ -203,9 +205,12 @@ This example wasn't very interesting. We could have just used a GIL-bound
|
||||||
we are *not* holding the GIL?
|
we are *not* holding the GIL?
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
# #![allow(unused_imports)]
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::types::PyString;
|
# use pyo3::types::PyString;
|
||||||
# fn main() -> PyResult<()> {
|
# fn main() -> PyResult<()> {
|
||||||
|
# #[cfg(feature = "gil-refs")]
|
||||||
|
# {
|
||||||
let hello: Py<PyString> = Python::with_gil(|py| {
|
let hello: Py<PyString> = Python::with_gil(|py| {
|
||||||
#[allow(deprecated)] // py.eval() is part of the GIL Refs API
|
#[allow(deprecated)] // py.eval() is part of the GIL Refs API
|
||||||
py.eval("\"Hello World!\"", None, None)?.extract()
|
py.eval("\"Hello World!\"", None, None)?.extract()
|
||||||
|
@ -224,6 +229,7 @@ Python::with_gil(|py|
|
||||||
// Memory for `hello` is released here.
|
// Memory for `hello` is released here.
|
||||||
# ()
|
# ()
|
||||||
);
|
);
|
||||||
|
# }
|
||||||
# Ok(())
|
# Ok(())
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
@ -237,9 +243,12 @@ We can avoid the delay in releasing memory if we are careful to drop the
|
||||||
`Py<Any>` while the GIL is held.
|
`Py<Any>` while the GIL is held.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
# #![allow(unused_imports)]
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::types::PyString;
|
# use pyo3::types::PyString;
|
||||||
# fn main() -> PyResult<()> {
|
# fn main() -> PyResult<()> {
|
||||||
|
# #[cfg(feature = "gil-refs")]
|
||||||
|
# {
|
||||||
#[allow(deprecated)] // py.eval() is part of the GIL Refs API
|
#[allow(deprecated)] // py.eval() is part of the GIL Refs API
|
||||||
let hello: Py<PyString> =
|
let hello: Py<PyString> =
|
||||||
Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?;
|
Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?;
|
||||||
|
@ -252,6 +261,7 @@ Python::with_gil(|py| {
|
||||||
}
|
}
|
||||||
drop(hello); // Memory released here.
|
drop(hello); // Memory released here.
|
||||||
});
|
});
|
||||||
|
# }
|
||||||
# Ok(())
|
# Ok(())
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
@ -263,9 +273,12 @@ that rather than being released immediately, the memory will not be released
|
||||||
until the GIL is dropped.
|
until the GIL is dropped.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
# #![allow(unused_imports)]
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::types::PyString;
|
# use pyo3::types::PyString;
|
||||||
# fn main() -> PyResult<()> {
|
# fn main() -> PyResult<()> {
|
||||||
|
# #[cfg(feature = "gil-refs")]
|
||||||
|
# {
|
||||||
#[allow(deprecated)] // py.eval() is part of the GIL Refs API
|
#[allow(deprecated)] // py.eval() is part of the GIL Refs API
|
||||||
let hello: Py<PyString> =
|
let hello: Py<PyString> =
|
||||||
Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?;
|
Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?;
|
||||||
|
@ -280,6 +293,7 @@ Python::with_gil(|py| {
|
||||||
// Do more stuff...
|
// Do more stuff...
|
||||||
// Memory released here at end of `with_gil()` closure.
|
// Memory released here at end of `with_gil()` closure.
|
||||||
});
|
});
|
||||||
|
# }
|
||||||
# Ok(())
|
# Ok(())
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
|
|
@ -107,7 +107,7 @@ fn main() -> PyResult<()> {
|
||||||
|
|
||||||
<div class="warning">
|
<div class="warning">
|
||||||
|
|
||||||
During PyO3's [migration from "GIL Refs" to the `Bound<T>` smart pointer](../migration.md#migrating-from-the-gil-refs-api-to-boundt), [`Py<T>::call`]({{#PYO3_DOCS_URL}}/pyo3/struct.Py.html#method.call) is temporarily named `call_bound` (and `call_method` is temporarily `call_method_bound`).
|
During PyO3's [migration from "GIL Refs" to the `Bound<T>` smart pointer](../migration.md#migrating-from-the-gil-refs-api-to-boundt), `Py<T>::call` is temporarily named [`Py<T>::call_bound`]({{#PYO3_DOCS_URL}}/pyo3/struct.Py.html#method.call_bound) (and `call_method` is temporarily `call_method_bound`).
|
||||||
|
|
||||||
(This temporary naming is only the case for the `Py<T>` smart pointer. The methods on the `&PyAny` GIL Ref such as `call` have not been given replacements, and the methods on the `Bound<PyAny>` smart pointer such as [`Bound<PyAny>::call`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call) already use follow the newest API conventions.)
|
(This temporary naming is only the case for the `Py<T>` smart pointer. The methods on the `&PyAny` GIL Ref such as `call` have not been given replacements, and the methods on the `Bound<PyAny>` smart pointer such as [`Bound<PyAny>::call`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call) already use follow the newest API conventions.)
|
||||||
|
|
||||||
|
|
|
@ -353,8 +353,10 @@ let _: Py<PyList> = obj.extract()?;
|
||||||
For a `&PyAny` object reference `any` where the underlying object is a `#[pyclass]`:
|
For a `&PyAny` object reference `any` where the underlying object is a `#[pyclass]`:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
# #![allow(unused_imports)]
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# #[pyclass] #[derive(Clone)] struct MyClass { }
|
# #[pyclass] #[derive(Clone)] struct MyClass { }
|
||||||
|
# #[cfg(feature = "gil-refs")]
|
||||||
# Python::with_gil(|py| -> PyResult<()> {
|
# Python::with_gil(|py| -> PyResult<()> {
|
||||||
#[allow(deprecated)] // into_ref is part of the deprecated GIL Refs API
|
#[allow(deprecated)] // into_ref is part of the deprecated GIL Refs API
|
||||||
let obj: &PyAny = Py::new(py, MyClass {})?.into_ref(py);
|
let obj: &PyAny = Py::new(py, MyClass {})?.into_ref(py);
|
||||||
|
|
|
@ -64,6 +64,7 @@ impl<'a> PyDowncastError<'a> {
|
||||||
|
|
||||||
/// Compatibility API to convert the Bound variant `DowncastError` into the
|
/// Compatibility API to convert the Bound variant `DowncastError` into the
|
||||||
/// gil-ref variant
|
/// gil-ref variant
|
||||||
|
#[cfg(feature = "gil-refs")]
|
||||||
pub(crate) fn from_downcast_err(DowncastError { from, to }: DowncastError<'a, 'a>) -> Self {
|
pub(crate) fn from_downcast_err(DowncastError { from, to }: DowncastError<'a, 'a>) -> Self {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
let from = unsafe { from.py().from_borrowed_ptr(from.as_ptr()) };
|
let from = unsafe { from.py().from_borrowed_ptr(from.as_ptr()) };
|
||||||
|
|
115
src/instance.rs
115
src/instance.rs
|
@ -1,4 +1,4 @@
|
||||||
use crate::err::{self, PyDowncastError, PyErr, PyResult};
|
use crate::err::{self, PyErr, PyResult};
|
||||||
use crate::impl_::pycell::PyClassObject;
|
use crate::impl_::pycell::PyClassObject;
|
||||||
use crate::pycell::{PyBorrowError, PyBorrowMutError};
|
use crate::pycell::{PyBorrowError, PyBorrowMutError};
|
||||||
use crate::pyclass::boolean_struct::{False, True};
|
use crate::pyclass::boolean_struct::{False, True};
|
||||||
|
@ -721,12 +721,12 @@ impl<T> IntoPy<PyObject> for Borrowed<'_, '_, T> {
|
||||||
///
|
///
|
||||||
/// This type does not auto-dereference to the inner object because you must prove you hold the GIL to access it.
|
/// This type does not auto-dereference to the inner object because you must prove you hold the GIL to access it.
|
||||||
/// Instead, call one of its methods to access the inner object:
|
/// Instead, call one of its methods to access the inner object:
|
||||||
/// - [`Py::as_ref`], to borrow a GIL-bound reference to the contained object.
|
/// - [`Py::bind`] or [`Py::into_bound`], to borrow a GIL-bound reference to the contained object.
|
||||||
/// - [`Py::borrow`], [`Py::try_borrow`], [`Py::borrow_mut`], or [`Py::try_borrow_mut`],
|
/// - [`Py::borrow`], [`Py::try_borrow`], [`Py::borrow_mut`], or [`Py::try_borrow_mut`],
|
||||||
/// to get a (mutable) reference to a contained pyclass, using a scheme similar to std's [`RefCell`].
|
/// to get a (mutable) reference to a contained pyclass, using a scheme similar to std's [`RefCell`].
|
||||||
/// See the [`PyCell` guide entry](https://pyo3.rs/latest/class.html#pycell-and-interior-mutability)
|
/// See the [guide entry](https://pyo3.rs/latest/class.html#bound-and-interior-mutability)
|
||||||
/// for more information.
|
/// for more information.
|
||||||
/// - You can call methods directly on `Py` with [`Py::call`], [`Py::call_method`] and friends.
|
/// - You can call methods directly on `Py` with [`Py::call_bound`], [`Py::call_method_bound`] and friends.
|
||||||
/// These require passing in the [`Python<'py>`](crate::Python) token but are otherwise similar to the corresponding
|
/// These require passing in the [`Python<'py>`](crate::Python) token but are otherwise similar to the corresponding
|
||||||
/// methods on [`PyAny`].
|
/// methods on [`PyAny`].
|
||||||
///
|
///
|
||||||
|
@ -991,12 +991,10 @@ where
|
||||||
/// assert!(my_class_cell.try_borrow().is_ok());
|
/// assert!(my_class_cell.try_borrow().is_ok());
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg_attr(
|
#[cfg(feature = "gil-refs")]
|
||||||
not(feature = "gil-refs"),
|
#[deprecated(
|
||||||
deprecated(
|
since = "0.21.0",
|
||||||
since = "0.21.0",
|
note = "use `obj.bind(py)` instead of `obj.as_ref(py)`"
|
||||||
note = "use `obj.bind(py)` instead of `obj.as_ref(py)`"
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
pub fn as_ref<'py>(&'py self, _py: Python<'py>) -> &'py T::AsRefTarget {
|
pub fn as_ref<'py>(&'py self, _py: Python<'py>) -> &'py T::AsRefTarget {
|
||||||
let any = self.as_ptr() as *const PyAny;
|
let any = self.as_ptr() as *const PyAny;
|
||||||
|
@ -1046,12 +1044,10 @@ where
|
||||||
/// obj.into_ref(py)
|
/// obj.into_ref(py)
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg_attr(
|
#[cfg(feature = "gil-refs")]
|
||||||
not(feature = "gil-refs"),
|
#[deprecated(
|
||||||
deprecated(
|
since = "0.21.0",
|
||||||
since = "0.21.0",
|
note = "use `obj.into_bound(py)` instead of `obj.into_ref(py)`"
|
||||||
note = "use `obj.into_bound(py)` instead of `obj.into_ref(py)`"
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
pub fn into_ref(self, py: Python<'_>) -> &T::AsRefTarget {
|
pub fn into_ref(self, py: Python<'_>) -> &T::AsRefTarget {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
@ -1464,12 +1460,10 @@ impl<T> Py<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated form of [`call_bound`][Py::call_bound].
|
/// Deprecated form of [`call_bound`][Py::call_bound].
|
||||||
#[cfg_attr(
|
#[cfg(feature = "gil-refs")]
|
||||||
not(feature = "gil-refs"),
|
#[deprecated(
|
||||||
deprecated(
|
since = "0.21.0",
|
||||||
since = "0.21.0",
|
note = "`call` will be replaced by `call_bound` in a future PyO3 version"
|
||||||
note = "`call` will be replaced by `call_bound` in a future PyO3 version"
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn call<A>(&self, py: Python<'_>, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
pub fn call<A>(&self, py: Python<'_>, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||||
|
@ -1506,12 +1500,10 @@ impl<T> Py<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated form of [`call_method_bound`][Py::call_method_bound].
|
/// Deprecated form of [`call_method_bound`][Py::call_method_bound].
|
||||||
#[cfg_attr(
|
#[cfg(feature = "gil-refs")]
|
||||||
not(feature = "gil-refs"),
|
#[deprecated(
|
||||||
deprecated(
|
since = "0.21.0",
|
||||||
since = "0.21.0",
|
note = "`call_method` will be replaced by `call_method_bound` in a future PyO3 version"
|
||||||
note = "`call_method` will be replaced by `call_method_bound` in a future PyO3 version"
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn call_method<N, A>(
|
pub fn call_method<N, A>(
|
||||||
|
@ -1779,6 +1771,7 @@ impl<T> std::convert::From<Bound<'_, T>> for Py<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// `&PyCell<T>` can be converted to `Py<T>`
|
// `&PyCell<T>` can be converted to `Py<T>`
|
||||||
|
#[cfg(feature = "gil-refs")]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl<T> std::convert::From<&crate::PyCell<T>> for Py<T>
|
impl<T> std::convert::From<&crate::PyCell<T>> for Py<T>
|
||||||
where
|
where
|
||||||
|
@ -1844,10 +1837,7 @@ where
|
||||||
{
|
{
|
||||||
/// Extracts `Self` from the source `PyObject`.
|
/// Extracts `Self` from the source `PyObject`.
|
||||||
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
|
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
|
||||||
// TODO update MSRV past 1.59 and use .cloned() to make
|
ob.downcast().cloned().map_err(Into::into)
|
||||||
// clippy happy
|
|
||||||
#[allow(clippy::map_clone)]
|
|
||||||
ob.downcast().map(Clone::clone).map_err(Into::into)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1888,21 +1878,22 @@ pub type PyObject = Py<PyAny>;
|
||||||
|
|
||||||
impl PyObject {
|
impl PyObject {
|
||||||
/// Deprecated form of [`PyObject::downcast_bound`]
|
/// Deprecated form of [`PyObject::downcast_bound`]
|
||||||
#[cfg_attr(
|
#[cfg(feature = "gil-refs")]
|
||||||
not(feature = "gil-refs"),
|
#[deprecated(
|
||||||
deprecated(
|
since = "0.21.0",
|
||||||
since = "0.21.0",
|
note = "`PyObject::downcast` will be replaced by `PyObject::downcast_bound` in a future PyO3 version"
|
||||||
note = "`PyObject::downcast` will be replaced by `PyObject::downcast_bound` in a future PyO3 version"
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn downcast<'py, T>(&'py self, py: Python<'py>) -> Result<&'py T, PyDowncastError<'py>>
|
pub fn downcast<'py, T>(
|
||||||
|
&'py self,
|
||||||
|
py: Python<'py>,
|
||||||
|
) -> Result<&'py T, crate::err::PyDowncastError<'py>>
|
||||||
where
|
where
|
||||||
T: PyTypeCheck<AsRefTarget = T>,
|
T: PyTypeCheck<AsRefTarget = T>,
|
||||||
{
|
{
|
||||||
self.downcast_bound::<T>(py)
|
self.downcast_bound::<T>(py)
|
||||||
.map(Bound::as_gil_ref)
|
.map(Bound::as_gil_ref)
|
||||||
.map_err(PyDowncastError::from_downcast_err)
|
.map_err(crate::err::PyDowncastError::from_downcast_err)
|
||||||
}
|
}
|
||||||
/// Downcast this `PyObject` to a concrete Python type or pyclass.
|
/// Downcast this `PyObject` to a concrete Python type or pyclass.
|
||||||
///
|
///
|
||||||
|
@ -1970,12 +1961,10 @@ impl PyObject {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Callers must ensure that the type is valid or risk type confusion.
|
/// Callers must ensure that the type is valid or risk type confusion.
|
||||||
#[cfg_attr(
|
#[cfg(feature = "gil-refs")]
|
||||||
not(feature = "gil-refs"),
|
#[deprecated(
|
||||||
deprecated(
|
since = "0.21.0",
|
||||||
since = "0.21.0",
|
note = "`PyObject::downcast_unchecked` will be replaced by `PyObject::downcast_bound_unchecked` in a future PyO3 version"
|
||||||
note = "`PyObject::downcast_unchecked` will be replaced by `PyObject::downcast_bound_unchecked` in a future PyO3 version"
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn downcast_unchecked<'py, T>(&'py self, py: Python<'py>) -> &T
|
pub unsafe fn downcast_unchecked<'py, T>(&'py self, py: Python<'py>) -> &T
|
||||||
|
@ -1997,35 +1986,31 @@ impl PyObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))]
|
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{Bound, Py, PyObject};
|
use super::{Bound, Py, PyObject};
|
||||||
use crate::types::any::PyAnyMethods;
|
use crate::types::any::PyAnyMethods;
|
||||||
use crate::types::{dict::IntoPyDict, PyDict, PyString};
|
use crate::types::{dict::IntoPyDict, PyDict, PyString};
|
||||||
use crate::types::{PyCapsule, PyStringMethods};
|
use crate::types::{PyCapsule, PyStringMethods};
|
||||||
use crate::{ffi, Borrowed, PyAny, PyNativeType, PyResult, Python, ToPyObject};
|
use crate::{ffi, Borrowed, PyAny, PyResult, Python, ToPyObject};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_call() {
|
fn test_call() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let obj = py.get_type::<PyDict>().to_object(py);
|
let obj = py.get_type_bound::<PyDict>().to_object(py);
|
||||||
|
|
||||||
let assert_repr = |obj: &PyAny, expected: &str| {
|
let assert_repr = |obj: &Bound<'_, PyAny>, expected: &str| {
|
||||||
assert_eq!(obj.repr().unwrap().to_str().unwrap(), expected);
|
assert_eq!(obj.repr().unwrap().to_cow().unwrap(), expected);
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_repr(obj.call0(py).unwrap().as_ref(py), "{}");
|
assert_repr(obj.call0(py).unwrap().bind(py), "{}");
|
||||||
assert_repr(obj.call1(py, ()).unwrap().as_ref(py), "{}");
|
assert_repr(obj.call1(py, ()).unwrap().bind(py), "{}");
|
||||||
assert_repr(obj.call(py, (), None).unwrap().as_ref(py), "{}");
|
assert_repr(obj.call_bound(py, (), None).unwrap().bind(py), "{}");
|
||||||
|
|
||||||
assert_repr(
|
assert_repr(obj.call1(py, ((('x', 1),),)).unwrap().bind(py), "{'x': 1}");
|
||||||
obj.call1(py, ((('x', 1),),)).unwrap().as_ref(py),
|
|
||||||
"{'x': 1}",
|
|
||||||
);
|
|
||||||
assert_repr(
|
assert_repr(
|
||||||
obj.call_bound(py, (), Some(&[('x', 1)].into_py_dict_bound(py)))
|
obj.call_bound(py, (), Some(&[('x', 1)].into_py_dict_bound(py)))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_ref(py),
|
.bind(py),
|
||||||
"{'x': 1}",
|
"{'x': 1}",
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -2037,7 +2022,7 @@ mod tests {
|
||||||
let obj: PyObject = PyDict::new_bound(py).into();
|
let obj: PyObject = PyDict::new_bound(py).into();
|
||||||
assert!(obj.call_method0(py, "asdf").is_err());
|
assert!(obj.call_method0(py, "asdf").is_err());
|
||||||
assert!(obj
|
assert!(obj
|
||||||
.call_method(py, "nonexistent_method", (1,), None)
|
.call_method_bound(py, "nonexistent_method", (1,), None)
|
||||||
.is_err());
|
.is_err());
|
||||||
assert!(obj.call_method0(py, "nonexistent_method").is_err());
|
assert!(obj.call_method0(py, "nonexistent_method").is_err());
|
||||||
assert!(obj.call_method1(py, "nonexistent_method", (1,)).is_err());
|
assert!(obj.call_method1(py, "nonexistent_method", (1,)).is_err());
|
||||||
|
@ -2083,7 +2068,7 @@ a = A()
|
||||||
|
|
||||||
assert!(instance
|
assert!(instance
|
||||||
.getattr(py, "foo")?
|
.getattr(py, "foo")?
|
||||||
.as_ref(py)
|
.bind(py)
|
||||||
.eq(PyString::new_bound(py, "bar"))?);
|
.eq(PyString::new_bound(py, "bar"))?);
|
||||||
|
|
||||||
instance.getattr(py, "foo")?;
|
instance.getattr(py, "foo")?;
|
||||||
|
@ -2109,7 +2094,7 @@ a = A()
|
||||||
|
|
||||||
instance.getattr(py, foo).unwrap_err();
|
instance.getattr(py, foo).unwrap_err();
|
||||||
instance.setattr(py, foo, bar)?;
|
instance.setattr(py, foo, bar)?;
|
||||||
assert!(instance.getattr(py, foo)?.as_ref(py).eq(bar)?);
|
assert!(instance.getattr(py, foo)?.bind(py).eq(bar)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2117,7 +2102,7 @@ a = A()
|
||||||
#[test]
|
#[test]
|
||||||
fn invalid_attr() -> PyResult<()> {
|
fn invalid_attr() -> PyResult<()> {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let instance: Py<PyAny> = py.eval("object()", None, None)?.into();
|
let instance: Py<PyAny> = py.eval_bound("object()", None, None)?.into();
|
||||||
|
|
||||||
instance.getattr(py, "foo").unwrap_err();
|
instance.getattr(py, "foo").unwrap_err();
|
||||||
|
|
||||||
|
@ -2130,7 +2115,7 @@ a = A()
|
||||||
#[test]
|
#[test]
|
||||||
fn test_py2_from_py_object() {
|
fn test_py2_from_py_object() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let instance: &PyAny = py.eval("object()", None, None).unwrap();
|
let instance = py.eval_bound("object()", None, None).unwrap();
|
||||||
let ptr = instance.as_ptr();
|
let ptr = instance.as_ptr();
|
||||||
let instance: Bound<'_, PyAny> = instance.extract().unwrap();
|
let instance: Bound<'_, PyAny> = instance.extract().unwrap();
|
||||||
assert_eq!(instance.as_ptr(), ptr);
|
assert_eq!(instance.as_ptr(), ptr);
|
||||||
|
@ -2141,7 +2126,7 @@ a = A()
|
||||||
fn test_py2_into_py_object() {
|
fn test_py2_into_py_object() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let instance = py
|
let instance = py
|
||||||
.eval("object()", None, None)
|
.eval_bound("object()", None, None)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_borrowed()
|
.as_borrowed()
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
|
@ -116,18 +116,17 @@
|
||||||
//! [`SendWrapper`]: https://docs.rs/send_wrapper/latest/send_wrapper/struct.SendWrapper.html
|
//! [`SendWrapper`]: https://docs.rs/send_wrapper/latest/send_wrapper/struct.SendWrapper.html
|
||||||
//! [`Rc`]: std::rc::Rc
|
//! [`Rc`]: std::rc::Rc
|
||||||
//! [`Py`]: crate::Py
|
//! [`Py`]: crate::Py
|
||||||
use crate::err::{self, PyDowncastError, PyErr, PyResult};
|
use crate::err::{self, PyErr, PyResult};
|
||||||
use crate::ffi_ptr_ext::FfiPtrExt;
|
use crate::ffi_ptr_ext::FfiPtrExt;
|
||||||
use crate::gil::{GILGuard, SuspendGIL};
|
use crate::gil::{GILGuard, SuspendGIL};
|
||||||
use crate::impl_::not_send::NotSend;
|
use crate::impl_::not_send::NotSend;
|
||||||
use crate::py_result_ext::PyResultExt;
|
use crate::py_result_ext::PyResultExt;
|
||||||
use crate::type_object::HasPyGilRef;
|
|
||||||
use crate::types::any::PyAnyMethods;
|
use crate::types::any::PyAnyMethods;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
PyAny, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, PyType,
|
PyAny, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, PyType,
|
||||||
};
|
};
|
||||||
use crate::version::PythonVersionInfo;
|
use crate::version::PythonVersionInfo;
|
||||||
use crate::{ffi, Bound, IntoPy, Py, PyNativeType, PyObject, PyTypeCheck, PyTypeInfo};
|
use crate::{ffi, Bound, IntoPy, Py, PyNativeType, PyObject, PyTypeInfo};
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
use crate::{gil::GILPool, FromPyPointer};
|
use crate::{gil::GILPool, FromPyPointer};
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
|
@ -839,16 +838,17 @@ impl<'py> Python<'py> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers the object in the release pool, and tries to downcast to specific type.
|
/// Registers the object in the release pool, and tries to downcast to specific type.
|
||||||
#[cfg_attr(
|
#[cfg(feature = "gil-refs")]
|
||||||
not(feature = "gil-refs"),
|
#[deprecated(
|
||||||
deprecated(
|
since = "0.21.0",
|
||||||
since = "0.21.0",
|
note = "use `obj.downcast_bound::<T>(py)` instead of `py.checked_cast_as::<T>(obj)`"
|
||||||
note = "use `obj.downcast_bound::<T>(py)` instead of `py.checked_cast_as::<T>(obj)`"
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'py T, PyDowncastError<'py>>
|
pub fn checked_cast_as<T>(
|
||||||
|
self,
|
||||||
|
obj: PyObject,
|
||||||
|
) -> Result<&'py T, crate::err::PyDowncastError<'py>>
|
||||||
where
|
where
|
||||||
T: PyTypeCheck<AsRefTarget = T>,
|
T: crate::PyTypeCheck<AsRefTarget = T>,
|
||||||
{
|
{
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
obj.into_ref(self).downcast()
|
obj.into_ref(self).downcast()
|
||||||
|
@ -860,16 +860,14 @@ impl<'py> Python<'py> {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Callers must ensure that ensure that the cast is valid.
|
/// Callers must ensure that ensure that the cast is valid.
|
||||||
#[cfg_attr(
|
#[cfg(feature = "gil-refs")]
|
||||||
not(feature = "gil-refs"),
|
#[deprecated(
|
||||||
deprecated(
|
since = "0.21.0",
|
||||||
since = "0.21.0",
|
note = "use `obj.downcast_bound_unchecked::<T>(py)` instead of `py.cast_as::<T>(obj)`"
|
||||||
note = "use `obj.downcast_bound_unchecked::<T>(py)` instead of `py.cast_as::<T>(obj)`"
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'py T
|
pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'py T
|
||||||
where
|
where
|
||||||
T: HasPyGilRef<AsRefTarget = T>,
|
T: crate::type_object::HasPyGilRef<AsRefTarget = T>,
|
||||||
{
|
{
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
obj.into_ref(self).downcast_unchecked()
|
obj.into_ref(self).downcast_unchecked()
|
||||||
|
|
|
@ -2705,17 +2705,16 @@ class SimpleClass:
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(deprecated)]
|
|
||||||
fn test_is_ellipsis() {
|
fn test_is_ellipsis() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let v = py
|
let v = py
|
||||||
.eval("...", None, None)
|
.eval_bound("...", None, None)
|
||||||
.map_err(|e| e.display(py))
|
.map_err(|e| e.display(py))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert!(v.is_ellipsis());
|
assert!(v.is_ellipsis());
|
||||||
|
|
||||||
let not_ellipsis = 5.to_object(py).into_ref(py);
|
let not_ellipsis = 5.to_object(py).into_bound(py);
|
||||||
assert!(!not_ellipsis.is_ellipsis());
|
assert!(!not_ellipsis.is_ellipsis());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -817,8 +817,6 @@ where
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[cfg(not(any(PyPy, GraalPy)))]
|
|
||||||
use crate::exceptions;
|
|
||||||
use crate::types::PyTuple;
|
use crate::types::PyTuple;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
|
|
||||||
|
@ -948,7 +946,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
#[cfg(not(any(PyPy, GraalPy)))]
|
#[cfg(all(not(any(PyPy, GraalPy)), feature = "gil-refs"))]
|
||||||
fn test_get_item_with_error() {
|
fn test_get_item_with_error() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let mut v = HashMap::new();
|
let mut v = HashMap::new();
|
||||||
|
@ -967,7 +965,7 @@ mod tests {
|
||||||
assert!(dict
|
assert!(dict
|
||||||
.get_item_with_error(dict)
|
.get_item_with_error(dict)
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.is_instance_of::<exceptions::PyTypeError>(py));
|
.is_instance_of::<crate::exceptions::PyTypeError>(py));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue