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/err/mod.rs b/src/err/mod.rs index 00ba111f8c5..a4160593441 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; @@ -811,7 +811,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_bound(), &self.to) } } diff --git a/src/instance.rs b/src/instance.rs index 8406e86abbe..98357acce84 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -27,6 +27,16 @@ pub unsafe trait PyNativeType: Sized { /// The form of this which is stored inside a `Py` smart pointer. type AsRefSource: HasPyGilRef; + /// Cast `&self` to a `Bound` smart pointer. + /// + /// This is available as a migration tool to adjust code from the deprecated "GIL Refs" + /// API to the `Bound` smart pointer API. + fn as_bound<'a, 'py>(self: &'a &'py Self) -> &'a Bound<'py, Self::AsRefSource> { + // Safety: &'py Self is expected to be a Python pointer, + // so &'a &'py Self has the same layout as &'a Bound<'py, T> + unsafe { std::mem::transmute(self) } + } + /// Returns a GIL marker constrained to the lifetime of this type. #[inline] fn py(&self) -> Python<'_> { @@ -172,18 +182,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) } - } - /// Internal helper to get to pool references for backwards compatibility #[doc(hidden)] // public and doc(hidden) to use in examples and tests for now pub fn as_gil_ref(&'py self) -> &'py T::AsRefTarget @@ -1351,7 +1349,7 @@ where { /// Extracts `Self` from the source `PyObject`. fn extract(ob: &'a PyAny) -> PyResult { - Bound::borrowed_from_gil_ref(&ob) + ob.as_bound() .downcast() .map(Clone::clone) .map_err(Into::into) @@ -1470,7 +1468,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() { @@ -1597,8 +1595,7 @@ 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_bound().clone(); 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 2e8a518fad4..96d6f4f344f 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_bound().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_bound().hasattr(attr_name) } /// Retrieves an attribute value. @@ -131,9 +131,7 @@ impl PyAny { where N: IntoPy>, { - Bound::borrowed_from_gil_ref(&self) - .getattr(attr_name) - .map(Bound::into_gil_ref) + self.as_bound().getattr(attr_name).map(Bound::into_gil_ref) } /// Retrieve an attribute value, skipping the instance dictionary during the lookup but still @@ -208,7 +206,7 @@ impl PyAny { N: IntoPy>, V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).setattr(attr_name, value) + self.as_bound().setattr(attr_name, value) } /// Deletes an attribute. @@ -221,7 +219,7 @@ impl PyAny { where N: IntoPy>, { - Bound::borrowed_from_gil_ref(&self).delattr(attr_name) + self.as_bound().delattr(attr_name) } /// Returns an [`Ordering`] between `self` and `other`. @@ -274,7 +272,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).compare(other) + self.as_bound().compare(other) } /// Tests whether two Python objects obey a given [`CompareOp`]. @@ -315,7 +313,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self) + self.as_bound() .rich_compare(other, compare_op) .map(Bound::into_gil_ref) } @@ -327,7 +325,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).lt(other) + self.as_bound().lt(other) } /// Tests whether this object is less than or equal to another. @@ -337,7 +335,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).le(other) + self.as_bound().le(other) } /// Tests whether this object is equal to another. @@ -347,7 +345,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).eq(other) + self.as_bound().eq(other) } /// Tests whether this object is not equal to another. @@ -357,7 +355,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).ne(other) + self.as_bound().ne(other) } /// Tests whether this object is greater than another. @@ -367,7 +365,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).gt(other) + self.as_bound().gt(other) } /// Tests whether this object is greater than or equal to another. @@ -377,7 +375,7 @@ impl PyAny { where O: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).ge(other) + self.as_bound().ge(other) } /// Determines whether this object appears callable. @@ -408,7 +406,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_bound().is_callable() } /// Calls the object. @@ -446,9 +444,7 @@ impl PyAny { args: impl IntoPy>, kwargs: Option<&PyDict>, ) -> PyResult<&PyAny> { - Bound::borrowed_from_gil_ref(&self) - .call(args, kwargs) - .map(Bound::into_gil_ref) + self.as_bound().call(args, kwargs).map(Bound::into_gil_ref) } /// Calls the object without arguments. @@ -472,9 +468,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_bound().call0().map(Bound::into_gil_ref) } /// Calls the object with only positional arguments. @@ -505,9 +499,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_bound().call1(args).map(Bound::into_gil_ref) } /// Calls a method on the object. @@ -550,7 +542,7 @@ impl PyAny { N: IntoPy>, A: IntoPy>, { - Bound::borrowed_from_gil_ref(&self) + self.as_bound() .call_method(name, args, kwargs) .map(Bound::into_gil_ref) } @@ -590,9 +582,7 @@ impl PyAny { where N: IntoPy>, { - Bound::borrowed_from_gil_ref(&self) - .call_method0(name) - .map(Bound::into_gil_ref) + self.as_bound().call_method0(name).map(Bound::into_gil_ref) } /// Calls a method on the object with only positional arguments. @@ -632,7 +622,7 @@ impl PyAny { N: IntoPy>, A: IntoPy>, { - Bound::borrowed_from_gil_ref(&self) + self.as_bound() .call_method1(name, args) .map(Bound::into_gil_ref) } @@ -649,7 +639,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_bound().is_truthy() } /// Returns whether the object is considered to be None. @@ -657,7 +647,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_bound().is_none() } /// Returns whether the object is Ellipsis, e.g. `...`. @@ -665,14 +655,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_bound().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_bound().is_empty() } /// Gets an item from the collection. @@ -682,9 +672,7 @@ impl PyAny { where K: ToPyObject, { - Bound::borrowed_from_gil_ref(&self) - .get_item(key) - .map(Bound::into_gil_ref) + self.as_bound().get_item(key).map(Bound::into_gil_ref) } /// Sets a collection item value. @@ -695,7 +683,7 @@ impl PyAny { K: ToPyObject, V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).set_item(key, value) + self.as_bound().set_item(key, value) } /// Deletes an item from the collection. @@ -705,7 +693,7 @@ impl PyAny { where K: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).del_item(key) + self.as_bound().del_item(key) } /// Takes an object and returns an iterator for it. @@ -713,20 +701,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_bound().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_bound().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_bound().get_type_ptr() } /// Downcast this `PyAny` to a concrete Python type or pyclass. @@ -863,46 +849,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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().dir().into_gil_ref() } /// Checks whether this object is an instance of type `ty`. @@ -910,7 +892,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_bound().is_instance(ty.as_bound()) } /// Checks whether this object is an instance of exactly type `ty` (not a subclass). @@ -918,7 +900,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_bound().is_exact_instance(ty.as_bound()) } /// Checks whether this object is an instance of type `T`. @@ -927,7 +909,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_bound().is_instance_of::() } /// Checks whether this object is an instance of exactly type `T`. @@ -936,7 +918,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_bound().is_exact_instance_of::() } /// Determines if self contains `value`. @@ -946,7 +928,7 @@ impl PyAny { where V: ToPyObject, { - Bound::borrowed_from_gil_ref(&self).contains(value) + self.as_bound().contains(value) } /// Returns a GIL marker constrained to the lifetime of this type. @@ -985,9 +967,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_bound().py_super().map(Bound::into_gil_ref) } } @@ -2193,7 +2173,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { #[cfg(not(PyPy))] fn py_super(&self) -> PyResult> { - PySuper::new2(Bound::borrowed_from_gil_ref(&self.get_type()), self) + PySuper::new2(self.get_type().as_bound(), self) } } diff --git a/src/types/boolobject.rs b/src/types/boolobject.rs index 55896f877c5..6508f7015c8 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_bound().is_true() } } diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index a90fec82273..3ea3a0fe6f8 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_bound().len() } /// Checks if the bytearray is empty. pub fn is_empty(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_bound().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_bound().data() } /// Extracts a slice of the `ByteArray`'s entire buffer. @@ -222,7 +222,7 @@ impl PyByteArray { /// # }); /// ``` pub fn to_vec(&self) -> Vec { - Bound::borrowed_from_gil_ref(&self).to_vec() + self.as_bound().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_bound().resize(len) } } diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 94802fe14ef..edd4e8ab4ab 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -214,15 +214,15 @@ impl PyDate { impl PyDateAccess for PyDate { fn get_year(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_year() + self.as_bound().get_year() } fn get_month(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_month() + self.as_bound().get_month() } fn get_day(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_day() + self.as_bound().get_day() } } @@ -342,15 +342,15 @@ impl PyDateTime { impl PyDateAccess for PyDateTime { fn get_year(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_year() + self.as_bound().get_year() } fn get_month(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_month() + self.as_bound().get_month() } fn get_day(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_day() + self.as_bound().get_day() } } @@ -370,23 +370,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_bound().get_hour() } fn get_minute(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_minute() + self.as_bound().get_minute() } fn get_second(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_second() + self.as_bound().get_second() } fn get_microsecond(&self) -> u32 { - Bound::borrowed_from_gil_ref(&self).get_microsecond() + self.as_bound().get_microsecond() } fn get_fold(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).get_fold() + self.as_bound().get_fold() } } @@ -414,7 +414,7 @@ impl PyTimeAccess for Bound<'_, PyDateTime> { impl<'py> PyTzInfoAccess<'py> for &'py PyDateTime { fn get_tzinfo(&self) -> Option> { - Bound::borrowed_from_gil_ref(self).get_tzinfo() + self.as_bound().get_tzinfo() } } @@ -500,23 +500,23 @@ impl PyTime { impl PyTimeAccess for PyTime { fn get_hour(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_hour() + self.as_bound().get_hour() } fn get_minute(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_minute() + self.as_bound().get_minute() } fn get_second(&self) -> u8 { - Bound::borrowed_from_gil_ref(&self).get_second() + self.as_bound().get_second() } fn get_microsecond(&self) -> u32 { - Bound::borrowed_from_gil_ref(&self).get_microsecond() + self.as_bound().get_microsecond() } fn get_fold(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).get_fold() + self.as_bound().get_fold() } } @@ -544,7 +544,7 @@ impl PyTimeAccess for Bound<'_, PyTime> { impl<'py> PyTzInfoAccess<'py> for &'py PyTime { fn get_tzinfo(&self) -> Option> { - Bound::borrowed_from_gil_ref(self).get_tzinfo() + self.as_bound().get_tzinfo() } } @@ -635,15 +635,15 @@ impl PyDelta { impl PyDeltaAccess for PyDelta { fn get_days(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_days() + self.as_bound().get_days() } fn get_seconds(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_seconds() + self.as_bound().get_seconds() } fn get_microseconds(&self) -> i32 { - Bound::borrowed_from_gil_ref(&self).get_microseconds() + self.as_bound().get_microseconds() } } diff --git a/src/types/dict.rs b/src/types/dict.rs index 89e0df96e63..db1959ca05e 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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().update(other.as_bound()) } /// 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_bound().update_if_missing(other.as_bound()) } } diff --git a/src/types/float.rs b/src/types/float.rs index bb55d7ed5f5..e6a3abc19c2 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_bound().value() } } diff --git a/src/types/iterator.rs b/src/types/iterator.rs index bf392398eb9..0a2fb437aae 100644 --- a/src/types/iterator.rs +++ b/src/types/iterator.rs @@ -34,7 +34,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_bound()).map(Bound::into_gil_ref) } pub(crate) fn from_object2<'py>(obj: &Bound<'py, PyAny>) -> PyResult> { diff --git a/src/types/list.rs b/src/types/list.rs index 0e7fc952b00..c0190b7bba4 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_bound().len() } /// Checks if the list is empty. pub fn is_empty(&self) -> bool { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().set_slice(low, high, seq.as_bound()) } /// 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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().to_tuple().into_gil_ref() } } diff --git a/src/types/mapping.rs b/src/types/mapping.rs index 4eae0cec7c5..5d364b190d5 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_bound().len() } /// Returns whether the mapping is empty. #[inline] pub fn is_empty(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().items().map(Bound::into_gil_ref) } /// Register a pyclass as a subclass of `collections.abc.Mapping` (from the Python standard diff --git a/src/types/pysuper.rs b/src/types/pysuper.rs index 5cf05a36a4d..697e04deec1 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. @@ -57,18 +57,15 @@ impl PySuper { /// } /// ``` pub fn new<'py>(ty: &'py PyType, obj: &'py PyAny) -> PyResult<&'py PySuper> { - Self::new2( - Bound::borrowed_from_gil_ref(&ty), - Bound::borrowed_from_gil_ref(&obj), - ) - .map(Bound::into_gil_ref) + Self::new2(ty.as_bound(), obj.as_bound()).map(Bound::into_gil_ref) } pub(crate) fn new2<'py>( 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_bound() .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 714288bd203..07b96dbab10 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_bound().len() } /// Returns whether the sequence is empty. #[inline] pub fn is_empty(&self) -> PyResult { - Bound::borrowed_from_gil_ref(&self).is_empty() + self.as_bound().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_bound() + .concat(other.as_bound()) .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_bound().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_bound() + .in_place_concat(other.as_bound()) .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_bound() .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_bound().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_bound() .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_bound().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_bound().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_bound().set_slice(i1, i2, v.as_bound()) } /// 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_bound().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_bound().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_bound().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_bound().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_bound().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_bound().to_tuple().map(Bound::into_gil_ref) } /// Register a pyclass as a subclass of `collections.abc.Sequence` (from the Python standard