introduce `PyIterator::from_bound_object`

This commit is contained in:
David Hewitt 2023-12-24 14:01:00 +00:00
parent 6776b90e15
commit 783e98b1a8
5 changed files with 23 additions and 10 deletions

View File

@ -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());

View File

@ -2018,7 +2018,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
}
fn iter(&self) -> PyResult<Bound<'py, PyIterator>> {
PyIterator::from_object2(self)
PyIterator::from_bound_object(self)
}
fn get_type(&self) -> &'py PyType {

View File

@ -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(),
}
}
}

View File

@ -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<Bound<'py, PyIterator>> {
/// 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<Bound<'py, PyIterator>> {
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;

View File

@ -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(),
}
}
}