-
Notifications
You must be signed in to change notification settings - Fork 909
Description
Currently __anext__ expects IterANextOutput<_, _>, which can be only converted from Option<T1> or IterANextOutput<T2, T3> where all Ts implement IntoPy<PyObject>. But __anext__ frequently returns an awaitable, and whether the result is going to be Yield or Return is up to the awaitable and not __anext__ itself.
Searching for the existing __anext__ implementations from GitHub confirms this issue, and everyone seems to come up with their own workaround (I also had one):
- https://github.com/Gelbpunkt/zangy/blob/a00fb19a62d2f2446c73d0c66999983c22b58627/src/pool.rs#L1373
- https://github.com/apache/incubator-opendal/blob/2d4c14437328bdf2bb96de8395f833777e777a55/bindings/python/src/asyncio.rs#L351
- https://github.com/hydro-project/hydroflow/blob/28f7c69cd73f0556b5ac2688105417d4ce0e8d08/hydro_cli/src/lib.rs#L414-L422
- https://github.com/awslabs/smithy-rs/blob/79ead4884c206f1c41eacb5e61feab2a96c06173/rust-runtime/aws-smithy-http-server-python/src/types.rs#L489
Therefore ideally we should allow any T (that implements IntoPy<PyObject> as above), but that impl will conflict with both existing impls. While the impl for IterANextOutput<_, _> can be merged into IntoPyCallbackOutput and so is redundant, the impl for Option<T> cannot be removed because (Rust) None should be converted to PyStopAsyncIteration, not (Python) None. So the only possibility would be an autoref specialization.
On the other hand the value of forcing IterANextOutput<_, _> from __anext__ seems unclear. Assuming the last __anext__ did return some awaitable and it yielded some value, the awaitable might or might not know that the iteration has stopped---both possibilities are plausible. The current design is only suitable if the stop is already known. Probably __anext__ should not restrict return types and we should just make IterANextOutput implement IntoPy, ditching the Option<T> case (with a proper documentation of course).