Also replace IterANextOutput by autoref-based specialization to allow returning arbitrary values
This commit is contained in:
parent
ca7d90dcf3
commit
83697f0c62
|
@ -799,8 +799,9 @@ const __NEXT__: SlotDef = SlotDef::new("Py_tp_iternext", "iternextfunc")
|
|||
);
|
||||
const __AWAIT__: SlotDef = SlotDef::new("Py_am_await", "unaryfunc");
|
||||
const __AITER__: SlotDef = SlotDef::new("Py_am_aiter", "unaryfunc");
|
||||
const __ANEXT__: SlotDef = SlotDef::new("Py_am_anext", "unaryfunc").return_conversion(
|
||||
TokenGenerator(|| quote! { _pyo3::class::pyasync::IterANextOutput::<_, _> }),
|
||||
const __ANEXT__: SlotDef = SlotDef::new("Py_am_anext", "unaryfunc").return_specialized_conversion(
|
||||
TokenGenerator(|| quote! { AsyncIterBaseKind, AsyncIterOptionKind, AsyncIterResultOptionKind }),
|
||||
TokenGenerator(|| quote! { async_iter_tag }),
|
||||
);
|
||||
const __LEN__: SlotDef = SlotDef::new("Py_mp_length", "lenfunc").ret_ty(Ty::PySsizeT);
|
||||
const __CONTAINS__: SlotDef = SlotDef::new("Py_sq_contains", "objobjproc")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::callback::IntoPyCallbackOutput;
|
||||
use crate::exceptions::PyStopAsyncIteration;
|
||||
use crate::gil::LockGIL;
|
||||
use crate::impl_::panic::PanicTrap;
|
||||
use crate::internal_tricks::extract_c_string;
|
||||
|
@ -381,3 +382,83 @@ pub trait IterResultOptionKind {
|
|||
}
|
||||
|
||||
impl<Value> IterResultOptionKind for PyResult<Option<Value>> {}
|
||||
|
||||
// Autoref-based specialization for handling `__anext__` returning `Option`
|
||||
|
||||
pub struct AsyncIterBaseTag;
|
||||
|
||||
impl AsyncIterBaseTag {
|
||||
#[inline]
|
||||
pub fn convert<Value, Target>(self, py: Python<'_>, value: Value) -> PyResult<Target>
|
||||
where
|
||||
Value: IntoPyCallbackOutput<Target>,
|
||||
{
|
||||
value.convert(py)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsyncIterBaseKind {
|
||||
#[inline]
|
||||
fn async_iter_tag(&self) -> AsyncIterBaseTag {
|
||||
AsyncIterBaseTag
|
||||
}
|
||||
}
|
||||
|
||||
impl<Value> AsyncIterBaseKind for &Value {}
|
||||
|
||||
pub struct AsyncIterOptionTag;
|
||||
|
||||
impl AsyncIterOptionTag {
|
||||
#[inline]
|
||||
pub fn convert<Value>(
|
||||
self,
|
||||
py: Python<'_>,
|
||||
value: Option<Value>,
|
||||
) -> PyResult<*mut ffi::PyObject>
|
||||
where
|
||||
Value: IntoPyCallbackOutput<*mut ffi::PyObject>,
|
||||
{
|
||||
match value {
|
||||
Some(value) => value.convert(py),
|
||||
None => Err(PyStopAsyncIteration::new_err(())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsyncIterOptionKind {
|
||||
#[inline]
|
||||
fn async_iter_tag(&self) -> AsyncIterOptionTag {
|
||||
AsyncIterOptionTag
|
||||
}
|
||||
}
|
||||
|
||||
impl<Value> AsyncIterOptionKind for Option<Value> {}
|
||||
|
||||
pub struct AsyncIterResultOptionTag;
|
||||
|
||||
impl AsyncIterResultOptionTag {
|
||||
#[inline]
|
||||
pub fn convert<Value>(
|
||||
self,
|
||||
py: Python<'_>,
|
||||
value: PyResult<Option<Value>>,
|
||||
) -> PyResult<*mut ffi::PyObject>
|
||||
where
|
||||
Value: IntoPyCallbackOutput<*mut ffi::PyObject>,
|
||||
{
|
||||
match value {
|
||||
Ok(Some(value)) => value.convert(py),
|
||||
Ok(None) => Err(PyStopAsyncIteration::new_err(())),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsyncIterResultOptionKind {
|
||||
#[inline]
|
||||
fn async_iter_tag(&self) -> AsyncIterResultOptionTag {
|
||||
AsyncIterResultOptionTag
|
||||
}
|
||||
}
|
||||
|
||||
impl<Value> AsyncIterResultOptionKind for PyResult<Option<Value>> {}
|
||||
|
|
|
@ -351,6 +351,7 @@ pub mod class {
|
|||
/// For compatibility reasons this has not yet been removed, however will be done so
|
||||
/// once <https://github.com/rust-lang/rust/issues/30827> is resolved.
|
||||
pub mod pyasync {
|
||||
#[allow(deprecated)]
|
||||
pub use crate::pyclass::{IterANextOutput, PyIterANextOutput};
|
||||
}
|
||||
|
||||
|
|
|
@ -155,6 +155,10 @@ where
|
|||
/// Output of `__anext__`.
|
||||
///
|
||||
/// <https://docs.python.org/3/reference/expressions.html#agen.__anext__>
|
||||
#[deprecated(
|
||||
since = "0.21.0",
|
||||
note = "Use `Option` or `PyStopAsyncIteration` instead."
|
||||
)]
|
||||
pub enum IterANextOutput<T, U> {
|
||||
/// An expression which the generator yielded.
|
||||
Yield(T),
|
||||
|
@ -163,40 +167,25 @@ pub enum IterANextOutput<T, U> {
|
|||
}
|
||||
|
||||
/// An [IterANextOutput] of Python objects.
|
||||
#[deprecated(
|
||||
since = "0.21.0",
|
||||
note = "Use `Option` or `PyStopAsyncIteration` instead."
|
||||
)]
|
||||
#[allow(deprecated)]
|
||||
pub type PyIterANextOutput = IterANextOutput<PyObject, PyObject>;
|
||||
|
||||
impl IntoPyCallbackOutput<*mut ffi::PyObject> for PyIterANextOutput {
|
||||
fn convert(self, _py: Python<'_>) -> PyResult<*mut ffi::PyObject> {
|
||||
match self {
|
||||
IterANextOutput::Yield(o) => Ok(o.into_ptr()),
|
||||
IterANextOutput::Return(opt) => {
|
||||
Err(crate::exceptions::PyStopAsyncIteration::new_err((opt,)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> IntoPyCallbackOutput<PyIterANextOutput> for IterANextOutput<T, U>
|
||||
#[allow(deprecated)]
|
||||
impl<T, U> IntoPyCallbackOutput<*mut ffi::PyObject> for IterANextOutput<T, U>
|
||||
where
|
||||
T: IntoPy<PyObject>,
|
||||
U: IntoPy<PyObject>,
|
||||
{
|
||||
fn convert(self, py: Python<'_>) -> PyResult<PyIterANextOutput> {
|
||||
fn convert(self, py: Python<'_>) -> PyResult<*mut ffi::PyObject> {
|
||||
match self {
|
||||
IterANextOutput::Yield(o) => Ok(IterANextOutput::Yield(o.into_py(py))),
|
||||
IterANextOutput::Return(o) => Ok(IterANextOutput::Return(o.into_py(py))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoPyCallbackOutput<PyIterANextOutput> for Option<T>
|
||||
where
|
||||
T: IntoPy<PyObject>,
|
||||
{
|
||||
fn convert(self, py: Python<'_>) -> PyResult<PyIterANextOutput> {
|
||||
match self {
|
||||
Some(o) => Ok(PyIterANextOutput::Yield(o.into_py(py))),
|
||||
None => Ok(PyIterANextOutput::Return(py.None().into())),
|
||||
IterANextOutput::Yield(o) => Ok(o.into_py(py).into_ptr()),
|
||||
IterANextOutput::Return(o) => Err(crate::exceptions::PyStopAsyncIteration::new_err(
|
||||
o.into_py(py),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue