diff --git a/pytests/test_async_std_asyncio.rs b/pytests/test_async_std_asyncio.rs index 7a7d800..3314500 100644 --- a/pytests/test_async_std_asyncio.rs +++ b/pytests/test_async_std_asyncio.rs @@ -96,12 +96,11 @@ async fn test_other_awaitables() -> PyResult<()> { #[pyo3_async_runtimes::async_std::test] async fn test_panic() -> PyResult<()> { let fut = Python::with_gil(|py| -> PyResult<_> { - pyo3_async_runtimes::async_std::into_future(pyo3_async_runtimes::async_std::future_into_py::< - _, - (), - >(py, async { - panic!("this panic was intentional!") - })?) + pyo3_async_runtimes::async_std::into_future( + pyo3_async_runtimes::async_std::future_into_py::<_, ()>(py, async { + panic!("this panic was intentional!") + })?, + ) })?; match fut.await { @@ -385,5 +384,7 @@ fn test_contextvars() -> PyResult<()> { fn main() -> pyo3::PyResult<()> { pyo3::prepare_freethreaded_python(); - Python::with_gil(|py| pyo3_async_runtimes::async_std::run(py, pyo3_async_runtimes::testing::main())) + Python::with_gil(|py| { + pyo3_async_runtimes::async_std::run(py, pyo3_async_runtimes::testing::main()) + }) } diff --git a/pytests/tokio_asyncio/mod.rs b/pytests/tokio_asyncio/mod.rs index 4692506..6a7d8fe 100644 --- a/pytests/tokio_asyncio/mod.rs +++ b/pytests/tokio_asyncio/mod.rs @@ -122,10 +122,11 @@ fn test_local_future_into_py(event_loop: PyObject) -> PyResult<()> { #[pyo3_async_runtimes::tokio::test] async fn test_panic() -> PyResult<()> { let fut = Python::with_gil(|py| -> PyResult<_> { - pyo3_async_runtimes::tokio::into_future(pyo3_async_runtimes::tokio::future_into_py::<_, ()>( - py, - async { panic!("this panic was intentional!") }, - )?) + pyo3_async_runtimes::tokio::into_future( + pyo3_async_runtimes::tokio::future_into_py::<_, ()>(py, async { + panic!("this panic was intentional!") + })?, + ) })?; match fut.await { diff --git a/src/generic.rs b/src/generic.rs index 415fa8b..3756cf9 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -5,7 +5,7 @@ //! class="module-item stab portability" //! style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;" //! >unstable-streams -//! are only available when the `unstable-streams` Cargo feature is enabled: +//! > are only available when the `unstable-streams` Cargo feature is enabled: //! //! ```toml //! [dependencies.pyo3-asyncio-0-21] @@ -478,13 +478,13 @@ where /// via [`into_future`] (new behaviour in `v0.15`). /// /// > Although `contextvars` are preserved for async Python functions, synchronous functions will -/// unfortunately fail to resolve them when called within the Rust future. This is because the -/// function is being called from a Rust thread, not inside an actual Python coroutine context. +/// > unfortunately fail to resolve them when called within the Rust future. This is because the +/// > function is being called from a Rust thread, not inside an actual Python coroutine context. /// > /// > As a workaround, you can get the `contextvars` from the current task locals using -/// [`get_current_locals`] and [`TaskLocals::context`](`crate::TaskLocals::context`), then wrap your -/// synchronous function in a call to `contextvars.Context.run`. This will set the context, call the -/// synchronous function, and restore the previous context when it returns or raises an exception. +/// > [`get_current_locals`] and [`TaskLocals::context`](`crate::TaskLocals::context`), then wrap your +/// > synchronous function in a call to `contextvars.Context.run`. This will set the context, call the +/// > synchronous function, and restore the previous context when it returns or raises an exception. /// /// # Arguments /// * `py` - PyO3 GIL guard @@ -655,7 +655,7 @@ fn get_panic_message(any: &dyn std::any::Any) -> &str { if let Some(str_slice) = any.downcast_ref::<&str>() { str_slice } else if let Some(string) = any.downcast_ref::() { - string + string.as_str() } else { "unknown error" } @@ -751,13 +751,13 @@ impl PyDoneCallback { /// via [`into_future`] (new behaviour in `v0.15`). /// /// > Although `contextvars` are preserved for async Python functions, synchronous functions will -/// unfortunately fail to resolve them when called within the Rust future. This is because the -/// function is being called from a Rust thread, not inside an actual Python coroutine context. +/// > unfortunately fail to resolve them when called within the Rust future. This is because the +/// > function is being called from a Rust thread, not inside an actual Python coroutine context. /// > /// > As a workaround, you can get the `contextvars` from the current task locals using -/// [`get_current_locals`] and [`TaskLocals::context`](`crate::TaskLocals::context`), then wrap your -/// synchronous function in a call to `contextvars.Context.run`. This will set the context, call the -/// synchronous function, and restore the previous context when it returns or raises an exception. +/// > [`get_current_locals`] and [`TaskLocals::context`](`crate::TaskLocals::context`), then wrap your +/// > synchronous function in a call to `contextvars.Context.run`. This will set the context, call the +/// > synchronous function, and restore the previous context when it returns or raises an exception. /// /// # Arguments /// * `py` - The current PyO3 GIL guard @@ -859,13 +859,13 @@ where /// via [`into_future`] (new behaviour in `v0.15`). /// /// > Although `contextvars` are preserved for async Python functions, synchronous functions will -/// unfortunately fail to resolve them when called within the Rust future. This is because the -/// function is being called from a Rust thread, not inside an actual Python coroutine context. +/// > unfortunately fail to resolve them when called within the Rust future. This is because the +/// > function is being called from a Rust thread, not inside an actual Python coroutine context. /// > /// > As a workaround, you can get the `contextvars` from the current task locals using -/// [`get_current_locals`] and [`TaskLocals::context`](`crate::TaskLocals::context`), then wrap your -/// synchronous function in a call to `contextvars.Context.run`. This will set the context, call the -/// synchronous function, and restore the previous context when it returns or raises an exception. +/// > [`get_current_locals`] and [`TaskLocals::context`](`crate::TaskLocals::context`), then wrap your +/// > synchronous function in a call to `contextvars.Context.run`. This will set the context, call the +/// > synchronous function, and restore the previous context when it returns or raises an exception. /// /// # Arguments /// * `py` - PyO3 GIL guard @@ -1065,13 +1065,13 @@ where /// via [`into_future`] (new behaviour in `v0.15`). /// /// > Although `contextvars` are preserved for async Python functions, synchronous functions will -/// unfortunately fail to resolve them when called within the Rust future. This is because the -/// function is being called from a Rust thread, not inside an actual Python coroutine context. +/// > unfortunately fail to resolve them when called within the Rust future. This is because the +/// > function is being called from a Rust thread, not inside an actual Python coroutine context. /// > /// > As a workaround, you can get the `contextvars` from the current task locals using -/// [`get_current_locals`] and [`TaskLocals::context`](`crate::TaskLocals::context`), then wrap your -/// synchronous function in a call to `contextvars.Context.run`. This will set the context, call the -/// synchronous function, and restore the previous context when it returns or raises an exception. +/// > [`get_current_locals`] and [`TaskLocals::context`](`crate::TaskLocals::context`), then wrap your +/// > synchronous function in a call to `contextvars.Context.run`. This will set the context, call the +/// > synchronous function, and restore the previous context when it returns or raises an exception. /// /// # Arguments /// * `py` - The current PyO3 GIL guard @@ -1446,11 +1446,14 @@ where into_stream_with_locals_v1::(get_current_locals::(gen.py())?, gen) } +#[allow(dead_code)] fn py_true() -> PyObject { static TRUE: OnceCell = OnceCell::new(); TRUE.get_or_init(|| Python::with_gil(|py| true.into_py(py))) .clone() } + +#[allow(dead_code)] fn py_false() -> PyObject { static FALSE: OnceCell = OnceCell::new(); FALSE @@ -1463,6 +1466,7 @@ trait Sender: Send + 'static { fn close(&mut self) -> PyResult<()>; } +#[allow(dead_code)] struct GenericSender where R: Runtime, diff --git a/src/lib.rs b/src/lib.rs index 8439427..e7b7453 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,8 +41,8 @@ //! library needs to be able to preserve `contextvars` during conversions. //! //! > The core conversions we've mentioned so far in the README should insulate you from these -//! concerns in most cases. For the edge cases where they don't, this section should provide you -//! with the information you need to solve these problems. +//! > concerns in most cases. For the edge cases where they don't, this section should provide you +//! > with the information you need to solve these problems. //! //! ### The Main Dilemma //! @@ -74,9 +74,9 @@ //! //! - `pyo3_async_runtimes::into_future_with_locals` - Convert a Python awaitable into a Rust future. //! - `pyo3_async_runtimes::::future_into_py_with_locals` - Convert a Rust future into a Python -//! awaitable. +//! awaitable. //! - `pyo3_async_runtimes::::local_future_into_py_with_locals` - Convert a `!Send` Rust future -//! into a Python awaitable. +//! into a Python awaitable. //! //! One clear disadvantage to this approach is that the Rust application has to explicitly track //! these references. In native libraries, we can't make any assumptions about the underlying event @@ -119,12 +119,12 @@ //! ``` //! //! > A naive solution to this tracking problem would be to cache a global reference to the asyncio -//! event loop that all PyO3 Asyncio conversions can use. In fact this is what we did in PyO3 -//! Asyncio `v0.13`. This works well for applications, but it soon became clear that this is not -//! so ideal for libraries. Libraries usually have no direct control over how the event loop is -//! managed, they're just expected to work with any event loop at any point in the application. -//! This problem is compounded further when multiple event loops are used in the application since -//! the global reference will only point to one. +//! > event loop that all PyO3 Asyncio conversions can use. In fact this is what we did in PyO3 +//! > Asyncio `v0.13`. This works well for applications, but it soon became clear that this is not +//! > so ideal for libraries. Libraries usually have no direct control over how the event loop is +//! > managed, they're just expected to work with any event loop at any point in the application. +//! > This problem is compounded further when multiple event loops are used in the application since +//! > the global reference will only point to one. //! //! Another disadvantage to this explicit approach that is less obvious is that we can no longer //! call our `#[pyfunction] fn sleep` on a Rust runtime since `asyncio.get_running_loop` only works @@ -146,7 +146,7 @@ //! //! - `pyo3_async_runtimes::::scope` - Store the task-local data when executing the given Future. //! - `pyo3_async_runtimes::::scope_local` - Store the task-local data when executing the given -//! `!Send` Future. +//! `!Send` Future. //! //! With these new functions, we can make our previous example more correct: //! @@ -222,15 +222,15 @@ //! //! - `pyo3_async_runtimes::::into_future` //! > Convert a Python awaitable into a Rust future (using -//! `pyo3_async_runtimes::::get_current_locals`) +//! > `pyo3_async_runtimes::::get_current_locals`) //! - `pyo3_async_runtimes::::future_into_py` //! > Convert a Rust future into a Python awaitable (using -//! `pyo3_async_runtimes::::get_current_locals` and `pyo3_async_runtimes::::scope` to set the -//! task-local event loop for the given Rust future) +//! > `pyo3_async_runtimes::::get_current_locals` and `pyo3_async_runtimes::::scope` to set the +//! > task-local event loop for the given Rust future) //! - `pyo3_async_runtimes::::local_future_into_py` //! > Convert a `!Send` Rust future into a Python awaitable (using -//! `pyo3_async_runtimes::::get_current_locals` and `pyo3_async_runtimes::::scope_local` to -//! set the task-local event loop for the given Rust future). +//! > `pyo3_async_runtimes::::get_current_locals` and `pyo3_async_runtimes::::scope_local` to +//! > set the task-local event loop for the given Rust future). //! //! __These are the functions that we recommend using__. With these functions, the previous example //! can be rewritten to be more compact: @@ -278,7 +278,7 @@ //! ``` //! //! > A special thanks to [@ShadowJonathan](https://github.com/ShadowJonathan) for helping with the -//! design and review of these changes! +//! > design and review of these changes! //! //! ## Rust's Event Loop //! @@ -287,7 +287,7 @@ //! with the [`generic`] module)! //! //! > _In the future, we may implement first class support for more Rust runtimes. Contributions are -//! welcome as well!_ +//! > welcome as well!_ //! //! ## Features //! @@ -296,7 +296,7 @@ //! class="module-item stab portability" //! style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;" //! >attributes -//! are only available when the `attributes` Cargo feature is enabled: +//! > are only available when the `attributes` Cargo feature is enabled: //! //! ```toml //! [dependencies.pyo3-asyncio-0-21] @@ -309,7 +309,7 @@ //! class="module-item stab portability" //! style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;" //! >async-std-runtime -//! are only available when the `async-std-runtime` Cargo feature is enabled: +//! > are only available when the `async-std-runtime` Cargo feature is enabled: //! //! ```toml //! [dependencies.pyo3-asyncio-0-21] @@ -322,7 +322,7 @@ //! class="module-item stab portability" //! style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;" //! >tokio-runtime -//! are only available when the `tokio-runtime` Cargo feature is enabled: +//! > are only available when the `tokio-runtime` Cargo feature is enabled: //! //! ```toml //! [dependencies.pyo3-asyncio-0-21] @@ -335,7 +335,7 @@ //! class="module-item stab portability" //! style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;" //! >testing -//! are only available when the `testing` Cargo feature is enabled: +//! > are only available when the `testing` Cargo feature is enabled: //! //! ```toml //! [dependencies.pyo3-asyncio-0-21]