From a09b9f88345009975449ab1708833948d63cd3cf Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Thu, 21 Dec 2023 12:20:33 +0000 Subject: [PATCH] make `Bound` and `Borrowed` types public API --- newsfragments/3686.added.md | 1 + src/instance.rs | 4 ++-- src/prelude.rs | 24 +++++++++++------------- src/types/any.rs | 2 +- src/types/bytes.rs | 2 +- src/types/dict.rs | 4 ++-- src/types/list.rs | 4 ++-- src/types/mapping.rs | 2 +- src/types/sequence.rs | 2 +- src/types/string.rs | 2 +- 10 files changed, 23 insertions(+), 24 deletions(-) create mode 100644 newsfragments/3686.added.md diff --git a/newsfragments/3686.added.md b/newsfragments/3686.added.md new file mode 100644 index 00000000..f808df36 --- /dev/null +++ b/newsfragments/3686.added.md @@ -0,0 +1 @@ +Add `Bound` and `Borrowed` smart pointers as a new API for accessing Python objects. diff --git a/src/instance.rs b/src/instance.rs index 0030c020..e23054e6 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -45,7 +45,7 @@ pub unsafe trait PyNativeType: Sized { /// A GIL-attached equivalent to `Py`. #[repr(transparent)] -pub(crate) struct Bound<'py, T>(Python<'py>, ManuallyDrop>); +pub struct Bound<'py, T>(Python<'py>, ManuallyDrop>); impl<'py> Bound<'py, PyAny> { /// Constructs a new Bound from a pointer. Panics if ptr is null. @@ -224,7 +224,7 @@ unsafe impl AsPyPointer for Bound<'_, T> { /// /// Similarly, this type is `Copy` and `Clone`, like a shared reference (`&T`). #[repr(transparent)] -pub(crate) struct Borrowed<'a, 'py, T>(NonNull, PhantomData<&'a Py>, Python<'py>); +pub struct Borrowed<'a, 'py, T>(NonNull, PhantomData<&'a Py>, Python<'py>); impl<'py, T> Borrowed<'_, 'py, T> { /// Creates a new owned `Bound` from this borrowed reference by increasing the reference count. diff --git a/src/prelude.rs b/src/prelude.rs index fa7b433a..866b2226 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -12,7 +12,7 @@ pub use crate::conversion::{FromPyObject, IntoPy, ToPyObject}; #[allow(deprecated)] pub use crate::conversion::{PyTryFrom, PyTryInto}; pub use crate::err::{PyErr, PyResult}; -pub use crate::instance::{Py, PyObject}; +pub use crate::instance::{Borrowed, Bound, Py, PyObject}; pub use crate::marker::Python; pub use crate::pycell::{PyCell, PyRef, PyRefMut}; pub use crate::pyclass_init::PyClassInitializer; @@ -24,15 +24,13 @@ pub use pyo3_macros::{pyclass, pyfunction, pymethods, pymodule, FromPyObject}; #[cfg(feature = "macros")] pub use crate::wrap_pyfunction; -// Expected to become public API in 0.21 -// pub(crate) use crate::instance::Bound; // Will be stabilized with a different name -// pub(crate) use crate::types::any::PyAnyMethods; -// pub(crate) use crate::types::boolobject::PyBoolMethods; -// pub(crate) use crate::types::bytearray::PyByteArrayMethods; -// pub(crate) use crate::types::bytes::PyBytesMethods; -// pub(crate) use crate::types::dict::PyDictMethods; -// pub(crate) use crate::types::float::PyFloatMethods; -// pub(crate) use crate::types::list::PyListMethods; -// pub(crate) use crate::types::mapping::PyMappingMethods; -// pub(crate) use crate::types::sequence::PySequenceMethods; -// pub(crate) use crate::types::string::PyStringMethods; +pub use crate::types::any::PyAnyMethods; +pub use crate::types::boolobject::PyBoolMethods; +pub use crate::types::bytearray::PyByteArrayMethods; +pub use crate::types::bytes::PyBytesMethods; +pub use crate::types::dict::PyDictMethods; +pub use crate::types::float::PyFloatMethods; +pub use crate::types::list::PyListMethods; +pub use crate::types::mapping::PyMappingMethods; +pub use crate::types::sequence::PySequenceMethods; +pub use crate::types::string::PyStringMethods; diff --git a/src/types/any.rs b/src/types/any.rs index ccfee052..51fdabd4 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -996,7 +996,7 @@ impl PyAny { /// It is recommended you import this trait via `use pyo3::prelude::*` rather than /// by importing this trait directly. #[doc(alias = "PyAny")] -pub(crate) trait PyAnyMethods<'py> { +pub trait PyAnyMethods<'py> { /// Returns whether `self` and `other` point to the same object. To compare /// the equality of two objects (the `==` operator), use [`eq`](PyAny::eq). /// diff --git a/src/types/bytes.rs b/src/types/bytes.rs index 4d097ff3..3fd7e383 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -99,7 +99,7 @@ impl PyBytes { /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyBytes")] -pub(crate) trait PyBytesMethods<'py> { +pub trait PyBytesMethods<'py> { /// Gets the Python string as a byte slice. fn as_bytes(&self) -> &[u8]; } diff --git a/src/types/dict.rs b/src/types/dict.rs index a8f0e36f..61fc21f8 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -265,7 +265,7 @@ impl PyDict { /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyDict")] -pub(crate) trait PyDictMethods<'py> { +pub trait PyDictMethods<'py> { /// Returns a new dictionary that contains the same key-value pairs as self. /// /// This is equivalent to the Python expression `self.copy()`. @@ -545,7 +545,7 @@ impl<'a> IntoIterator for &'a PyDict { } /// PyO3 implementation of an iterator for a Python `dict` object. -pub(crate) struct PyDictIterator2<'py> { +pub struct PyDictIterator2<'py> { dict: Bound<'py, PyDict>, ppos: ffi::Py_ssize_t, di_used: ffi::Py_ssize_t, diff --git a/src/types/list.rs b/src/types/list.rs index cdb0f534..c042feac 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -256,7 +256,7 @@ index_impls!(PyList, "list", PyList::len, PyList::get_slice); /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyList")] -pub(crate) trait PyListMethods<'py> { +pub trait PyListMethods<'py> { /// Returns the length of the list. fn len(&self) -> usize; @@ -594,7 +594,7 @@ impl<'a> IntoIterator for &'a PyList { } /// Used by `PyList::iter()`. -pub(crate) struct PyListIterator2<'py> { +pub struct PyListIterator2<'py> { list: Bound<'py, PyList>, index: usize, length: usize, diff --git a/src/types/mapping.rs b/src/types/mapping.rs index a8ab8746..4eae0cec 100644 --- a/src/types/mapping.rs +++ b/src/types/mapping.rs @@ -117,7 +117,7 @@ impl PyMapping { /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyMapping")] -pub(crate) trait PyMappingMethods<'py> { +pub trait PyMappingMethods<'py> { /// Returns the number of objects in the mapping. /// /// This is equivalent to the Python expression `len(self)`. diff --git a/src/types/sequence.rs b/src/types/sequence.rs index 8dad82b9..0042780c 100644 --- a/src/types/sequence.rs +++ b/src/types/sequence.rs @@ -200,7 +200,7 @@ impl PySequence { /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PySequence")] -pub(crate) trait PySequenceMethods<'py> { +pub trait PySequenceMethods<'py> { /// Returns the number of objects in sequence. /// /// This is equivalent to the Python expression `len(self)`. diff --git a/src/types/string.rs b/src/types/string.rs index a3ad2c3e..cc05293a 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -239,7 +239,7 @@ impl PyString { /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyString")] -pub(crate) trait PyStringMethods<'py> { +pub trait PyStringMethods<'py> { /// Gets the Python string as a Rust UTF-8 string slice. /// /// Returns a `UnicodeEncodeError` if the input is not valid unicode