Skip to content

Commit 99fe0b7

Browse files
author
Andrew J Westlake
committed
Added spawn_local impl for async-std
1 parent 17f8d7a commit 99fe0b7

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

pytests/test_async_std_asyncio.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
mod common;
22

3-
use std::time::Duration;
3+
use std::{rc::Rc, time::Duration};
44

55
use async_std::task;
66
use pyo3::{prelude::*, wrap_pyfunction};
@@ -78,3 +78,20 @@ fn test_init_twice() -> PyResult<()> {
7878
async fn main() -> pyo3::PyResult<()> {
7979
pyo3_asyncio::testing::main().await
8080
}
81+
82+
#[pyo3_asyncio::async_std::test]
83+
async fn test_local_coroutine() -> PyResult<()> {
84+
Python::with_gil(|py| {
85+
let non_send_secs = Rc::new(1);
86+
87+
let py_future = pyo3_asyncio::async_std::into_local_py_future(py, async move {
88+
async_std::task::sleep(Duration::from_secs(*non_send_secs)).await;
89+
Ok(Python::with_gil(|py| py.None()))
90+
})?;
91+
92+
pyo3_asyncio::into_future(py_future.as_ref(py))
93+
})?
94+
.await?;
95+
96+
Ok(())
97+
}

src/async_std.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::future::Future;
33
use async_std::task;
44
use pyo3::prelude::*;
55

6-
use crate::generic::{self, JoinError, Runtime};
6+
use crate::generic::{self, JoinError, Runtime, SpawnLocalExt};
77

88
/// <span class="module-item stab portability" style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;"><code>attributes</code></span>
99
/// re-exports for macros
@@ -48,6 +48,18 @@ impl Runtime for AsyncStdRuntime {
4848
}
4949
}
5050

51+
impl SpawnLocalExt for AsyncStdRuntime {
52+
fn spawn_local<F>(fut: F) -> Self::JoinHandle
53+
where
54+
F: Future<Output = ()> + 'static,
55+
{
56+
task::spawn_local(async move {
57+
fut.await;
58+
Ok(())
59+
})
60+
}
61+
}
62+
5163
/// Run the event loop until the given Future completes
5264
///
5365
/// The event loop runs until the given future is complete.
@@ -117,3 +129,49 @@ where
117129
{
118130
generic::into_coroutine::<AsyncStdRuntime, _>(py, fut)
119131
}
132+
133+
/// Convert a `!Send` Rust Future into a Python coroutine
134+
///
135+
/// # Arguments
136+
/// * `py` - The current PyO3 GIL guard
137+
/// * `fut` - The Rust future to be converted
138+
///
139+
/// # Examples
140+
///
141+
/// ```
142+
/// use std::{rc::Rc, time::Duration};
143+
///
144+
/// use pyo3::prelude::*;
145+
///
146+
/// /// Awaitable non-send sleep function
147+
/// #[pyfunction]
148+
/// fn sleep_for(py: Python, secs: u64) -> PyResult<PyObject> {
149+
/// // Rc is non-send so it cannot be passed into pyo3_asyncio::tokio::into_coroutine
150+
/// let secs = Rc::new(secs);
151+
///
152+
/// pyo3_asyncio::async_std::into_local_py_future(py, async move {
153+
/// async_std::task::sleep(Duration::from_secs(*secs)).await;
154+
/// Python::with_gil(|py| Ok(py.None()))
155+
/// })
156+
/// }
157+
///
158+
/// # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
159+
/// #[pyo3_asyncio::async_std::main]
160+
/// async fn main() -> PyResult<()> {
161+
/// Python::with_gil(|py| {
162+
/// let py_future = sleep_for(py, 1)?;
163+
/// pyo3_asyncio::into_future(py_future.as_ref(py))
164+
/// })?
165+
/// .await?;
166+
///
167+
/// Ok(())
168+
/// }
169+
/// # #[cfg(not(all(feature = "async-std-runtime", feature = "attributes")))]
170+
/// # fn main() {}
171+
/// ```
172+
pub fn into_local_py_future<F>(py: Python, fut: F) -> PyResult<PyObject>
173+
where
174+
F: Future<Output = PyResult<PyObject>> + 'static,
175+
{
176+
generic::into_local_py_future::<AsyncStdRuntime, _>(py, fut)
177+
}

0 commit comments

Comments
 (0)