From 12b0f9ee50c8c2fc5b19cb7fc2ea5cd4d738a35c Mon Sep 17 00:00:00 2001 From: Chris Sellers Date: Thu, 10 Oct 2024 13:58:53 +1100 Subject: [PATCH 1/8] Fix formatting and clippy lints --- pytests/test_async_std_asyncio.rs | 15 +++++----- pytests/tokio_asyncio/mod.rs | 9 +++--- src/generic.rs | 48 +++++++++++++++++-------------- src/lib.rs | 44 ++++++++++++++-------------- 4 files changed, 61 insertions(+), 55 deletions(-) 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] From 490f2e6b6feeb599845036f9543601b8d6780db8 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Sat, 5 Oct 2024 09:36:05 +0100 Subject: [PATCH 2/8] update CI to run targeting main --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9838b91..5c712f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,10 +3,10 @@ name: CI on: push: branches: - - master + - main pull_request: branches: - - master + - main env: CARGO_TERM_COLOR: always From 5fbc57ce055d3068761d7f49ad6e0b9a8cdf8c98 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Thu, 10 Oct 2024 06:16:45 +0100 Subject: [PATCH 3/8] fix naming error --- src/async_std.rs | 4 ++-- src/tokio.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/async_std.rs b/src/async_std.rs index 476b236..6ab2e16 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -34,13 +34,13 @@ pub mod re_exports { /// attributes Provides the boilerplate for the `async-std` runtime and runs an async fn as main #[cfg(feature = "attributes")] -pub use pyo3_asyncio_macros_0_21::async_std_main as main; +pub use pyo3_async_runtimes_macros::async_std_main as main; /// attributes /// testing /// Registers an `async-std` test with the `pyo3-asyncio` test harness #[cfg(all(feature = "attributes", feature = "testing"))] -pub use pyo3_asyncio_macros_0_21::async_std_test as test; +pub use pyo3_async_runtimes_macros::async_std_test as test; struct AsyncStdJoinErr(Box); diff --git a/src/tokio.rs b/src/tokio.rs index cb24141..468a49c 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -43,13 +43,13 @@ pub mod re_exports { /// attributes #[cfg(feature = "attributes")] -pub use pyo3_asyncio_macros_0_21::tokio_main as main; +pub use pyo3_async_runtimes_macros::tokio_main as main; /// attributes /// testing /// Registers a `tokio` test with the `pyo3-asyncio` test harness #[cfg(all(feature = "attributes", feature = "testing"))] -pub use pyo3_asyncio_macros_0_21::tokio_test as test; +pub use pyo3_async_runtimes_macros::tokio_test as test; enum Pyo3Runtime { Borrowed(&'static Runtime), From 8288819b97ce4b9e646f75cb435e2b70076a8dc7 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Tue, 8 Oct 2024 10:42:17 +0200 Subject: [PATCH 4/8] cargo clippy --- src/async_std.rs | 60 ++++++++++++++++++++++++------------------------ src/generic.rs | 16 ++++++------- src/testing.rs | 17 +++----------- src/tokio.rs | 59 ++++++++++++++++++++++++----------------------- 4 files changed, 71 insertions(+), 81 deletions(-) diff --git a/src/async_std.rs b/src/async_std.rs index 6ab2e16..3e9b702 100644 --- a/src/async_std.rs +++ b/src/async_std.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] @@ -71,7 +71,7 @@ impl Runtime for AsyncStdRuntime { AssertUnwindSafe(fut) .catch_unwind() .await - .map_err(|e| AsyncStdJoinErr(e)) + .map_err(AsyncStdJoinErr) }) } } @@ -236,13 +236,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 @@ -291,13 +291,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 @@ -337,13 +337,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 @@ -412,13 +412,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 @@ -573,8 +573,8 @@ pub fn into_future( /// # fn main() {} /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_v1<'p>( - gen: Bound<'p, PyAny>, +pub fn into_stream_v1( + gen: Bound<'_, PyAny>, ) -> PyResult> + 'static> { generic::into_stream_v1::(gen) } @@ -633,9 +633,9 @@ pub fn into_stream_v1<'p>( /// # fn main() {} /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_with_locals_v1<'p>( +pub fn into_stream_with_locals_v1( locals: TaskLocals, - gen: Bound<'p, PyAny>, + gen: Bound<'_, PyAny>, ) -> PyResult> + 'static> { generic::into_stream_with_locals_v1::(locals, gen) } @@ -694,9 +694,9 @@ pub fn into_stream_with_locals_v1<'p>( /// # fn main() {} /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_with_locals_v2<'p>( +pub fn into_stream_with_locals_v2( locals: TaskLocals, - gen: Bound<'p, PyAny>, + gen: Bound<'_, PyAny>, ) -> PyResult + 'static> { generic::into_stream_with_locals_v2::(locals, gen) } @@ -751,8 +751,8 @@ pub fn into_stream_with_locals_v2<'p>( /// # fn main() {} /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_v2<'p>( - gen: Bound<'p, PyAny>, +pub fn into_stream_v2( + gen: Bound<'_, PyAny>, ) -> PyResult + 'static> { generic::into_stream_v2::(gen) } diff --git a/src/generic.rs b/src/generic.rs index 3756cf9..fd40c84 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -1293,9 +1293,9 @@ where /// ``` #[cfg(feature = "unstable-streams")] #[allow(unused_must_use)] // False positive unused lint on `R::spawn` -pub fn into_stream_with_locals_v1<'p, R>( +pub fn into_stream_with_locals_v1( locals: TaskLocals, - gen: Bound<'p, PyAny>, + gen: Bound<'_, PyAny>, ) -> PyResult> + 'static> where R: Runtime, @@ -1437,8 +1437,8 @@ where /// # } /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_v1<'p, R>( - gen: Bound<'p, PyAny>, +pub fn into_stream_v1( + gen: Bound<'_, PyAny>, ) -> PyResult> + 'static> where R: Runtime + ContextExt, @@ -1651,9 +1651,9 @@ async def forward(gen, sender): /// # } /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_with_locals_v2<'p, R>( +pub fn into_stream_with_locals_v2( locals: TaskLocals, - gen: Bound<'p, PyAny>, + gen: Bound<'_, PyAny>, ) -> PyResult + 'static> where R: Runtime + ContextExt, @@ -1796,8 +1796,8 @@ where /// # } /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_v2<'p, R>( - gen: Bound<'p, PyAny>, +pub fn into_stream_v2( + gen: Bound<'_, PyAny>, ) -> PyResult + 'static> where R: Runtime + ContextExt, diff --git a/src/testing.rs b/src/testing.rs index ed004f9..b4d5785 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -189,16 +189,11 @@ use pyo3::prelude::*; /// /// These args are meant to mirror the default test harness's args. /// > Currently only `--filter` is supported. +#[derive(Default)] pub struct Args { filter: Option, } -impl Default for Args { - fn default() -> Self { - Self { filter: None } - } -} - /// Parse the test args from the command line /// /// This should be called at the start of your test harness to give the CLI some @@ -240,9 +235,7 @@ pub fn parse_args() -> Args { .get_matches(); Args { - filter: matches - .get_one::("TESTNAME") - .map(|name| name.clone()), + filter: matches.get_one::("TESTNAME").cloned(), } } @@ -315,11 +308,7 @@ pub async fn test_harness(tests: Vec, args: Args) -> PyResult<()> { pub async fn main() -> PyResult<()> { let args = parse_args(); - test_harness( - inventory::iter::().map(|test| test.clone()).collect(), - args, - ) - .await + test_harness(inventory::iter::().cloned().collect(), args).await } #[cfg(test)] diff --git a/src/tokio.rs b/src/tokio.rs index 468a49c..c41cf89 100644 --- a/src/tokio.rs +++ b/src/tokio.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] @@ -176,6 +176,7 @@ pub fn init(builder: Builder) { /// Initialize the Tokio runtime with a custom Tokio runtime /// /// Returns Ok(()) if success and Err(()) if it had been inited. +#[allow(clippy::result_unit_err)] pub fn init_with_runtime(runtime: &'static Runtime) -> Result<(), ()> { TOKIO_RUNTIME .set(Pyo3Runtime::Borrowed(runtime)) @@ -278,13 +279,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 @@ -333,13 +334,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 @@ -379,13 +380,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 @@ -470,13 +471,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 @@ -650,9 +651,9 @@ pub fn into_future( /// # fn main() {} /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_with_locals_v1<'p>( +pub fn into_stream_with_locals_v1( locals: TaskLocals, - gen: Bound<'p, PyAny>, + gen: Bound<'_, PyAny>, ) -> PyResult> + 'static> { generic::into_stream_with_locals_v1::(locals, gen) } @@ -707,8 +708,8 @@ pub fn into_stream_with_locals_v1<'p>( /// # fn main() {} /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_v1<'p>( - gen: Bound<'p, PyAny>, +pub fn into_stream_v1( + gen: Bound<'_, PyAny>, ) -> PyResult> + 'static> { generic::into_stream_v1::(gen) } @@ -767,9 +768,9 @@ pub fn into_stream_v1<'p>( /// # fn main() {} /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_with_locals_v2<'p>( +pub fn into_stream_with_locals_v2( locals: TaskLocals, - gen: Bound<'p, PyAny>, + gen: Bound<'_, PyAny>, ) -> PyResult + 'static> { generic::into_stream_with_locals_v2::(locals, gen) } @@ -824,8 +825,8 @@ pub fn into_stream_with_locals_v2<'p>( /// # fn main() {} /// ``` #[cfg(feature = "unstable-streams")] -pub fn into_stream_v2<'p>( - gen: Bound<'p, PyAny>, +pub fn into_stream_v2( + gen: Bound<'_, PyAny>, ) -> PyResult + 'static> { generic::into_stream_v2::(gen) } From dd4f0a67097ea404576bde30956d2dab588f40a5 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Tue, 8 Oct 2024 14:24:49 +0200 Subject: [PATCH 5/8] Update pyo3 to v0.22 --- Cargo.toml | 4 +-- src/async_std.rs | 14 +++++----- src/generic.rs | 70 +++++++++++++++++++----------------------------- src/lib.rs | 15 ++++++++--- src/tokio.rs | 10 ++++--- 5 files changed, 56 insertions(+), 57 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 49a0f6a..7d6f662 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -120,11 +120,11 @@ futures = "0.3" inventory = { version = "0.3", optional = true } once_cell = "1.14" pin-project-lite = "0.2" -pyo3 = "0.21" +pyo3 = "0.22" pyo3-async-runtimes-macros = { path = "pyo3-asyncio-macros", version = "=0.21.0", optional = true } [dev-dependencies] -pyo3 = { version = "0.21", features = ["macros"] } +pyo3 = { version = "0.22", features = ["macros"] } [dependencies.async-std] version = "1.12" diff --git a/src/async_std.rs b/src/async_std.rs index 3e9b702..199d472 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -13,11 +13,10 @@ //! features = ["unstable-streams"] //! ``` -use std::{any::Any, cell::RefCell, future::Future, panic::AssertUnwindSafe, pin::Pin}; - use async_std::task; use futures::FutureExt; use pyo3::prelude::*; +use std::{any::Any, cell::RefCell, future::Future, panic::AssertUnwindSafe, pin::Pin}; use crate::{ generic::{self, ContextExt, JoinError, LocalContextExt, Runtime, SpawnLocalExt}, @@ -90,10 +89,13 @@ impl ContextExt for AsyncStdRuntime { } fn get_task_locals() -> Option { - match TASK_LOCALS.try_with(|c| c.borrow().clone()) { - Ok(locals) => locals, - Err(_) => None, - } + TASK_LOCALS + .try_with(|c| { + c.borrow() + .as_ref() + .map(|locals| Python::with_gil(|py| locals.clone_ref(py))) + }) + .unwrap_or_default() } } diff --git a/src/generic.rs b/src/generic.rs index fd40c84..702d008 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -15,24 +15,24 @@ use std::{ future::Future, - marker::PhantomData, pin::Pin, sync::{Arc, Mutex}, task::{Context, Poll}, }; -use futures::{ - channel::{mpsc, oneshot}, - SinkExt, -}; -use once_cell::sync::OnceCell; -use pin_project_lite::pin_project; -use pyo3::prelude::*; - use crate::{ asyncio, call_soon_threadsafe, close, create_future, dump_err, err::RustPanic, get_running_loop, into_future_with_locals, TaskLocals, }; +use futures::channel::oneshot; +#[cfg(feature = "unstable-streams")] +use futures::{channel::mpsc, SinkExt}; +#[cfg(feature = "unstable-streams")] +use once_cell::sync::OnceCell; +use pin_project_lite::pin_project; +use pyo3::prelude::*; +#[cfg(feature = "unstable-streams")] +use std::marker::PhantomData; /// Generic utilities for a JoinError pub trait JoinError { @@ -585,7 +585,7 @@ where { let (cancel_tx, cancel_rx) = oneshot::channel(); - let py_fut = create_future(locals.event_loop.clone().into_bound(py))?; + let py_fut = create_future(locals.event_loop.bind(py).clone())?; py_fut.call_method1( "add_done_callback", (PyDoneCallback { @@ -594,14 +594,14 @@ where )?; let future_tx1 = PyObject::from(py_fut.clone()); - let future_tx2 = future_tx1.clone(); + let future_tx2 = future_tx1.clone_ref(py); R::spawn(async move { - let locals2 = locals.clone(); + let locals2 = Python::with_gil(|py| locals.clone_ref(py)); if let Err(e) = R::spawn(async move { let result = R::scope( - locals2.clone(), + Python::with_gil(|py| locals2.clone_ref(py)), Cancellable::new_with_cancel_rx(fut, cancel_rx), ) .await; @@ -990,7 +990,7 @@ where { let (cancel_tx, cancel_rx) = oneshot::channel(); - let py_fut = create_future(locals.event_loop.clone().into_bound(py))?; + let py_fut = create_future(locals.event_loop.clone_ref(py).into_bound(py))?; py_fut.call_method1( "add_done_callback", (PyDoneCallback { @@ -999,14 +999,14 @@ where )?; let future_tx1 = PyObject::from(py_fut.clone()); - let future_tx2 = future_tx1.clone(); + let future_tx2 = future_tx1.clone_ref(py); R::spawn_local(async move { - let locals2 = locals.clone(); + let locals2 = Python::with_gil(|py| locals.clone_ref(py)); if let Err(e) = R::spawn_local(async move { let result = R::scope_local( - locals2.clone(), + Python::with_gil(|py| locals2.clone_ref(py)), Cancellable::new_with_cancel_rx(fut, cancel_rx), ) .await; @@ -1446,27 +1446,12 @@ 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 - .get_or_init(|| Python::with_gil(|py| false.into_py(py))) - .clone() -} - trait Sender: Send + 'static { - fn send(&mut self, locals: TaskLocals, item: PyObject) -> PyResult; + fn send(&mut self, py: Python, locals: TaskLocals, item: PyObject) -> PyResult; fn close(&mut self) -> PyResult<()>; } -#[allow(dead_code)] +#[cfg(feature = "unstable-streams")] struct GenericSender where R: Runtime, @@ -1475,13 +1460,14 @@ where tx: mpsc::Sender, } +#[cfg(feature = "unstable-streams")] impl Sender for GenericSender where R: Runtime + ContextExt, { - fn send(&mut self, locals: TaskLocals, item: PyObject) -> PyResult { - match self.tx.try_send(item.clone()) { - Ok(_) => Ok(py_true()), + fn send(&mut self, py: Python, locals: TaskLocals, item: PyObject) -> PyResult { + match self.tx.try_send(item.clone_ref(py)) { + Ok(_) => Ok(true.into_py(py)), Err(e) => { if e.is_full() { let mut tx = self.tx.clone(); @@ -1490,19 +1476,19 @@ where future_into_py_with_locals::(py, locals, async move { if tx.flush().await.is_err() { // receiving side disconnected - return Ok(py_false()); + return Python::with_gil(|py| Ok(false.into_py(py))); } if tx.send(item).await.is_err() { // receiving side disconnected - return Ok(py_false()); + return Python::with_gil(|py| Ok(false.into_py(py))); } - Ok(py_true()) + Python::with_gil(|py| Ok(true.into_py(py))) })? .into(), ) }) } else { - Ok(py_false()) + Ok(false.into_py(py)) } } } @@ -1521,7 +1507,7 @@ struct SenderGlue { #[pymethods] impl SenderGlue { pub fn send(&mut self, item: PyObject) -> PyResult { - self.tx.send(self.locals.clone(), item) + Python::with_gil(|py| self.tx.send(py, self.locals.clone_ref(py), item)) } pub fn close(&mut self) -> PyResult<()> { self.tx.close() diff --git a/src/lib.rs b/src/lib.rs index e7b7453..b22f8bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -473,7 +473,7 @@ fn copy_context(py: Python) -> PyResult> { } /// Task-local data to store for Python conversions. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct TaskLocals { /// Track the event loop of the Python task event_loop: PyObject, @@ -510,12 +510,21 @@ impl TaskLocals { /// Get a reference to the event loop pub fn event_loop<'p>(&self, py: Python<'p>) -> Bound<'p, PyAny> { - self.event_loop.clone().into_bound(py) + self.event_loop.clone_ref(py).into_bound(py) } /// Get a reference to the python context pub fn context<'p>(&self, py: Python<'p>) -> Bound<'p, PyAny> { - self.context.clone().into_bound(py) + self.context.clone_ref(py).into_bound(py) + } + + /// Create a clone of the TaskLocals by incrementing the reference counters of the event loop and + /// contextvars. + pub fn clone_ref(&self, py: Python<'_>) -> Self { + Self { + event_loop: self.event_loop.clone_ref(py), + context: self.context.clone_ref(py), + } } } diff --git a/src/tokio.rs b/src/tokio.rs index c41cf89..3ee35bc 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -109,10 +109,12 @@ impl ContextExt for TokioRuntime { } fn get_task_locals() -> Option { - match TASK_LOCALS.try_with(|c| c.get().map(|locals| locals.clone())) { - Ok(locals) => locals, - Err(_) => None, - } + TASK_LOCALS + .try_with(|c| { + c.get() + .map(|locals| Python::with_gil(|py| locals.clone_ref(py))) + }) + .unwrap_or_default() } } From fd70e99f349f6433a196d0ad75a42274f8fa2354 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Tue, 8 Oct 2024 15:09:35 +0200 Subject: [PATCH 6/8] Fix tests --- README.md | 6 +++--- pytests/test_async_std_asyncio.rs | 4 ++-- pytests/tokio_asyncio/mod.rs | 4 ++-- src/lib.rs | 16 ++++++++-------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index f8b06ec..0d7c9bd 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ fn rust_sleep(py: Python) -> PyResult> { } #[pymodule] -fn my_async_module(py: Python, m: &PyModule) -> PyResult<()> { +fn my_async_module(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(rust_sleep, m)?)?; Ok(()) @@ -183,7 +183,7 @@ fn rust_sleep(py: Python) -> PyResult> { } #[pymodule] -fn my_async_module(py: Python, m: &PyModule) -> PyResult<()> { +fn my_async_module(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(rust_sleep, m)?)?; Ok(()) } @@ -453,7 +453,7 @@ fn rust_sleep(py: Python) -> PyResult> { } #[pymodule] -fn my_async_module(_py: Python, m: &PyModule) -> PyResult<()> { +fn my_async_module(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(rust_sleep, m)?)?; Ok(()) diff --git a/pytests/test_async_std_asyncio.rs b/pytests/test_async_std_asyncio.rs index 3314500..0f4afed 100644 --- a/pytests/test_async_std_asyncio.rs +++ b/pytests/test_async_std_asyncio.rs @@ -262,7 +262,7 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { /// This module is implemented in Rust. #[pymodule] -fn test_mod(_py: Python, m: &PyModule) -> PyResult<()> { +fn test_mod(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { #![allow(deprecated)] #[pyfunction(name = "sleep")] fn sleep_(py: Python) -> PyResult> { @@ -309,7 +309,7 @@ fn test_multiple_asyncio_run() -> PyResult<()> { } #[pymodule] -fn cvars_mod(_py: Python, m: &PyModule) -> PyResult<()> { +fn cvars_mod(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { #![allow(deprecated)] #[pyfunction] pub(crate) fn async_callback(py: Python, callback: PyObject) -> PyResult> { diff --git a/pytests/tokio_asyncio/mod.rs b/pytests/tokio_asyncio/mod.rs index 6a7d8fe..740619e 100644 --- a/pytests/tokio_asyncio/mod.rs +++ b/pytests/tokio_asyncio/mod.rs @@ -240,7 +240,7 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { /// This module is implemented in Rust. #[pymodule] -fn test_mod(_py: Python, m: &PyModule) -> PyResult<()> { +fn test_mod(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { #![allow(deprecated)] #[pyfunction(name = "sleep")] fn sleep_(py: Python) -> PyResult> { @@ -287,7 +287,7 @@ fn test_multiple_asyncio_run() -> PyResult<()> { } #[pymodule] -fn cvars_mod(_py: Python, m: &PyModule) -> PyResult<()> { +fn cvars_mod(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { #![allow(deprecated)] #[pyfunction] fn async_callback(py: Python, callback: PyObject) -> PyResult> { diff --git a/src/lib.rs b/src/lib.rs index b22f8bc..f8b2d55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,7 +93,7 @@ //! let locals = pyo3_async_runtimes::TaskLocals::with_running_loop(py)?.copy_context(py)?; //! //! // Convert the async move { } block to a Python awaitable -//! pyo3_async_runtimes::tokio::future_into_py_with_locals(py, locals.clone(), async move { +//! pyo3_async_runtimes::tokio::future_into_py_with_locals(py, locals.clone_ref(py), async move { //! let py_sleep = Python::with_gil(|py| { //! // Sometimes we need to call other async Python functions within //! // this future. In order for this to work, we need to track the @@ -112,7 +112,7 @@ //! //! # #[cfg(feature = "tokio-runtime")] //! #[pymodule] -//! fn my_mod(py: Python, m: &PyModule) -> PyResult<()> { +//! fn my_mod(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(sleep, m)?)?; //! Ok(()) //! } @@ -162,9 +162,9 @@ //! //! pyo3_async_runtimes::tokio::future_into_py_with_locals( //! py, -//! locals.clone(), +//! locals.clone_ref(py), //! // Store the current locals in task-local data -//! pyo3_async_runtimes::tokio::scope(locals.clone(), async move { +//! pyo3_async_runtimes::tokio::scope(locals.clone_ref(py), async move { //! let py_sleep = Python::with_gil(|py| { //! pyo3_async_runtimes::into_future_with_locals( //! // Now we can get the current locals through task-local data @@ -189,9 +189,9 @@ //! //! pyo3_async_runtimes::tokio::future_into_py_with_locals( //! py, -//! locals.clone(), +//! locals.clone_ref(py), //! // Store the current locals in task-local data -//! pyo3_async_runtimes::tokio::scope(locals.clone(), async move { +//! pyo3_async_runtimes::tokio::scope(locals.clone_ref(py), async move { //! let py_sleep = Python::with_gil(|py| { //! pyo3_async_runtimes::into_future_with_locals( //! &pyo3_async_runtimes::tokio::get_current_locals(py)?, @@ -210,7 +210,7 @@ //! //! # #[cfg(feature = "tokio-runtime")] //! #[pymodule] -//! fn my_mod(py: Python, m: &PyModule) -> PyResult<()> { +//! fn my_mod(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(sleep, m)?)?; //! m.add_function(wrap_pyfunction!(wrap_sleep, m)?)?; //! Ok(()) @@ -270,7 +270,7 @@ //! //! # #[cfg(feature = "tokio-runtime")] //! #[pymodule] -//! fn my_mod(py: Python, m: &PyModule) -> PyResult<()> { +//! fn my_mod(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(sleep, m)?)?; //! m.add_function(wrap_pyfunction!(wrap_sleep, m)?)?; //! Ok(()) From 47c41470a2c26ca4f4ea3c39dbdf10b71ba28002 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Fri, 11 Oct 2024 08:43:09 +0100 Subject: [PATCH 7/8] remove unneeded angle bracket --- src/async_std.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/async_std.rs b/src/async_std.rs index 199d472..e3d3c7b 100644 --- a/src/async_std.rs +++ b/src/async_std.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] From d4524690a9210c045ed17b2f0ccf05e74f45ed76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 07:46:13 +0000 Subject: [PATCH 8/8] Update async-channel requirement from 1.6 to 2.3 Updates the requirements on [async-channel](https://github.com/smol-rs/async-channel) to permit the latest version. - [Release notes](https://github.com/smol-rs/async-channel/releases) - [Changelog](https://github.com/smol-rs/async-channel/blob/master/CHANGELOG.md) - [Commits](https://github.com/smol-rs/async-channel/compare/v1.6.0...v2.3.1) --- updated-dependencies: - dependency-name: async-channel dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7d6f662..52ead6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,7 +114,7 @@ harness = false required-features = ["async-std-runtime", "testing"] [dependencies] -async-channel = { version = "1.6", optional = true } +async-channel = { version = "2.3", optional = true } clap = { version = "3.2", optional = true } futures = "0.3" inventory = { version = "0.3", optional = true }