diff --git a/src/coroutine.rs b/src/coroutine.rs index 7dd73cbb..415bbc88 100644 --- a/src/coroutine.rs +++ b/src/coroutine.rs @@ -15,7 +15,7 @@ use crate::{ exceptions::{PyAttributeError, PyRuntimeError, PyStopIteration}, panic::PanicException, types::{PyIterator, PyString}, - IntoPy, Py, PyAny, PyErr, PyObject, PyResult, Python, + IntoPy, Py, PyAny, PyErr, PyNativeType, PyObject, PyResult, Python, }; pub(crate) mod cancel; @@ -107,7 +107,10 @@ impl Coroutine { if let Some(future) = self.waker.as_ref().unwrap().initialize_future(py)? { // `asyncio.Future` must be awaited; fortunately, it implements `__iter__ = __await__` // and will yield itself if its result has not been set in polling above - if let Some(future) = PyIterator::from_object(future).unwrap().next() { + if let Some(future) = PyIterator::from_bound_object(&future.as_borrowed()) + .unwrap() + .next() + { // future has not been leaked into Python for now, and Rust code can only call // `set_result(None)` in `Wake` implementation, so it's safe to unwrap return Ok(future.unwrap().into()); diff --git a/src/types/any.rs b/src/types/any.rs index edc74879..ffc98e9b 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -2018,7 +2018,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { } fn iter(&self) -> PyResult> { - PyIterator::from_object2(self) + PyIterator::from_bound_object(self) } fn get_type(&self) -> &'py PyType { diff --git a/src/types/frozenset.rs b/src/types/frozenset.rs index 1bcdce4c..ff0be7b5 100644 --- a/src/types/frozenset.rs +++ b/src/types/frozenset.rs @@ -209,7 +209,7 @@ mod impl_ { impl<'py> BoundFrozenSetIterator<'py> { pub(super) fn new(frozenset: Bound<'py, PyFrozenSet>) -> Self { Self { - it: PyIterator::from_object2(&frozenset).unwrap(), + it: PyIterator::from_bound_object(&frozenset).unwrap(), } } } diff --git a/src/types/iterator.rs b/src/types/iterator.rs index 67866348..e2703286 100644 --- a/src/types/iterator.rs +++ b/src/types/iterator.rs @@ -31,14 +31,23 @@ pyobject_native_type_named!(PyIterator); pyobject_native_type_extract!(PyIterator); impl PyIterator { - /// Constructs a `PyIterator` from a Python iterable object. - /// - /// Equivalent to Python's built-in `iter` function. + /// Deprecated form of `PyIterator::from_bound_object`. + #[cfg_attr( + not(feature = "gil-refs"), + deprecated( + since = "0.21.0", + note = "`PyIterator::from_object` will be replaced by `PyIterator::from_bound_object` in a future PyO3 version" + ) + )] pub fn from_object(obj: &PyAny) -> PyResult<&PyIterator> { - Self::from_object2(&obj.as_borrowed()).map(Bound::into_gil_ref) + Self::from_bound_object(&obj.as_borrowed()).map(Bound::into_gil_ref) } - pub(crate) fn from_object2<'py>(obj: &Bound<'py, PyAny>) -> PyResult> { + /// Builds an iterator for an iterable Python object; the equivalent of calling `iter(obj)` in Python. + /// + /// Usually it is more convenient to write [`obj.iter()`][crate::types::any::PyAnyMethods::iter], + /// which is a more concise way of calling this function. + pub fn from_bound_object<'py>(obj: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyObject_GetIter(obj.as_ptr()) .assume_owned_or_err(obj.py()) @@ -135,6 +144,7 @@ impl<'v> crate::PyTryFrom<'v> for PyIterator { } #[cfg(test)] +#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] mod tests { use super::PyIterator; use crate::exceptions::PyTypeError; diff --git a/src/types/set.rs b/src/types/set.rs index be65500b..d59a9e3f 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -289,7 +289,7 @@ mod impl_ { impl<'py> BoundSetIterator<'py> { pub(super) fn new(set: Bound<'py, PySet>) -> Self { Self { - it: PyIterator::from_object2(&set).unwrap(), + it: PyIterator::from_bound_object(&set).unwrap(), } } }