Remove AsPyRef for just Py::as_ref
This commit is contained in:
parent
bcb90775b4
commit
77ed6d6d69
|
@ -122,7 +122,7 @@ fn return_myclass() -> Py<MyClass> {
|
|||
}
|
||||
let gil = Python::acquire_gil();
|
||||
let obj = return_myclass();
|
||||
let cell = obj.as_ref(gil.python()); // AsPyRef::as_ref returns &PyCell
|
||||
let cell = obj.as_ref(gil.python()); // Py<MyClass>::as_ref returns &PyCell<MyClass>
|
||||
let obj_ref = cell.borrow(); // Get PyRef<T>
|
||||
assert_eq!(obj_ref.num, 1);
|
||||
```
|
||||
|
|
|
@ -46,7 +46,7 @@ There are also a few special types related to the GIL and Rust-defined `#[pyclas
|
|||
| What | Description |
|
||||
| ------------- | ------------------------------------- |
|
||||
| `Python` | A GIL token, used to pass to PyO3 constructors to prove ownership of the GIL |
|
||||
| `Py<T>` | A Python object isolated from the GIL lifetime. This can be sent to other threads. To call Python APIs using this object, it must be used with `AsPyRef::as_ref` to get an `&T` reference bound to the GIL. |
|
||||
| `Py<T>` | A Python object isolated from the GIL lifetime. This can be sent to other threads. |
|
||||
| `PyObject` | An alias for `Py<PyAny>` |
|
||||
| `&PyCell<T>` | A `#[pyclass]` value owned by Python. |
|
||||
| `PyRef<T>` | A `#[pyclass]` borrowed immutably. |
|
||||
|
|
|
@ -14,7 +14,6 @@ Now, the canonical implementation is always `IntoPy`, so downstream crates may n
|
|||
accordingly.
|
||||
|
||||
Before:
|
||||
|
||||
```rust,ignore
|
||||
# use pyo3::prelude::*;
|
||||
struct MyPyObjectWrapper(PyObject);
|
||||
|
@ -27,7 +26,6 @@ impl FromPy<MyPyObjectWrapper> for PyObject {
|
|||
```
|
||||
|
||||
After
|
||||
|
||||
```rust
|
||||
# use pyo3::prelude::*;
|
||||
struct MyPyObjectWrapper(PyObject);
|
||||
|
@ -42,7 +40,6 @@ impl IntoPy<PyObject> for MyPyObjectWrapper {
|
|||
Similarly, code which was using the `FromPy` trait can be trivially rewritten to use `IntoPy`.
|
||||
|
||||
Before:
|
||||
|
||||
```rust,ignore
|
||||
# use pyo3::prelude::*;
|
||||
# Python::with_gil(|py| {
|
||||
|
@ -62,6 +59,30 @@ let obj: PyObject = 1.234.into_py(py);
|
|||
This should change very little from a usage perspective. If you implemented traits for both
|
||||
`PyObject` and `Py<T>`, you may find you can just remove the `PyObject` implementation.
|
||||
|
||||
### `AsPyRef` has been removed
|
||||
The only implementor of `AsPyRef` was `Py<T>`, so the `AsPyRef::as_ref` method has been moved to
|
||||
`Py::as_ref`. This should require no code changes except removing the old `use` for code which
|
||||
did not use `pyo3::prelude`.
|
||||
|
||||
Before:
|
||||
```rust,ignore
|
||||
use pyo3::{AsPyRef, Py, types::PyList};
|
||||
# pyo3::Python::with_gil(|py| {
|
||||
let list_py: Py<PyList> = PyList::empty(py).into();
|
||||
let list_ref: &PyList = list_py.as_ref(py);
|
||||
# })
|
||||
```
|
||||
|
||||
After:
|
||||
```rust
|
||||
use pyo3::{Py, types::PyList};
|
||||
# pyo3::Python::with_gil(|py| {
|
||||
let list_py: Py<PyList> = PyList::empty(py).into();
|
||||
let list_ref: &PyList = list_py.as_ref(py);
|
||||
# })
|
||||
```
|
||||
|
||||
|
||||
## from 0.10.* to 0.11
|
||||
|
||||
### Stable Rust
|
||||
|
|
|
@ -140,7 +140,7 @@ Can be cloned using Python reference counts with `.clone()`.
|
|||
# let py = gil.python();
|
||||
let list: Py<PyList> = PyList::empty(py).into();
|
||||
|
||||
// Access the native type using AsPyRef::as_ref(py)
|
||||
// Access the native type using Py::as_ref(py)
|
||||
// (For #[pyclass] types, as_ref() will return &PyCell<T>)
|
||||
let _: &PyList = list.as_ref(py);
|
||||
|
||||
|
|
113
src/instance.rs
113
src/instance.rs
|
@ -33,15 +33,23 @@ pub unsafe trait PyNativeType: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
/// A Python object of known type.
|
||||
/// A Python object of known type T.
|
||||
///
|
||||
/// Accessing this object is thread-safe, since any access to its API requires a
|
||||
/// `Python<'py>` GIL token.
|
||||
/// Accessing this object is thread-safe, since any access to its API requires a `Python<'py>` GIL
|
||||
/// token. There are a few different ways to use the Python object contained:
|
||||
/// - [`Py::as_ref`](#method.as_ref) to borrow a GIL-bound reference to the contained object,
|
||||
/// - [`Py::borrow`](#method.borrow), [`Py::try_borrow`](#method.try_borrow),
|
||||
/// [`Py::borrow_mut`](#method.borrow_mut), or [`Py::try_borrow_mut`](#method.try_borrow_mut),
|
||||
/// to directly access a `#[pyclass]` value (which has RefCell-like behavior, see
|
||||
/// [the `PyCell` guide entry](https://pyo3.rs/master/class.html#pycell-and-interior-mutability)
|
||||
/// ).
|
||||
/// - Use methods directly on `Py`, such as [`Py::call`](#method.call) and
|
||||
/// [`Py::call_method`](#method.call_method).
|
||||
///
|
||||
/// See [the guide](https://pyo3.rs/master/types.html) for an explanation
|
||||
/// of the different Python object types.
|
||||
///
|
||||
/// Technically, it is a safe wrapper around `NonNull<ffi::PyObject>` with
|
||||
/// `Py<T>` is implemented as a safe wrapper around `NonNull<ffi::PyObject>` with
|
||||
/// specified type information.
|
||||
#[repr(transparent)]
|
||||
pub struct Py<T>(NonNull<ffi::PyObject>, PhantomData<T>);
|
||||
|
@ -63,7 +71,52 @@ where
|
|||
let ob = unsafe { Py::from_owned_ptr(py, obj as _) };
|
||||
Ok(ob)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Py<T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
/// Borrows a GIL-bound reference to the contained `T`. By binding to the GIL lifetime, this
|
||||
/// allows the GIL-bound reference to not require `Python` for any of its methods.
|
||||
///
|
||||
/// For native types, this reference is `&T`. For pyclasses, this is `&PyCell<T>`.
|
||||
///
|
||||
/// # Examples
|
||||
/// Get access to `&PyList` from `Py<PyList>`:
|
||||
///
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// # use pyo3::types::PyList;
|
||||
/// # Python::with_gil(|py| {
|
||||
/// let list: Py<PyList> = PyList::empty(py).into();
|
||||
/// let list: &PyList = list.as_ref(py);
|
||||
/// assert_eq!(list.len(), 0);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// Get access to `&PyCell<MyClass>` from `Py<MyClass>`:
|
||||
///
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// #[pyclass]
|
||||
/// struct MyClass { }
|
||||
/// # Python::with_gil(|py| {
|
||||
/// let my_class: Py<MyClass> = Py::new(py, MyClass { }).unwrap();
|
||||
/// let my_class_cell: &PyCell<MyClass> = my_class.as_ref(py);
|
||||
/// assert!(my_class_cell.try_borrow().is_ok());
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn as_ref<'py>(&'py self, _py: Python<'py>) -> &'py T::AsRefTarget {
|
||||
let any = self.as_ptr() as *const PyAny;
|
||||
unsafe { PyNativeType::unchecked_downcast(&*any) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Py<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
/// Immutably borrows the value `T`. This borrow lasts untill the returned `PyRef` exists.
|
||||
///
|
||||
/// Equivalent to `self.as_ref(py).borrow()` -
|
||||
|
@ -355,58 +408,6 @@ impl<T> Py<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Retrieves `&'py` types from `Py<T>` or `PyObject`.
|
||||
///
|
||||
/// # Examples
|
||||
/// `PyObject::as_ref` returns `&PyAny`.
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// let obj: PyObject = {
|
||||
/// let gil = Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// py.eval("[]", None, None).unwrap().to_object(py)
|
||||
/// };
|
||||
/// let gil = Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// assert_eq!(obj.as_ref(py).len().unwrap(), 0);
|
||||
/// ```
|
||||
///
|
||||
/// `Py<T>::as_ref` returns `&PyDict`, `&PyList` or so for native types, and `&PyCell<T>`
|
||||
/// for `#[pyclass]`.
|
||||
/// ```
|
||||
/// # use pyo3::prelude::*;
|
||||
/// #[pyclass]
|
||||
/// struct Counter {
|
||||
/// count: usize,
|
||||
/// }
|
||||
/// let counter = {
|
||||
/// let gil = Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// Py::new(py, Counter { count: 0}).unwrap()
|
||||
/// };
|
||||
/// let gil = Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// let counter_cell: &PyCell<Counter> = counter.as_ref(py);
|
||||
/// let counter_ref = counter_cell.borrow();
|
||||
/// assert_eq!(counter_ref.count, 0);
|
||||
/// ```
|
||||
pub trait AsPyRef: Sized {
|
||||
type Target;
|
||||
/// Return reference to object.
|
||||
fn as_ref<'p>(&'p self, py: Python<'p>) -> &'p Self::Target;
|
||||
}
|
||||
|
||||
impl<T> AsPyRef for Py<T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
type Target = T::AsRefTarget;
|
||||
fn as_ref<'p>(&'p self, _py: Python<'p>) -> &'p Self::Target {
|
||||
let any = self.as_ptr() as *const PyAny;
|
||||
unsafe { PyNativeType::unchecked_downcast(&*any) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToPyObject for Py<T> {
|
||||
/// Converts `Py` instance -> PyObject.
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
|
|
|
@ -140,7 +140,7 @@ pub use crate::conversion::{
|
|||
};
|
||||
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult};
|
||||
pub use crate::gil::{GILGuard, GILPool};
|
||||
pub use crate::instance::{AsPyRef, Py, PyNativeType, PyObject};
|
||||
pub use crate::instance::{Py, PyNativeType, PyObject};
|
||||
pub use crate::pycell::{PyCell, PyRef, PyRefMut};
|
||||
pub use crate::pyclass::PyClass;
|
||||
pub use crate::pyclass_init::PyClassInitializer;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
pub use crate::err::{PyErr, PyResult};
|
||||
pub use crate::gil::GILGuard;
|
||||
pub use crate::instance::{AsPyRef, Py, PyObject};
|
||||
pub use crate::instance::{Py, PyObject};
|
||||
pub use crate::pycell::{PyCell, PyRef, PyRefMut};
|
||||
pub use crate::pyclass_init::PyClassInitializer;
|
||||
pub use crate::python::Python;
|
||||
|
|
|
@ -98,7 +98,7 @@ pub unsafe trait PyTypeInfo: Sized {
|
|||
/// Initializer for layout
|
||||
type Initializer: PyObjectInit<Self>;
|
||||
|
||||
/// Utility type to make AsPyRef work
|
||||
/// Utility type to make Py::as_ref work
|
||||
type AsRefTarget: crate::PyNativeType;
|
||||
|
||||
/// PyTypeObject instance for this type.
|
||||
|
|
|
@ -357,7 +357,6 @@ where
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::conversion::IntoPy;
|
||||
use crate::instance::AsPyRef;
|
||||
use crate::types::dict::IntoPyDict;
|
||||
#[cfg(not(PyPy))]
|
||||
use crate::types::PyList;
|
||||
|
|
|
@ -85,7 +85,6 @@ mod tests {
|
|||
use super::PyIterator;
|
||||
use crate::exceptions::PyTypeError;
|
||||
use crate::gil::GILPool;
|
||||
use crate::instance::AsPyRef;
|
||||
use crate::types::{PyDict, PyList};
|
||||
use crate::Python;
|
||||
use crate::ToPyObject;
|
||||
|
|
|
@ -225,7 +225,6 @@ where
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::instance::AsPyRef;
|
||||
use crate::types::PyList;
|
||||
use crate::Python;
|
||||
use crate::{IntoPy, PyObject, PyTryFrom, ToPyObject};
|
||||
|
|
|
@ -326,7 +326,6 @@ mod bigint_conversion {
|
|||
}
|
||||
impl<'source> FromPyObject<'source> for $rust_ty {
|
||||
fn extract(ob: &'source PyAny) -> PyResult<$rust_ty> {
|
||||
use crate::instance::AsPyRef;
|
||||
let py = ob.py();
|
||||
unsafe {
|
||||
let num = ffi::PyNumber_Index(ob.as_ptr());
|
||||
|
|
|
@ -396,7 +396,6 @@ impl<'v> PyTryFrom<'v> for PySequence {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::instance::AsPyRef;
|
||||
use crate::types::PySequence;
|
||||
use crate::AsPyPointer;
|
||||
use crate::Python;
|
||||
|
|
|
@ -303,7 +303,7 @@ impl<'a> std::iter::IntoIterator for &'a PyFrozenSet {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{PyFrozenSet, PySet};
|
||||
use crate::{AsPyRef, IntoPy, PyObject, PyTryFrom, Python, ToPyObject};
|
||||
use crate::{IntoPy, PyObject, PyTryFrom, Python, ToPyObject};
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
use std::iter::FromIterator;
|
||||
|
||||
|
|
|
@ -146,7 +146,6 @@ impl<'source> FromPyObject<'source> for String {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::PyString;
|
||||
use crate::instance::AsPyRef;
|
||||
use crate::Python;
|
||||
use crate::{FromPyObject, PyObject, PyTryFrom, ToPyObject};
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ tuple_conversion!(
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::types::{PyAny, PyTuple};
|
||||
use crate::{AsPyRef, PyTryFrom, Python, ToPyObject};
|
||||
use crate::{PyTryFrom, Python, ToPyObject};
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Test slf: PyRef/PyMutRef<Self>(especially, slf.into::<Py>) works
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::{PyBytes, PyString};
|
||||
use pyo3::{AsPyRef, PyCell, PyIterProtocol};
|
||||
use pyo3::{PyCell, PyIterProtocol};
|
||||
use std::collections::HashMap;
|
||||
|
||||
mod common;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::types::IntoPyDict;
|
||||
use pyo3::types::{PyDict, PyTuple};
|
||||
use pyo3::{py_run, wrap_pyfunction, AsPyRef, PyCell};
|
||||
use pyo3::{py_run, wrap_pyfunction, PyCell};
|
||||
|
||||
mod common;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use pyo3::{types::PyDict, AsPyRef, Py, PyNativeType, Python};
|
||||
use pyo3::{types::PyDict, Py, PyNativeType, Python};
|
||||
|
||||
fn main() {
|
||||
let gil = Python::acquire_gil();
|
||||
|
|
Loading…
Reference in New Issue