Relax the error type in the Result<Option<T>, E>> specializations for __(a)next__.
This commit is contained in:
parent
a605308cee
commit
5528895f3e
|
@ -76,7 +76,7 @@ Python::with_gil(|py| {
|
||||||
|
|
||||||
### `Iter(A)NextOutput` are deprecated
|
### `Iter(A)NextOutput` are deprecated
|
||||||
|
|
||||||
The `__next__` and `__anext__` magic methods can now return any type convertible into Python objects directly just like all other `#[pymethods]`. The `IterNextOutput` used by `__next__` and `IterANextOutput` used by `__anext__` are subsequently deprecated. Most importantly, this change allows returning an awaitable from `__anext__` without non-sensically wrapping it into `Yield` or `Some`. Only the return types `Option<T>` and `PyResult<Option<T>>` are still handled in a special manner where `Some(val)` yields `val` and `None` stops iteration.
|
The `__next__` and `__anext__` magic methods can now return any type convertible into Python objects directly just like all other `#[pymethods]`. The `IterNextOutput` used by `__next__` and `IterANextOutput` used by `__anext__` are subsequently deprecated. Most importantly, this change allows returning an awaitable from `__anext__` without non-sensically wrapping it into `Yield` or `Some`. Only the return types `Option<T>` and `Result<Option<T>, E>` are still handled in a special manner where `Some(val)` yields `val` and `None` stops iteration.
|
||||||
|
|
||||||
Starting with an implementation of a Python iterator using `IterNextOutput`, e.g.
|
Starting with an implementation of a Python iterator using `IterNextOutput`, e.g.
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ impl PyClassIter {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This form also has additional benefits: It has already worked in previous PyO3 versions, it matches the signature of Rust's [`Iterator` trait](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) and it allows using a fast path in CPython which completely avoids the cost of raising a `StopIteration` exception. Note that using [`Option::transpose`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose) and the `PyResult<Option<T>>` variant, this form can also be used to wrap fallible iterators.
|
This form also has additional benefits: It has already worked in previous PyO3 versions, it matches the signature of Rust's [`Iterator` trait](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) and it allows using a fast path in CPython which completely avoids the cost of raising a `StopIteration` exception. Note that using [`Option::transpose`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose) and the `Result<Option<T>, E>` variant, this form can also be used to wrap fallible iterators.
|
||||||
|
|
||||||
Alternatively, the implementation can also be done as it would in Python itself, i.e. by "raising" a `StopIteration` exception
|
Alternatively, the implementation can also be done as it would in Python itself, i.e. by "raising" a `StopIteration` exception
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,9 @@ use crate::exceptions::PyStopAsyncIteration;
|
||||||
use crate::gil::LockGIL;
|
use crate::gil::LockGIL;
|
||||||
use crate::impl_::panic::PanicTrap;
|
use crate::impl_::panic::PanicTrap;
|
||||||
use crate::internal_tricks::extract_c_string;
|
use crate::internal_tricks::extract_c_string;
|
||||||
use crate::{ffi, PyAny, PyCell, PyClass, PyObject, PyResult, PyTraverseError, PyVisit, Python};
|
use crate::{
|
||||||
|
ffi, PyAny, PyCell, PyClass, PyErr, PyObject, PyResult, PyTraverseError, PyVisit, Python,
|
||||||
|
};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -358,18 +360,19 @@ pub struct IterResultOptionTag;
|
||||||
|
|
||||||
impl IterResultOptionTag {
|
impl IterResultOptionTag {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn convert<Value>(
|
pub fn convert<Value, Error>(
|
||||||
self,
|
self,
|
||||||
py: Python<'_>,
|
py: Python<'_>,
|
||||||
value: PyResult<Option<Value>>,
|
value: Result<Option<Value>, Error>,
|
||||||
) -> PyResult<*mut ffi::PyObject>
|
) -> PyResult<*mut ffi::PyObject>
|
||||||
where
|
where
|
||||||
Value: IntoPyCallbackOutput<*mut ffi::PyObject>,
|
Value: IntoPyCallbackOutput<*mut ffi::PyObject>,
|
||||||
|
Error: Into<PyErr>,
|
||||||
{
|
{
|
||||||
match value {
|
match value {
|
||||||
Ok(Some(value)) => value.convert(py),
|
Ok(Some(value)) => value.convert(py),
|
||||||
Ok(None) => Ok(null_mut()),
|
Ok(None) => Ok(null_mut()),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,7 +384,7 @@ pub trait IterResultOptionKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Value> IterResultOptionKind for PyResult<Option<Value>> {}
|
impl<Value, Error> IterResultOptionKind for Result<Option<Value>, Error> {}
|
||||||
|
|
||||||
// Autoref-based specialization for handling `__anext__` returning `Option`
|
// Autoref-based specialization for handling `__anext__` returning `Option`
|
||||||
|
|
||||||
|
@ -438,18 +441,19 @@ pub struct AsyncIterResultOptionTag;
|
||||||
|
|
||||||
impl AsyncIterResultOptionTag {
|
impl AsyncIterResultOptionTag {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn convert<Value>(
|
pub fn convert<Value, Error>(
|
||||||
self,
|
self,
|
||||||
py: Python<'_>,
|
py: Python<'_>,
|
||||||
value: PyResult<Option<Value>>,
|
value: Result<Option<Value>, Error>,
|
||||||
) -> PyResult<*mut ffi::PyObject>
|
) -> PyResult<*mut ffi::PyObject>
|
||||||
where
|
where
|
||||||
Value: IntoPyCallbackOutput<*mut ffi::PyObject>,
|
Value: IntoPyCallbackOutput<*mut ffi::PyObject>,
|
||||||
|
Error: Into<PyErr>,
|
||||||
{
|
{
|
||||||
match value {
|
match value {
|
||||||
Ok(Some(value)) => value.convert(py),
|
Ok(Some(value)) => value.convert(py),
|
||||||
Ok(None) => Err(PyStopAsyncIteration::new_err(())),
|
Ok(None) => Err(PyStopAsyncIteration::new_err(())),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,4 +465,4 @@ pub trait AsyncIterResultOptionKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Value> AsyncIterResultOptionKind for PyResult<Option<Value>> {}
|
impl<Value, Error> AsyncIterResultOptionKind for Result<Option<Value>, Error> {}
|
||||||
|
|
Loading…
Reference in New Issue