Skip to content

Commit

Permalink
introduce PyIterator::from_bound_object
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Dec 24, 2023
1 parent d669a94 commit 20a71ba
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 7 deletions.
7 changes: 6 additions & 1 deletion src/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use pyo3_macros::{pyclass, pymethods};
use crate::{
coroutine::{cancel::ThrowCallback, waker::AsyncioWaker},
exceptions::{PyAttributeError, PyRuntimeError, PyStopIteration},
instance::Bound,
panic::PanicException,
types::{PyIterator, PyString},
IntoPy, Py, PyAny, PyErr, PyObject, PyResult, Python,
Expand Down Expand Up @@ -107,7 +108,11 @@ 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(Bound::borrowed_from_gil_ref(&future))
.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());
Expand Down
2 changes: 1 addition & 1 deletion src/types/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2032,7 +2032,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 {
Expand Down
16 changes: 11 additions & 5 deletions src/types/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,19 @@ 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`.
#[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(Bound::borrowed_from_gil_ref(&obj)).map(Bound::into_gil_ref)
Self::from_bound_object(Bound::borrowed_from_gil_ref(&obj)).map(Bound::into_gil_ref)
}

pub(crate) fn from_object2<'py>(obj: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyIterator>> {
/// Constructs a `PyIterator` from a Python iterable object.
///
/// Equivalent to Python's built-in `iter` 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())
Expand Down Expand Up @@ -240,6 +245,7 @@ def fibonacci(target):
fn int_not_iterable() {
Python::with_gil(|py| {
let x = 5.to_object(py);
#[allow(deprecated)]
let err = PyIterator::from_object(x.as_ref(py)).unwrap_err();

assert!(err.is_instance_of::<PyTypeError>(py));
Expand Down

0 comments on commit 20a71ba

Please sign in to comment.