From 1b61cb015a498d383c4a9406e2179f3f2849d65e Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 23 Dec 2023 21:48:04 +0000 Subject: [PATCH 1/2] Add `.as_borrowed()` conversion from gil-refs to `Bound` --- newsfragments/3692.added.md | 1 + newsfragments/3692.changed.md | 1 + src/conversions/chrono.rs | 7 ++- src/err/mod.rs | 6 +- src/instance.rs | 42 +++++++------- src/prelude.rs | 1 + src/types/any.rs | 100 +++++++++++++++------------------- src/types/boolobject.rs | 6 +- src/types/bytearray.rs | 16 +++--- src/types/bytes.rs | 4 +- src/types/datetime.rs | 42 +++++++------- src/types/dict.rs | 32 +++++------ src/types/float.rs | 2 +- src/types/iterator.rs | 6 +- src/types/list.rs | 44 ++++++--------- src/types/mapping.rs | 31 ++++------- src/types/mod.rs | 3 +- src/types/pysuper.rs | 11 ++-- src/types/sequence.rs | 51 +++++++---------- src/types/string.rs | 10 ++-- 20 files changed, 185 insertions(+), 231 deletions(-) create mode 100644 newsfragments/3692.added.md create mode 100644 newsfragments/3692.changed.md diff --git a/newsfragments/3692.added.md b/newsfragments/3692.added.md new file mode 100644 index 00000000000..45cdd5aba28 --- /dev/null +++ b/newsfragments/3692.added.md @@ -0,0 +1 @@ +Add `PyNativeType::as_bound` to convert "GIL refs" to the new `Bound` smart pointer. diff --git a/newsfragments/3692.changed.md b/newsfragments/3692.changed.md new file mode 100644 index 00000000000..9535cbb23db --- /dev/null +++ b/newsfragments/3692.changed.md @@ -0,0 +1 @@ +Include `PyNativeType` in `pyo3::prelude`. diff --git a/src/conversions/chrono.rs b/src/conversions/chrono.rs index 83100f8023a..cc0eb73a8ef 100644 --- a/src/conversions/chrono.rs +++ b/src/conversions/chrono.rs @@ -42,7 +42,6 @@ //! } //! ``` use crate::exceptions::{PyTypeError, PyUserWarning, PyValueError}; -use crate::instance::Bound; #[cfg(Py_LIMITED_API)] use crate::sync::GILOnceCell; #[cfg(not(Py_LIMITED_API))] @@ -56,7 +55,9 @@ use crate::types::{ }; #[cfg(Py_LIMITED_API)] use crate::{intern, PyDowncastError}; -use crate::{FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject}; +use crate::{ + FromPyObject, IntoPy, PyAny, PyErr, PyNativeType, PyObject, PyResult, Python, ToPyObject, +}; use chrono::offset::{FixedOffset, Utc}; use chrono::{ DateTime, Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone, Timelike, @@ -466,7 +467,7 @@ fn warn_truncated_leap_second(obj: &PyAny) { "ignored leap-second, `datetime` does not support leap-seconds", 0, ) { - e.write_unraisable_bound(py, Some(Bound::borrowed_from_gil_ref(&obj))) + e.write_unraisable_bound(py, Some(&obj.as_borrowed())) }; } diff --git a/src/err/mod.rs b/src/err/mod.rs index c2d47a8f17a..ed719103646 100644 --- a/src/err/mod.rs +++ b/src/err/mod.rs @@ -7,7 +7,7 @@ use crate::{ exceptions::{self, PyBaseException}, ffi, }; -use crate::{IntoPy, Py, PyAny, PyObject, Python, ToPyObject}; +use crate::{IntoPy, Py, PyAny, PyNativeType, PyObject, Python, ToPyObject}; use std::borrow::Cow; use std::cell::UnsafeCell; use std::ffi::CString; @@ -542,7 +542,7 @@ impl PyErr { )] #[inline] pub fn write_unraisable(self, py: Python<'_>, obj: Option<&PyAny>) { - self.write_unraisable_bound(py, obj.as_ref().map(Bound::borrowed_from_gil_ref)) + self.write_unraisable_bound(py, obj.map(PyAny::as_borrowed).as_deref()) } /// Reports the error as unraisable. @@ -821,7 +821,7 @@ impl<'a> std::error::Error for PyDowncastError<'a> {} impl<'a> std::fmt::Display for PyDowncastError<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - display_downcast_error(f, Bound::borrowed_from_gil_ref(&self.from), &self.to) + display_downcast_error(f, &self.from.as_borrowed(), &self.to) } } diff --git a/src/instance.rs b/src/instance.rs index dae71e671d8..90e672c4fa5 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -28,6 +28,19 @@ pub unsafe trait PyNativeType: Sized { /// The form of this which is stored inside a `Py` smart pointer. type AsRefSource: HasPyGilRef; + /// Cast `&self` to a `Borrowed` smart pointer. + /// + /// `Borrowed` implements `Deref>`, so can also be used in locations + /// where `Bound` is expected. + /// + /// This is available as a migration tool to adjust code from the deprecated "GIL Refs" + /// API to the `Bound` smart pointer API. + fn as_borrowed(&self) -> Borrowed<'_, '_, Self::AsRefSource> { + // Safety: &'py Self is expected to be a Python pointer, + // so has the same layout as Borrowed<'py, 'py, T> + unsafe { std::mem::transmute(self) } + } + /// Returns a GIL marker constrained to the lifetime of this type. #[inline] fn py(&self) -> Python<'_> { @@ -184,18 +197,6 @@ impl<'py, T> Bound<'py, T> { self.into_non_null().as_ptr() } - /// Internal helper to convert e.g. &'a &'py PyDict to &'a Bound<'py, PyDict> for - /// backwards-compatibility during migration to removal of pool. - #[doc(hidden)] // public and doc(hidden) to use in examples and tests for now - pub fn borrowed_from_gil_ref<'a, U>(gil_ref: &'a &'py U) -> &'a Self - where - U: PyNativeType, - { - // Safety: &'py T::AsRefTarget is expected to be a Python pointer, - // so &'a &'py T::AsRefTarget has the same layout as &'a Bound<'py, T> - unsafe { std::mem::transmute(gil_ref) } - } - /// Casts this `Bound` as the corresponding "GIL Ref" type. /// /// This is a helper to be used for migration from the deprecated "GIL Refs" API. @@ -311,12 +312,6 @@ impl<'py, T> Borrowed<'py, 'py, T> where T: HasPyGilRef, { - pub(crate) fn from_gil_ref(gil_ref: &'py T::AsRefTarget) -> Self { - // Safety: &'py T::AsRefTarget is expected to be a Python pointer, - // so &'py T::AsRefTarget has the same layout as Self. - unsafe { std::mem::transmute(gil_ref) } - } - // pub(crate) fn into_gil_ref(self) -> &'py T::AsRefTarget { // // Safety: self is a borrow over `'py`. // unsafe { self.py().from_borrowed_ptr(self.0.as_ptr()) } @@ -1366,7 +1361,7 @@ where { /// Extracts `Self` from the source `PyObject`. fn extract(ob: &'a PyAny) -> PyResult { - Bound::borrowed_from_gil_ref(&ob) + ob.as_borrowed() .downcast() .map(Clone::clone) .map_err(Into::into) @@ -1485,7 +1480,7 @@ impl PyObject { mod tests { use super::{Bound, Py, PyObject}; use crate::types::{PyDict, PyString}; - use crate::{PyAny, PyResult, Python, ToPyObject}; + use crate::{PyAny, PyNativeType, PyResult, Python, ToPyObject}; #[test] fn test_call0() { @@ -1612,8 +1607,11 @@ a = A() #[test] fn test_py2_into_py_object() { Python::with_gil(|py| { - let instance: Bound<'_, PyAny> = - Bound::borrowed_from_gil_ref(&py.eval("object()", None, None).unwrap()).clone(); + let instance = py + .eval("object()", None, None) + .unwrap() + .as_borrowed() + .to_owned(); let ptr = instance.as_ptr(); let instance: PyObject = instance.clone().into(); assert_eq!(instance.as_ptr(), ptr); diff --git a/src/prelude.rs b/src/prelude.rs index 866b2226765..b06625dc36a 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -17,6 +17,7 @@ pub use crate::marker::Python; pub use crate::pycell::{PyCell, PyRef, PyRefMut}; pub use crate::pyclass_init::PyClassInitializer; pub use crate::types::{PyAny, PyModule}; +pub use crate::PyNativeType; #[cfg(feature = "macros")] pub use pyo3_macros::{pyclass, pyfunction, pymethods, pymodule, FromPyObject}; diff --git a/src/types/any.rs b/src/types/any.rs index b8e8c03ad06..edc74879cb6 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -73,7 +73,7 @@ impl PyAny { /// This is equivalent to the Python expression `self is other`. #[inline] pub fn is(&self, other: &T) -> bool { - Bound::borrowed_from_gil_ref(&self).is(other) + self.as_borrowed().is(other) } /// Determines whether this object has the given attribute. @@ -102,7 +102,7 @@ impl PyAny { where N: IntoPy>, { - Bound::borrowed_from_gil_ref(&self).hasattr(attr_name) + self.as_borrowed().hasattr(attr_name) } /// Retrieves an attribute value. @@ -131,7 +131,7 @@ impl PyAny { where N: IntoPy>, { - Bound::borrowed_from_gil_ref(&self) + self.as_borrowed() .getattr(attr_name) .map(Bound::into_gil_ref) } @@ -208,7 +208,7 @@ impl PyAny { N: IntoPy>, V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).setattr(attr_name, value) + self.as_borrowed().setattr(attr_name, value) } /// Deletes an attribute. @@ -221,7 +221,7 @@ impl PyAny { where N: IntoPy>, { - Bound::borrowed_from_gil_ref(&self).delattr(attr_name) + self.as_borrowed().delattr(attr_name) } /// Returns an [`Ordering`] between `self` and `other`. @@ -274,7 +274,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).compare(other) + self.as_borrowed().compare(other) } /// Tests whether two Python objects obey a given [`CompareOp`]. @@ -315,7 +315,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self) + self.as_borrowed() .rich_compare(other, compare_op) .map(Bound::into_gil_ref) } @@ -327,7 +327,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).lt(other) + self.as_borrowed().lt(other) } /// Tests whether this object is less than or equal to another. @@ -337,7 +337,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).le(other) + self.as_borrowed().le(other) } /// Tests whether this object is equal to another. @@ -347,7 +347,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).eq(other) + self.as_borrowed().eq(other) } /// Tests whether this object is not equal to another. @@ -357,7 +357,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).ne(other) + self.as_borrowed().ne(other) } /// Tests whether this object is greater than another. @@ -367,7 +367,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).gt(other) + self.as_borrowed().gt(other) } /// Tests whether this object is greater than or equal to another. @@ -377,7 +377,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).ge(other) + self.as_borrowed().ge(other) } /// Determines whether this object appears callable. @@ -408,7 +408,7 @@ impl PyAny { /// /// [1]: https://docs.python.org/3/library/functions.html#callable pub fn is_callable(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_callable() + self.as_borrowed().is_callable() } /// Calls the object. @@ -446,7 +446,7 @@ impl PyAny { args: impl IntoPy>, kwargs: Option<&PyDict>, ) -> PyResult<&PyAny> { - Bound::borrowed_from_gil_ref(&self) + self.as_borrowed() .call(args, kwargs) .map(Bound::into_gil_ref) } @@ -472,9 +472,7 @@ impl PyAny { /// /// This is equivalent to the Python expression `help()`. pub fn call0(&self) -> PyResult<&PyAny> { - Bound::borrowed_from_gil_ref(&self) - .call0() - .map(Bound::into_gil_ref) + self.as_borrowed().call0().map(Bound::into_gil_ref) } /// Calls the object with only positional arguments. @@ -505,9 +503,7 @@ impl PyAny { /// # } /// ``` pub fn call1(&self, args: impl IntoPy>) -> PyResult<&PyAny> { - Bound::borrowed_from_gil_ref(&self) - .call1(args) - .map(Bound::into_gil_ref) + self.as_borrowed().call1(args).map(Bound::into_gil_ref) } /// Calls a method on the object. @@ -550,7 +546,7 @@ impl PyAny { N: IntoPy>, A: IntoPy>, { - Bound::borrowed_from_gil_ref(&self) + self.as_borrowed() .call_method(name, args, kwargs) .map(Bound::into_gil_ref) } @@ -590,7 +586,7 @@ impl PyAny { where N: IntoPy>, { - Bound::borrowed_from_gil_ref(&self) + self.as_borrowed() .call_method0(name) .map(Bound::into_gil_ref) } @@ -632,7 +628,7 @@ impl PyAny { N: IntoPy>, A: IntoPy>, { - Bound::borrowed_from_gil_ref(&self) + self.as_borrowed() .call_method1(name, args) .map(Bound::into_gil_ref) } @@ -649,7 +645,7 @@ impl PyAny { /// /// This applies truth value testing equivalent to the Python expression `bool(self)`. pub fn is_truthy(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).is_truthy() + self.as_borrowed().is_truthy() } /// Returns whether the object is considered to be None. @@ -657,7 +653,7 @@ impl PyAny { /// This is equivalent to the Python expression `self is None`. #[inline] pub fn is_none(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_none() + self.as_borrowed().is_none() } /// Returns whether the object is Ellipsis, e.g. `...`. @@ -665,14 +661,14 @@ impl PyAny { /// This is equivalent to the Python expression `self is ...`. #[deprecated(since = "0.20.0", note = "use `.is(py.Ellipsis())` instead")] pub fn is_ellipsis(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_ellipsis() + self.as_borrowed().is_ellipsis() } /// Returns true if the sequence or mapping has a length of 0. /// /// This is equivalent to the Python expression `len(self) == 0`. pub fn is_empty(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_borrowed().is_empty() } /// Gets an item from the collection. @@ -682,9 +678,7 @@ impl PyAny { where K: ToPyObject, { - Bound::borrowed_from_gil_ref(&self) - .get_item(key) - .map(Bound::into_gil_ref) + self.as_borrowed().get_item(key).map(Bound::into_gil_ref) } /// Sets a collection item value. @@ -695,7 +689,7 @@ impl PyAny { K: ToPyObject, V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).set_item(key, value) + self.as_borrowed().set_item(key, value) } /// Deletes an item from the collection. @@ -705,7 +699,7 @@ impl PyAny { where K: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).del_item(key) + self.as_borrowed().del_item(key) } /// Takes an object and returns an iterator for it. @@ -713,20 +707,18 @@ impl PyAny { /// This is typically a new iterator but if the argument is an iterator, /// this returns itself. pub fn iter(&self) -> PyResult<&PyIterator> { - Bound::borrowed_from_gil_ref(&self) - .iter() - .map(Bound::into_gil_ref) + self.as_borrowed().iter().map(Bound::into_gil_ref) } /// Returns the Python type object for this object's type. pub fn get_type(&self) -> &PyType { - Bound::borrowed_from_gil_ref(&self).get_type() + self.as_borrowed().get_type() } /// Returns the Python type pointer for this object. #[inline] pub fn get_type_ptr(&self) -> *mut ffi::PyTypeObject { - Bound::borrowed_from_gil_ref(&self).get_type_ptr() + self.as_borrowed().get_type_ptr() } /// Downcast this `PyAny` to a concrete Python type or pyclass. @@ -863,46 +855,42 @@ impl PyAny { /// Returns the reference count for the Python object. pub fn get_refcnt(&self) -> isize { - Bound::borrowed_from_gil_ref(&self).get_refcnt() + self.as_borrowed().get_refcnt() } /// Computes the "repr" representation of self. /// /// This is equivalent to the Python expression `repr(self)`. pub fn repr(&self) -> PyResult<&PyString> { - Bound::borrowed_from_gil_ref(&self) - .repr() - .map(Bound::into_gil_ref) + self.as_borrowed().repr().map(Bound::into_gil_ref) } /// Computes the "str" representation of self. /// /// This is equivalent to the Python expression `str(self)`. pub fn str(&self) -> PyResult<&PyString> { - Bound::borrowed_from_gil_ref(&self) - .str() - .map(Bound::into_gil_ref) + self.as_borrowed().str().map(Bound::into_gil_ref) } /// Retrieves the hash code of self. /// /// This is equivalent to the Python expression `hash(self)`. pub fn hash(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).hash() + self.as_borrowed().hash() } /// Returns the length of the sequence or mapping. /// /// This is equivalent to the Python expression `len(self)`. pub fn len(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).len() + self.as_borrowed().len() } /// Returns the list of attributes of this object. /// /// This is equivalent to the Python expression `dir(self)`. pub fn dir(&self) -> &PyList { - Bound::borrowed_from_gil_ref(&self).dir().into_gil_ref() + self.as_borrowed().dir().into_gil_ref() } /// Checks whether this object is an instance of type `ty`. @@ -910,7 +898,7 @@ impl PyAny { /// This is equivalent to the Python expression `isinstance(self, ty)`. #[inline] pub fn is_instance(&self, ty: &PyAny) -> PyResult { - Bound::borrowed_from_gil_ref(&self).is_instance(Bound::borrowed_from_gil_ref(&ty)) + self.as_borrowed().is_instance(&ty.as_borrowed()) } /// Checks whether this object is an instance of exactly type `ty` (not a subclass). @@ -918,7 +906,7 @@ impl PyAny { /// This is equivalent to the Python expression `type(self) is ty`. #[inline] pub fn is_exact_instance(&self, ty: &PyAny) -> bool { - Bound::borrowed_from_gil_ref(&self).is_exact_instance(Bound::borrowed_from_gil_ref(&ty)) + self.as_borrowed().is_exact_instance(&ty.as_borrowed()) } /// Checks whether this object is an instance of type `T`. @@ -927,7 +915,7 @@ impl PyAny { /// if the type `T` is known at compile time. #[inline] pub fn is_instance_of(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_instance_of::() + self.as_borrowed().is_instance_of::() } /// Checks whether this object is an instance of exactly type `T`. @@ -936,7 +924,7 @@ impl PyAny { /// if the type `T` is known at compile time. #[inline] pub fn is_exact_instance_of(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_exact_instance_of::() + self.as_borrowed().is_exact_instance_of::() } /// Determines if self contains `value`. @@ -946,7 +934,7 @@ impl PyAny { where V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).contains(value) + self.as_borrowed().contains(value) } /// Returns a GIL marker constrained to the lifetime of this type. @@ -985,9 +973,7 @@ impl PyAny { /// This is equivalent to the Python expression `super()` #[cfg(not(PyPy))] pub fn py_super(&self) -> PyResult<&PySuper> { - Bound::borrowed_from_gil_ref(&self) - .py_super() - .map(Bound::into_gil_ref) + self.as_borrowed().py_super().map(Bound::into_gil_ref) } } @@ -2193,7 +2179,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { #[cfg(not(PyPy))] fn py_super(&self) -> PyResult> { - PySuper::new_bound(Bound::borrowed_from_gil_ref(&self.get_type()), self) + PySuper::new_bound(&self.get_type().as_borrowed(), self) } } diff --git a/src/types/boolobject.rs b/src/types/boolobject.rs index 55896f877c5..5c246de380d 100644 --- a/src/types/boolobject.rs +++ b/src/types/boolobject.rs @@ -1,8 +1,8 @@ #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ - exceptions::PyTypeError, ffi, instance::Bound, FromPyObject, IntoPy, PyAny, PyObject, PyResult, - Python, ToPyObject, + exceptions::PyTypeError, ffi, instance::Bound, FromPyObject, IntoPy, PyAny, PyNativeType, + PyObject, PyResult, Python, ToPyObject, }; /// Represents a Python `bool`. @@ -21,7 +21,7 @@ impl PyBool { /// Gets whether this boolean is `true`. #[inline] pub fn is_true(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_true() + self.as_borrowed().is_true() } } diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index a90fec82273..f1b8050c066 100644 --- a/src/types/bytearray.rs +++ b/src/types/bytearray.rs @@ -1,6 +1,6 @@ use crate::err::{PyErr, PyResult}; use crate::instance::{Borrowed, Bound}; -use crate::{ffi, AsPyPointer, Py, PyAny, Python}; +use crate::{ffi, AsPyPointer, Py, PyAny, PyNativeType, Python}; use std::os::raw::c_char; use std::slice; @@ -75,12 +75,12 @@ impl PyByteArray { /// Gets the length of the bytearray. #[inline] pub fn len(&self) -> usize { - Bound::borrowed_from_gil_ref(&self).len() + self.as_borrowed().len() } /// Checks if the bytearray is empty. pub fn is_empty(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_borrowed().is_empty() } /// Gets the start of the buffer containing the contents of the bytearray. @@ -89,7 +89,7 @@ impl PyByteArray { /// /// See the safety requirements of [`PyByteArray::as_bytes`] and [`PyByteArray::as_bytes_mut`]. pub fn data(&self) -> *mut u8 { - Bound::borrowed_from_gil_ref(&self).data() + self.as_borrowed().data() } /// Extracts a slice of the `ByteArray`'s entire buffer. @@ -188,7 +188,7 @@ impl PyByteArray { /// } /// ``` pub unsafe fn as_bytes(&self) -> &[u8] { - Borrowed::from_gil_ref(self).as_bytes() + self.as_borrowed().as_bytes() } /// Extracts a mutable slice of the `ByteArray`'s entire buffer. @@ -200,7 +200,7 @@ impl PyByteArray { /// apply to this function as well. #[allow(clippy::mut_from_ref)] pub unsafe fn as_bytes_mut(&self) -> &mut [u8] { - Borrowed::from_gil_ref(self).as_bytes_mut() + self.as_borrowed().as_bytes_mut() } /// Copies the contents of the bytearray to a Rust vector. @@ -222,7 +222,7 @@ impl PyByteArray { /// # }); /// ``` pub fn to_vec(&self) -> Vec { - Bound::borrowed_from_gil_ref(&self).to_vec() + self.as_borrowed().to_vec() } /// Resizes the bytearray object to the new length `len`. @@ -230,7 +230,7 @@ impl PyByteArray { /// Note that this will invalidate any pointers obtained by [PyByteArray::data], as well as /// any (unsafe) slices obtained from [PyByteArray::as_bytes] and [PyByteArray::as_bytes_mut]. pub fn resize(&self, len: usize) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).resize(len) + self.as_borrowed().resize(len) } } diff --git a/src/types/bytes.rs b/src/types/bytes.rs index 4db098c6bb6..5a7b174ea0c 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -1,5 +1,5 @@ use crate::instance::{Borrowed, Bound}; -use crate::{ffi, FromPyObject, IntoPy, Py, PyAny, PyResult, Python, ToPyObject}; +use crate::{ffi, FromPyObject, IntoPy, Py, PyAny, PyNativeType, PyResult, Python, ToPyObject}; use std::borrow::Cow; use std::ops::Index; use std::os::raw::c_char; @@ -89,7 +89,7 @@ impl PyBytes { /// Gets the Python string as a byte slice. #[inline] pub fn as_bytes(&self) -> &[u8] { - Borrowed::from_gil_ref(self).as_bytes() + self.as_borrowed().as_bytes() } } diff --git a/src/types/datetime.rs b/src/types/datetime.rs index b2d0f6efa00..b671249c983 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -223,15 +223,15 @@ impl PyDate { impl PyDateAccess for PyDate { fn get_year(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_year() + self.as_borrowed().get_year() } fn get_month(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_month() + self.as_borrowed().get_month() } fn get_day(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_day() + self.as_borrowed().get_day() } } @@ -351,15 +351,15 @@ impl PyDateTime { impl PyDateAccess for PyDateTime { fn get_year(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_year() + self.as_borrowed().get_year() } fn get_month(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_month() + self.as_borrowed().get_month() } fn get_day(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_day() + self.as_borrowed().get_day() } } @@ -379,23 +379,23 @@ impl PyDateAccess for Bound<'_, PyDateTime> { impl PyTimeAccess for PyDateTime { fn get_hour(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_hour() + self.as_borrowed().get_hour() } fn get_minute(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_minute() + self.as_borrowed().get_minute() } fn get_second(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_second() + self.as_borrowed().get_second() } fn get_microsecond(&self) -> u32 { - Bound::borrowed_from_gil_ref(&self).get_microsecond() + self.as_borrowed().get_microsecond() } fn get_fold(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).get_fold() + self.as_borrowed().get_fold() } } @@ -423,7 +423,7 @@ impl PyTimeAccess for Bound<'_, PyDateTime> { impl<'py> PyTzInfoAccess<'py> for &'py PyDateTime { fn get_tzinfo_bound(&self) -> Option> { - Bound::borrowed_from_gil_ref(self).get_tzinfo_bound() + self.as_borrowed().get_tzinfo_bound() } } @@ -509,23 +509,23 @@ impl PyTime { impl PyTimeAccess for PyTime { fn get_hour(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_hour() + self.as_borrowed().get_hour() } fn get_minute(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_minute() + self.as_borrowed().get_minute() } fn get_second(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_second() + self.as_borrowed().get_second() } fn get_microsecond(&self) -> u32 { - Bound::borrowed_from_gil_ref(&self).get_microsecond() + self.as_borrowed().get_microsecond() } fn get_fold(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).get_fold() + self.as_borrowed().get_fold() } } @@ -553,7 +553,7 @@ impl PyTimeAccess for Bound<'_, PyTime> { impl<'py> PyTzInfoAccess<'py> for &'py PyTime { fn get_tzinfo_bound(&self) -> Option> { - Bound::borrowed_from_gil_ref(self).get_tzinfo_bound() + self.as_borrowed().get_tzinfo_bound() } } @@ -644,15 +644,15 @@ impl PyDelta { impl PyDeltaAccess for PyDelta { fn get_days(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_days() + self.as_borrowed().get_days() } fn get_seconds(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_seconds() + self.as_borrowed().get_seconds() } fn get_microseconds(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_microseconds() + self.as_borrowed().get_microseconds() } } diff --git a/src/types/dict.rs b/src/types/dict.rs index 89e0df96e63..80d2798a863 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -6,7 +6,7 @@ use crate::instance::{Borrowed, Bound}; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyList}; -use crate::{ffi, Python, ToPyObject}; +use crate::{ffi, PyNativeType, Python, ToPyObject}; /// Represents a Python `dict`. #[repr(transparent)] @@ -82,26 +82,24 @@ impl PyDict { /// /// This is equivalent to the Python expression `self.copy()`. pub fn copy(&self) -> PyResult<&PyDict> { - Bound::borrowed_from_gil_ref(&self) - .copy() - .map(Bound::into_gil_ref) + self.as_borrowed().copy().map(Bound::into_gil_ref) } /// Empties an existing dictionary of all key-value pairs. pub fn clear(&self) { - Bound::borrowed_from_gil_ref(&self).clear() + self.as_borrowed().clear() } /// Return the number of items in the dictionary. /// /// This is equivalent to the Python expression `len(self)`. pub fn len(&self) -> usize { - Bound::borrowed_from_gil_ref(&self).len() + self.as_borrowed().len() } /// Checks if the dict is empty, i.e. `len(self) == 0`. pub fn is_empty(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_borrowed().is_empty() } /// Determines if the dictionary contains the specified key. @@ -111,7 +109,7 @@ impl PyDict { where K: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).contains(key) + self.as_borrowed().contains(key) } /// Gets an item from the dictionary. @@ -160,7 +158,7 @@ impl PyDict { where K: ToPyObject, { - match Bound::borrowed_from_gil_ref(&self).get_item(key) { + match self.as_borrowed().get_item(key) { Ok(Some(item)) => Ok(Some(item.into_gil_ref())), Ok(None) => Ok(None), Err(e) => Err(e), @@ -188,7 +186,7 @@ impl PyDict { K: ToPyObject, V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).set_item(key, value) + self.as_borrowed().set_item(key, value) } /// Deletes an item. @@ -198,28 +196,28 @@ impl PyDict { where K: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).del_item(key) + self.as_borrowed().del_item(key) } /// Returns a list of dict keys. /// /// This is equivalent to the Python expression `list(dict.keys())`. pub fn keys(&self) -> &PyList { - Bound::borrowed_from_gil_ref(&self).keys().into_gil_ref() + self.as_borrowed().keys().into_gil_ref() } /// Returns a list of dict values. /// /// This is equivalent to the Python expression `list(dict.values())`. pub fn values(&self) -> &PyList { - Bound::borrowed_from_gil_ref(&self).values().into_gil_ref() + self.as_borrowed().values().into_gil_ref() } /// Returns a list of dict items. /// /// This is equivalent to the Python expression `list(dict.items())`. pub fn items(&self) -> &PyList { - Bound::borrowed_from_gil_ref(&self).items().into_gil_ref() + self.as_borrowed().items().into_gil_ref() } /// Returns an iterator of `(key, value)` pairs in this dictionary. @@ -230,7 +228,7 @@ impl PyDict { /// It is allowed to modify values as you iterate over the dictionary, but only /// so long as the set of keys does not change. pub fn iter(&self) -> PyDictIterator<'_> { - PyDictIterator(Bound::borrowed_from_gil_ref(&self).iter()) + PyDictIterator(self.as_borrowed().iter()) } /// Returns `self` cast as a `PyMapping`. @@ -243,7 +241,7 @@ impl PyDict { /// This is equivalent to the Python expression `self.update(other)`. If `other` is a `PyDict`, you may want /// to use `self.update(other.as_mapping())`, note: `PyDict::as_mapping` is a zero-cost conversion. pub fn update(&self, other: &PyMapping) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).update(Bound::borrowed_from_gil_ref(&other)) + self.as_borrowed().update(&other.as_borrowed()) } /// Add key/value pairs from another dictionary to this one only when they do not exist in this. @@ -255,7 +253,7 @@ impl PyDict { /// This method uses [`PyDict_Merge`](https://docs.python.org/3/c-api/dict.html#c.PyDict_Merge) internally, /// so should have the same performance as `update`. pub fn update_if_missing(&self, other: &PyMapping) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).update_if_missing(Bound::borrowed_from_gil_ref(&other)) + self.as_borrowed().update_if_missing(&other.as_borrowed()) } } diff --git a/src/types/float.rs b/src/types/float.rs index bb55d7ed5f5..b6dabdc48e8 100644 --- a/src/types/float.rs +++ b/src/types/float.rs @@ -29,7 +29,7 @@ impl PyFloat { /// Gets the value of this float. pub fn value(&self) -> c_double { - Bound::borrowed_from_gil_ref(&self).value() + self.as_borrowed().value() } } diff --git a/src/types/iterator.rs b/src/types/iterator.rs index 0e033232964..67866348f8c 100644 --- a/src/types/iterator.rs +++ b/src/types/iterator.rs @@ -35,7 +35,7 @@ impl PyIterator { /// /// Equivalent to Python's built-in `iter` function. pub fn from_object(obj: &PyAny) -> PyResult<&PyIterator> { - Self::from_object2(Bound::borrowed_from_gil_ref(&obj)).map(Bound::into_gil_ref) + Self::from_object2(&obj.as_borrowed()).map(Bound::into_gil_ref) } pub(crate) fn from_object2<'py>(obj: &Bound<'py, PyAny>) -> PyResult> { @@ -57,14 +57,14 @@ impl<'p> Iterator for &'p PyIterator { /// Further `next()` calls after an exception occurs are likely /// to repeatedly result in the same exception. fn next(&mut self) -> Option { - Borrowed::::from_gil_ref(self) + self.as_borrowed() .next() .map(|result| result.map(Bound::into_gil_ref)) } #[cfg(not(Py_LIMITED_API))] fn size_hint(&self) -> (usize, Option) { - Bound::borrowed_from_gil_ref(self).size_hint() + self.as_borrowed().size_hint() } } diff --git a/src/types/list.rs b/src/types/list.rs index 0e7fc952b00..cdc39349bfd 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -7,7 +7,7 @@ use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Borrowed; use crate::internal_tricks::get_ssize_index; use crate::types::{PySequence, PyTuple}; -use crate::{Bound, PyAny, PyObject, Python, ToPyObject}; +use crate::{Bound, PyAny, PyNativeType, PyObject, Python, ToPyObject}; use crate::types::any::PyAnyMethods; use crate::types::sequence::PySequenceMethods; @@ -98,12 +98,12 @@ impl PyList { /// Returns the length of the list. pub fn len(&self) -> usize { - Bound::borrowed_from_gil_ref(&self).len() + self.as_borrowed().len() } /// Checks if the list is empty. pub fn is_empty(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_borrowed().is_empty() } /// Returns `self` cast as a `PySequence`. @@ -122,9 +122,7 @@ impl PyList { /// }); /// ``` pub fn get_item(&self, index: usize) -> PyResult<&PyAny> { - Bound::borrowed_from_gil_ref(&self) - .get_item(index) - .map(Bound::into_gil_ref) + self.as_borrowed().get_item(index).map(Bound::into_gil_ref) } /// Gets the list item at the specified index. Undefined behavior on bad index. Use with caution. @@ -134,9 +132,7 @@ impl PyList { /// Caller must verify that the index is within the bounds of the list. #[cfg(not(Py_LIMITED_API))] pub unsafe fn get_item_unchecked(&self, index: usize) -> &PyAny { - Bound::borrowed_from_gil_ref(&self) - .get_item_unchecked(index) - .into_gil_ref() + self.as_borrowed().get_item_unchecked(index).into_gil_ref() } /// Takes the slice `self[low:high]` and returns it as a new list. @@ -144,9 +140,7 @@ impl PyList { /// Indices must be nonnegative, and out-of-range indices are clipped to /// `self.len()`. pub fn get_slice(&self, low: usize, high: usize) -> &PyList { - Bound::borrowed_from_gil_ref(&self) - .get_slice(low, high) - .into_gil_ref() + self.as_borrowed().get_slice(low, high).into_gil_ref() } /// Sets the item at the specified index. @@ -156,7 +150,7 @@ impl PyList { where I: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).set_item(index, item) + self.as_borrowed().set_item(index, item) } /// Deletes the `index`th element of self. @@ -164,7 +158,7 @@ impl PyList { /// This is equivalent to the Python statement `del self[i]`. #[inline] pub fn del_item(&self, index: usize) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).del_item(index) + self.as_borrowed().del_item(index) } /// Assigns the sequence `seq` to the slice of `self` from `low` to `high`. @@ -172,7 +166,7 @@ impl PyList { /// This is equivalent to the Python statement `self[low:high] = v`. #[inline] pub fn set_slice(&self, low: usize, high: usize, seq: &PyAny) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).set_slice(low, high, Bound::borrowed_from_gil_ref(&seq)) + self.as_borrowed().set_slice(low, high, &seq.as_borrowed()) } /// Deletes the slice from `low` to `high` from `self`. @@ -180,7 +174,7 @@ impl PyList { /// This is equivalent to the Python statement `del self[low:high]`. #[inline] pub fn del_slice(&self, low: usize, high: usize) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).del_slice(low, high) + self.as_borrowed().del_slice(low, high) } /// Appends an item to the list. @@ -188,7 +182,7 @@ impl PyList { where I: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).append(item) + self.as_borrowed().append(item) } /// Inserts an item at the specified index. @@ -198,7 +192,7 @@ impl PyList { where I: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).insert(index, item) + self.as_borrowed().insert(index, item) } /// Determines if self contains `value`. @@ -209,7 +203,7 @@ impl PyList { where V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).contains(value) + self.as_borrowed().contains(value) } /// Returns the first index `i` for which `self[i] == value`. @@ -220,31 +214,29 @@ impl PyList { where V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).index(value) + self.as_borrowed().index(value) } /// Returns an iterator over this list's items. pub fn iter(&self) -> PyListIterator<'_> { - PyListIterator(Bound::borrowed_from_gil_ref(&self).iter()) + PyListIterator(self.as_borrowed().iter()) } /// Sorts the list in-place. Equivalent to the Python expression `l.sort()`. pub fn sort(&self) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).sort() + self.as_borrowed().sort() } /// Reverses the list in-place. Equivalent to the Python expression `l.reverse()`. pub fn reverse(&self) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).reverse() + self.as_borrowed().reverse() } /// Return a new tuple containing the contents of the list; equivalent to the Python expression `tuple(list)`. /// /// This method is equivalent to `self.as_sequence().to_tuple()` and faster than `PyTuple::new(py, this_list)`. pub fn to_tuple(&self) -> &PyTuple { - Bound::borrowed_from_gil_ref(&self) - .to_tuple() - .into_gil_ref() + self.as_borrowed().to_tuple().into_gil_ref() } } diff --git a/src/types/mapping.rs b/src/types/mapping.rs index 239ade9b20c..4c9677cea8b 100644 --- a/src/types/mapping.rs +++ b/src/types/mapping.rs @@ -20,13 +20,13 @@ impl PyMapping { /// This is equivalent to the Python expression `len(self)`. #[inline] pub fn len(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).len() + self.as_borrowed().len() } /// Returns whether the mapping is empty. #[inline] pub fn is_empty(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_borrowed().is_empty() } /// Determines if the mapping contains the specified key. @@ -36,7 +36,7 @@ impl PyMapping { where K: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).contains(key) + self.as_borrowed().contains(key) } /// Gets the item in self with key `key`. @@ -49,9 +49,7 @@ impl PyMapping { where K: ToPyObject, { - Bound::borrowed_from_gil_ref(&self) - .get_item(key) - .map(Bound::into_gil_ref) + self.as_borrowed().get_item(key).map(Bound::into_gil_ref) } /// Sets the item in self with key `key`. @@ -63,7 +61,7 @@ impl PyMapping { K: ToPyObject, V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).set_item(key, value) + self.as_borrowed().set_item(key, value) } /// Deletes the item with key `key`. @@ -74,31 +72,25 @@ impl PyMapping { where K: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).del_item(key) + self.as_borrowed().del_item(key) } /// Returns a sequence containing all keys in the mapping. #[inline] pub fn keys(&self) -> PyResult<&PySequence> { - Bound::borrowed_from_gil_ref(&self) - .keys() - .map(Bound::into_gil_ref) + self.as_borrowed().keys().map(Bound::into_gil_ref) } /// Returns a sequence containing all values in the mapping. #[inline] pub fn values(&self) -> PyResult<&PySequence> { - Bound::borrowed_from_gil_ref(&self) - .values() - .map(Bound::into_gil_ref) + self.as_borrowed().values().map(Bound::into_gil_ref) } /// Returns a sequence of tuples of all (key, value) pairs in the mapping. #[inline] pub fn items(&self) -> PyResult<&PySequence> { - Bound::borrowed_from_gil_ref(&self) - .items() - .map(Bound::into_gil_ref) + self.as_borrowed().items().map(Bound::into_gil_ref) } /// Register a pyclass as a subclass of `collections.abc.Mapping` (from the Python standard @@ -257,10 +249,7 @@ impl PyTypeCheck for PyMapping { || get_mapping_abc(object.py()) .and_then(|abc| object.is_instance(abc)) .unwrap_or_else(|err| { - err.write_unraisable_bound( - object.py(), - Some(Bound::borrowed_from_gil_ref(&object)), - ); + err.write_unraisable_bound(object.py(), Some(&object.as_borrowed())); false }) } diff --git a/src/types/mod.rs b/src/types/mod.rs index f153c4d92ec..41fb5b0adc8 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -105,9 +105,10 @@ macro_rules! pyobject_native_type_base( fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> { + use $crate::PyNativeType; match self.str() { ::std::result::Result::Ok(s) => return f.write_str(&s.to_string_lossy()), - ::std::result::Result::Err(err) => err.write_unraisable_bound(self.py(), ::std::option::Option::Some($crate::Bound::borrowed_from_gil_ref(&self))), + ::std::result::Result::Err(err) => err.write_unraisable_bound(self.py(), ::std::option::Option::Some(&self.as_borrowed())), } match self.get_type().name() { diff --git a/src/types/pysuper.rs b/src/types/pysuper.rs index d14670987b5..23f445f76b3 100644 --- a/src/types/pysuper.rs +++ b/src/types/pysuper.rs @@ -1,7 +1,7 @@ use crate::instance::Bound; use crate::types::any::PyAnyMethods; use crate::types::PyType; -use crate::{ffi, PyTypeInfo}; +use crate::{ffi, PyNativeType, PyTypeInfo}; use crate::{PyAny, PyResult}; /// Represents a Python `super` object. @@ -22,11 +22,7 @@ impl PySuper { note = "`PySuper::new` will be replaced by `PySuper::new_bound` in a future PyO3 version" )] pub fn new<'py>(ty: &'py PyType, obj: &'py PyAny) -> PyResult<&'py PySuper> { - Self::new_bound( - Bound::borrowed_from_gil_ref(&ty), - Bound::borrowed_from_gil_ref(&obj), - ) - .map(Bound::into_gil_ref) + Self::new_bound(&ty.as_borrowed(), &obj.as_borrowed()).map(Bound::into_gil_ref) } /// Constructs a new super object. More read about super object: [docs](https://docs.python.org/3/library/functions.html#super) @@ -73,7 +69,8 @@ impl PySuper { ty: &Bound<'py, PyType>, obj: &Bound<'py, PyAny>, ) -> PyResult> { - Bound::borrowed_from_gil_ref(&PySuper::type_object(ty.py())) + PySuper::type_object(ty.py()) + .as_borrowed() .call1((ty, obj)) .map(|any| { // Safety: super() always returns instance of super diff --git a/src/types/sequence.rs b/src/types/sequence.rs index 9b497ded4f7..f4eae4d05a9 100644 --- a/src/types/sequence.rs +++ b/src/types/sequence.rs @@ -23,13 +23,13 @@ impl PySequence { /// This is equivalent to the Python expression `len(self)`. #[inline] pub fn len(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).len() + self.as_borrowed().len() } /// Returns whether the sequence is empty. #[inline] pub fn is_empty(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_borrowed().is_empty() } /// Returns the concatenation of `self` and `other`. @@ -37,8 +37,8 @@ impl PySequence { /// This is equivalent to the Python expression `self + other`. #[inline] pub fn concat(&self, other: &PySequence) -> PyResult<&PySequence> { - Bound::borrowed_from_gil_ref(&self) - .concat(Bound::borrowed_from_gil_ref(&other)) + self.as_borrowed() + .concat(&other.as_borrowed()) .map(Bound::into_gil_ref) } @@ -47,9 +47,7 @@ impl PySequence { /// This is equivalent to the Python expression `self * count`. #[inline] pub fn repeat(&self, count: usize) -> PyResult<&PySequence> { - Bound::borrowed_from_gil_ref(&self) - .repeat(count) - .map(Bound::into_gil_ref) + self.as_borrowed().repeat(count).map(Bound::into_gil_ref) } /// Concatenates `self` and `other`, in place if possible. @@ -61,8 +59,8 @@ impl PySequence { /// possible, but create and return a new object if not. #[inline] pub fn in_place_concat(&self, other: &PySequence) -> PyResult<&PySequence> { - Bound::borrowed_from_gil_ref(&self) - .in_place_concat(Bound::borrowed_from_gil_ref(&other)) + self.as_borrowed() + .in_place_concat(&other.as_borrowed()) .map(Bound::into_gil_ref) } @@ -75,7 +73,7 @@ impl PySequence { /// possible, but create and return a new object if not. #[inline] pub fn in_place_repeat(&self, count: usize) -> PyResult<&PySequence> { - Bound::borrowed_from_gil_ref(&self) + self.as_borrowed() .in_place_repeat(count) .map(Bound::into_gil_ref) } @@ -85,9 +83,7 @@ impl PySequence { /// This is equivalent to the Python expression `self[index]` without support of negative indices. #[inline] pub fn get_item(&self, index: usize) -> PyResult<&PyAny> { - Bound::borrowed_from_gil_ref(&self) - .get_item(index) - .map(|py2| py2.into_gil_ref()) + self.as_borrowed().get_item(index).map(Bound::into_gil_ref) } /// Returns the slice of sequence object between `begin` and `end`. @@ -95,7 +91,7 @@ impl PySequence { /// This is equivalent to the Python expression `self[begin:end]`. #[inline] pub fn get_slice(&self, begin: usize, end: usize) -> PyResult<&PySequence> { - Bound::borrowed_from_gil_ref(&self) + self.as_borrowed() .get_slice(begin, end) .map(Bound::into_gil_ref) } @@ -108,7 +104,7 @@ impl PySequence { where I: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).set_item(i, item) + self.as_borrowed().set_item(i, item) } /// Deletes the `i`th element of self. @@ -116,7 +112,7 @@ impl PySequence { /// This is equivalent to the Python statement `del self[i]`. #[inline] pub fn del_item(&self, i: usize) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).del_item(i) + self.as_borrowed().del_item(i) } /// Assigns the sequence `v` to the slice of `self` from `i1` to `i2`. @@ -124,7 +120,7 @@ impl PySequence { /// This is equivalent to the Python statement `self[i1:i2] = v`. #[inline] pub fn set_slice(&self, i1: usize, i2: usize, v: &PyAny) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).set_slice(i1, i2, Bound::borrowed_from_gil_ref(&v)) + self.as_borrowed().set_slice(i1, i2, &v.as_borrowed()) } /// Deletes the slice from `i1` to `i2` from `self`. @@ -132,7 +128,7 @@ impl PySequence { /// This is equivalent to the Python statement `del self[i1:i2]`. #[inline] pub fn del_slice(&self, i1: usize, i2: usize) -> PyResult<()> { - Bound::borrowed_from_gil_ref(&self).del_slice(i1, i2) + self.as_borrowed().del_slice(i1, i2) } /// Returns the number of occurrences of `value` in self, that is, return the @@ -143,7 +139,7 @@ impl PySequence { where V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).count(value) + self.as_borrowed().count(value) } /// Determines if self contains `value`. @@ -154,7 +150,7 @@ impl PySequence { where V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).contains(value) + self.as_borrowed().contains(value) } /// Returns the first index `i` for which `self[i] == value`. @@ -165,23 +161,19 @@ impl PySequence { where V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).index(value) + self.as_borrowed().index(value) } /// Returns a fresh list based on the Sequence. #[inline] pub fn to_list(&self) -> PyResult<&PyList> { - Bound::borrowed_from_gil_ref(&self) - .to_list() - .map(|py2| py2.into_gil_ref()) + self.as_borrowed().to_list().map(Bound::into_gil_ref) } /// Returns a fresh tuple based on the Sequence. #[inline] pub fn to_tuple(&self) -> PyResult<&PyTuple> { - Bound::borrowed_from_gil_ref(&self) - .to_tuple() - .map(|py2| py2.into_gil_ref()) + self.as_borrowed().to_tuple().map(Bound::into_gil_ref) } /// Register a pyclass as a subclass of `collections.abc.Sequence` (from the Python standard @@ -541,10 +533,7 @@ impl PyTypeCheck for PySequence { || get_sequence_abc(object.py()) .and_then(|abc| object.is_instance(abc)) .unwrap_or_else(|err| { - err.write_unraisable_bound( - object.py(), - Some(Bound::borrowed_from_gil_ref(&object)), - ); + err.write_unraisable_bound(object.py(), Some(&object.as_borrowed())); false }) } diff --git a/src/types/string.rs b/src/types/string.rs index 03d41963f1e..111f3112f26 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -5,7 +5,7 @@ use crate::instance::Borrowed; use crate::types::any::PyAnyMethods; use crate::types::bytes::PyBytesMethods; use crate::types::PyBytes; -use crate::{ffi, Bound, IntoPy, Py, PyAny, PyResult, Python}; +use crate::{ffi, Bound, IntoPy, Py, PyAny, PyNativeType, PyResult, Python}; use std::borrow::Cow; use std::os::raw::c_char; use std::str; @@ -184,7 +184,7 @@ impl PyString { pub fn to_str(&self) -> PyResult<&str> { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] { - Borrowed::from_gil_ref(self).to_str() + self.as_borrowed().to_str() } #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] @@ -202,7 +202,7 @@ impl PyString { /// Returns a `UnicodeEncodeError` if the input is not valid unicode /// (containing unpaired surrogates). pub fn to_cow(&self) -> PyResult> { - Borrowed::from_gil_ref(self).to_cow() + self.as_borrowed().to_cow() } /// Converts the `PyString` into a Rust string. @@ -210,7 +210,7 @@ impl PyString { /// Unpaired surrogates invalid UTF-8 sequences are /// replaced with `U+FFFD REPLACEMENT CHARACTER`. pub fn to_string_lossy(&self) -> Cow<'_, str> { - Borrowed::from_gil_ref(self).to_string_lossy() + self.as_borrowed().to_string_lossy() } /// Obtains the raw data backing the Python string. @@ -229,7 +229,7 @@ impl PyString { /// expected on the targets where you plan to distribute your software. #[cfg(not(Py_LIMITED_API))] pub unsafe fn data(&self) -> PyResult> { - Borrowed::from_gil_ref(self).data() + self.as_borrowed().data() } } From d36ad8f61fdb999b6cc21c9f8fa0e4cfb96db5d6 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sun, 24 Dec 2023 13:48:13 +0000 Subject: [PATCH 2/2] introduce `Bound::as_borrowed` --- src/instance.rs | 15 ++++++++++----- src/types/bytearray.rs | 6 +++--- src/types/bytes.rs | 2 +- src/types/string.rs | 8 ++++---- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/instance.rs b/src/instance.rs index 90e672c4fa5..e857efc9889 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -197,6 +197,15 @@ impl<'py, T> Bound<'py, T> { self.into_non_null().as_ptr() } + /// Casts this `Bound` to a `Borrowed` smart pointer. + pub fn as_borrowed<'a>(&'a self) -> Borrowed<'a, 'py, T> { + Borrowed( + unsafe { NonNull::new_unchecked(self.as_ptr()) }, + PhantomData, + self.py(), + ) + } + /// Casts this `Bound` as the corresponding "GIL Ref" type. /// /// This is a helper to be used for migration from the deprecated "GIL Refs" API. @@ -300,11 +309,7 @@ impl<'a, 'py> Borrowed<'a, 'py, PyAny> { impl<'a, 'py, T> From<&'a Bound<'py, T>> for Borrowed<'a, 'py, T> { /// Create borrow on a Bound fn from(instance: &'a Bound<'py, T>) -> Self { - Self( - unsafe { NonNull::new_unchecked(instance.as_ptr()) }, - PhantomData, - instance.py(), - ) + instance.as_borrowed() } } diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index f1b8050c066..2514e987d4d 100644 --- a/src/types/bytearray.rs +++ b/src/types/bytearray.rs @@ -400,16 +400,16 @@ impl<'py> PyByteArrayMethods<'py> for Bound<'py, PyByteArray> { } fn data(&self) -> *mut u8 { - Borrowed::from(self).data() + self.as_borrowed().data() } unsafe fn as_bytes(&self) -> &[u8] { - Borrowed::from(self).as_bytes() + self.as_borrowed().as_bytes() } #[allow(clippy::mut_from_ref)] unsafe fn as_bytes_mut(&self) -> &mut [u8] { - Borrowed::from(self).as_bytes_mut() + self.as_borrowed().as_bytes_mut() } fn to_vec(&self) -> Vec { diff --git a/src/types/bytes.rs b/src/types/bytes.rs index 5a7b174ea0c..d9d22dbb173 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -107,7 +107,7 @@ pub trait PyBytesMethods<'py> { impl<'py> PyBytesMethods<'py> for Bound<'py, PyBytes> { #[inline] fn as_bytes(&self) -> &[u8] { - Borrowed::from(self).as_bytes() + self.as_borrowed().as_bytes() } } diff --git a/src/types/string.rs b/src/types/string.rs index 111f3112f26..65f5a3922b9 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -280,20 +280,20 @@ pub trait PyStringMethods<'py> { impl<'py> PyStringMethods<'py> for Bound<'py, PyString> { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] fn to_str(&self) -> PyResult<&str> { - Borrowed::from(self).to_str() + self.as_borrowed().to_str() } fn to_cow(&self) -> PyResult> { - Borrowed::from(self).to_cow() + self.as_borrowed().to_cow() } fn to_string_lossy(&self) -> Cow<'_, str> { - Borrowed::from(self).to_string_lossy() + self.as_borrowed().to_string_lossy() } #[cfg(not(Py_LIMITED_API))] unsafe fn data(&self) -> PyResult> { - Borrowed::from(self).data() + self.as_borrowed().data() } }