From ed31a14f8645eecb31bb460c6d299ed87ed5adf3 Mon Sep 17 00:00:00 2001 From: Kevin King <4kevinking@gmail.com> Date: Fri, 17 May 2024 16:43:23 -0700 Subject: [PATCH] Upgrade to pyo3 0.21 Fix compilation errors Migrate off of deprecated methods Ignore must use false-positive --- Cargo.toml | 6 +- README.md | 26 ++--- examples/async_std.rs | 2 +- examples/tokio.rs | 2 +- examples/tokio_current_thread.rs | 2 +- examples/tokio_multi_thread.rs | 2 +- pytests/common/mod.rs | 12 +- pytests/test_async_std_asyncio.rs | 64 +++++----- pytests/test_async_std_run_forever.rs | 10 +- pytests/test_async_std_uvloop.rs | 4 +- pytests/test_race_condition_regression.rs | 6 +- pytests/test_tokio_current_thread_uvloop.rs | 4 +- pytests/test_tokio_multi_thread_uvloop.rs | 4 +- pytests/tokio_asyncio/mod.rs | 68 +++++------ pytests/tokio_run_forever/mod.rs | 10 +- src/async_std.rs | 60 +++++----- src/generic.rs | 122 +++++++++++--------- src/lib.rs | 84 +++++++------- src/tokio.rs | 60 +++++----- 19 files changed, 288 insertions(+), 260 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7427320..f3292d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pyo3-asyncio" description = "PyO3 utilities for Python's Asyncio library" -version = "0.20.0" +version = "0.21.0" authors = ["Andrew J Westlake "] readme = "README.md" keywords = ["pyo3", "python", "ffi", "async", "asyncio"] @@ -116,11 +116,11 @@ futures = "0.3" inventory = { version = "0.3", optional = true } once_cell = "1.14" pin-project-lite = "0.2" -pyo3 = "0.20" +pyo3 = "0.21" pyo3-asyncio-macros = { path = "pyo3-asyncio-macros", version = "=0.20.0", optional = true } [dev-dependencies] -pyo3 = { version = "0.20", features = ["macros"] } +pyo3 = { version = "0.21", features = ["macros"] } [dependencies.async-std] version = "1.12" diff --git a/README.md b/README.md index cd6cdb3..f7655e6 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ use pyo3::prelude::*; #[pyo3_asyncio::async_std::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::async_std::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) })?; @@ -95,7 +95,7 @@ use pyo3::prelude::*; #[pyo3_asyncio::tokio::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) })?; @@ -149,7 +149,7 @@ Export an async function that makes use of `async-std`: use pyo3::{prelude::*, wrap_pyfunction}; #[pyfunction] -fn rust_sleep(py: Python) -> PyResult<&PyAny> { +fn rust_sleep(py: Python) -> PyResult> { pyo3_asyncio::async_std::future_into_py(py, async { async_std::task::sleep(std::time::Duration::from_secs(1)).await; Ok(()) @@ -173,7 +173,7 @@ If you want to use `tokio` instead, here's what your module should look like: use pyo3::{prelude::*, wrap_pyfunction}; #[pyfunction] -fn rust_sleep(py: Python) -> PyResult<&PyAny> { +fn rust_sleep(py: Python) -> PyResult> { pyo3_asyncio::tokio::future_into_py(py, async { tokio::time::sleep(std::time::Duration::from_secs(1)).await; Ok(()) @@ -237,7 +237,7 @@ use pyo3::prelude::*; async fn main() -> PyResult<()> { let future = Python::with_gil(|py| -> PyResult<_> { // import the module containing the py_sleep function - let example = py.import("example")?; + let example = py.import_bound("example")?; // calling the py_sleep method like a normal function // returns a coroutine @@ -289,7 +289,7 @@ async fn rust_sleep() { } #[pyfunction] -fn call_rust_sleep(py: Python) -> PyResult<&PyAny> { +fn call_rust_sleep(py: Python) -> PyResult> { pyo3_asyncio::async_std::future_into_py(py, async move { rust_sleep().await; Ok(()) @@ -356,7 +356,7 @@ async fn main() -> PyResult<()> { // PyO3 is initialized - Ready to go let fut = Python::with_gil(|py| -> PyResult<_> { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::async_std::into_future( @@ -443,7 +443,7 @@ tokio = "1.9" use pyo3::{prelude::*, wrap_pyfunction}; #[pyfunction] -fn rust_sleep(py: Python) -> PyResult<&PyAny> { +fn rust_sleep(py: Python) -> PyResult> { pyo3_asyncio::tokio::future_into_py(py, async { tokio::time::sleep(std::time::Duration::from_secs(1)).await; Ok(()) @@ -504,7 +504,7 @@ fn main() -> PyResult<()> { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { - let uvloop = py.import("uvloop")?; + let uvloop = py.import_bound("uvloop")?; uvloop.call_method0("install")?; // store a reference for the assertion @@ -514,7 +514,7 @@ fn main() -> PyResult<()> { // verify that we are on a uvloop.Loop Python::with_gil(|py| -> PyResult<()> { assert!(uvloop - .as_ref(py) + .bind(py) .getattr("Loop")? .downcast::() .unwrap() @@ -601,7 +601,7 @@ To make things a bit easier, I decided to keep most of the old API alongside the pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; let event_loop = asyncio.call_method0("new_event_loop")?; asyncio.call_method1("set_event_loop", (event_loop,))?; @@ -614,11 +614,11 @@ To make things a bit easier, I decided to keep most of the old API alongside the // Stop the event loop manually Python::with_gil(|py| { event_loop_hdl - .as_ref(py) + .bind(py) .call_method1( "call_soon_threadsafe", (event_loop_hdl - .as_ref(py) + .bind(py) .getattr("stop") .unwrap(),), ) diff --git a/examples/async_std.rs b/examples/async_std.rs index ba7c8e7..ef58cef 100644 --- a/examples/async_std.rs +++ b/examples/async_std.rs @@ -3,7 +3,7 @@ use pyo3::prelude::*; #[pyo3_asyncio::async_std::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::async_std::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) diff --git a/examples/tokio.rs b/examples/tokio.rs index 794c43a..9fa0646 100644 --- a/examples/tokio.rs +++ b/examples/tokio.rs @@ -3,7 +3,7 @@ use pyo3::prelude::*; #[pyo3_asyncio::tokio::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) diff --git a/examples/tokio_current_thread.rs b/examples/tokio_current_thread.rs index 5b8819a..aa56b43 100644 --- a/examples/tokio_current_thread.rs +++ b/examples/tokio_current_thread.rs @@ -3,7 +3,7 @@ use pyo3::prelude::*; #[pyo3_asyncio::tokio::main(flavor = "current_thread")] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) diff --git a/examples/tokio_multi_thread.rs b/examples/tokio_multi_thread.rs index 0deb688..8af0de2 100644 --- a/examples/tokio_multi_thread.rs +++ b/examples/tokio_multi_thread.rs @@ -3,7 +3,7 @@ use pyo3::prelude::*; #[pyo3_asyncio::tokio::main(flavor = "multi_thread", worker_threads = 10)] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) diff --git a/pytests/common/mod.rs b/pytests/common/mod.rs index 241c5ef..e3fe86b 100644 --- a/pytests/common/mod.rs +++ b/pytests/common/mod.rs @@ -16,10 +16,10 @@ async def sleep_for_1s(sleep_for): pub(super) async fn test_into_future(event_loop: PyObject) -> PyResult<()> { let fut = Python::with_gil(|py| { let test_mod = - PyModule::from_code(py, TEST_MOD, "test_rust_coroutine/test_mod.py", "test_mod")?; + PyModule::from_code_bound(py, TEST_MOD, "test_rust_coroutine/test_mod.py", "test_mod")?; pyo3_asyncio::into_future_with_locals( - &TaskLocals::new(event_loop.as_ref(py)), + &TaskLocals::new(event_loop.into_bound(py)), test_mod.call_method1("py_sleep", (1.into_py(py),))?, ) })?; @@ -36,11 +36,11 @@ pub(super) fn test_blocking_sleep() -> PyResult<()> { pub(super) async fn test_other_awaitables(event_loop: PyObject) -> PyResult<()> { let fut = Python::with_gil(|py| { - let functools = py.import("functools")?; - let time = py.import("time")?; + let functools = py.import_bound("functools")?; + let time = py.import_bound("time")?; // spawn a blocking sleep in the threadpool executor - returns a task, not a coroutine - let task = event_loop.as_ref(py).call_method1( + let task = event_loop.bind(py).call_method1( "run_in_executor", ( py.None(), @@ -48,7 +48,7 @@ pub(super) async fn test_other_awaitables(event_loop: PyObject) -> PyResult<()> ), )?; - pyo3_asyncio::into_future_with_locals(&TaskLocals::new(event_loop.as_ref(py)), task) + pyo3_asyncio::into_future_with_locals(&TaskLocals::new(event_loop.into_bound(py)), task) })?; fut.await?; diff --git a/pytests/test_async_std_asyncio.rs b/pytests/test_async_std_asyncio.rs index 9139c06..7c06f3b 100644 --- a/pytests/test_async_std_asyncio.rs +++ b/pytests/test_async_std_asyncio.rs @@ -18,7 +18,7 @@ use pyo3_asyncio::TaskLocals; use futures::{StreamExt, TryStreamExt}; #[pyfunction] -fn sleep<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { +fn sleep<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult> { let secs = secs.extract()?; pyo3_asyncio::async_std::future_into_py(py, async move { @@ -30,11 +30,11 @@ fn sleep<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { #[pyo3_asyncio::async_std::test] async fn test_future_into_py() -> PyResult<()> { let fut = Python::with_gil(|py| { - let sleeper_mod = PyModule::new(py, "rust_sleeper")?; + let sleeper_mod = PyModule::new_bound(py, "rust_sleeper")?; sleeper_mod.add_wrapped(wrap_pyfunction!(sleep))?; - let test_mod = PyModule::from_code( + let test_mod = PyModule::from_code_bound( py, common::TEST_MOD, "test_future_into_py_mod.py", @@ -53,13 +53,15 @@ async fn test_future_into_py() -> PyResult<()> { #[pyo3_asyncio::async_std::test] async fn test_async_sleep() -> PyResult<()> { - let asyncio = - Python::with_gil(|py| py.import("asyncio").map(|asyncio| PyObject::from(asyncio)))?; + let asyncio = Python::with_gil(|py| { + py.import_bound("asyncio") + .map(|asyncio| PyObject::from(asyncio)) + })?; task::sleep(Duration::from_secs(1)).await; Python::with_gil(|py| { - pyo3_asyncio::async_std::into_future(asyncio.as_ref(py).call_method1("sleep", (1.0,))?) + pyo3_asyncio::async_std::into_future(asyncio.bind(py).call_method1("sleep", (1.0,))?) })? .await?; @@ -146,14 +148,14 @@ async fn test_cancel() -> PyResult<()> { })?; if let Err(e) = Python::with_gil(|py| -> PyResult<_> { - py_future.as_ref(py).call_method0("cancel")?; - pyo3_asyncio::async_std::into_future(py_future.as_ref(py)) + py_future.bind(py).call_method0("cancel")?; + pyo3_asyncio::async_std::into_future(py_future.into_bound(py)) })? .await { Python::with_gil(|py| -> PyResult<()> { - assert!(e.value(py).is_instance( - py.import("asyncio")? + assert!(e.value_bound(py).is_instance( + py.import_bound("asyncio")? .getattr("CancelledError")? .downcast::() .unwrap() @@ -186,7 +188,7 @@ async def gen(): #[pyo3_asyncio::async_std::test] async fn test_async_gen_v1() -> PyResult<()> { let stream = Python::with_gil(|py| { - let test_mod = PyModule::from_code( + let test_mod = PyModule::from_code_bound( py, ASYNC_STD_TEST_MOD, "test_rust_coroutine/async_std_test_mod.py", @@ -197,7 +199,7 @@ async fn test_async_gen_v1() -> PyResult<()> { })?; let vals = stream - .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.as_ref(py).extract()?) })) + .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) .try_collect::>() .await?; @@ -209,7 +211,7 @@ async fn test_async_gen_v1() -> PyResult<()> { #[pyo3_asyncio::async_std::test] fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { let locals = Python::with_gil(|py| -> PyResult { - Ok(TaskLocals::new(event_loop.as_ref(py)).copy_context(py)?) + Ok(TaskLocals::new(event_loop.into_bound(py)).copy_context(py)?) })?; async_std::task::block_on(pyo3_asyncio::async_std::scope_local(locals, async { let completed = Arc::new(Mutex::new(false)); @@ -226,14 +228,14 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { })?; if let Err(e) = Python::with_gil(|py| -> PyResult<_> { - py_future.as_ref(py).call_method0("cancel")?; - pyo3_asyncio::async_std::into_future(py_future.as_ref(py)) + py_future.bind(py).call_method0("cancel")?; + pyo3_asyncio::async_std::into_future(py_future.into_bound(py)) })? .await { Python::with_gil(|py| -> PyResult<()> { - assert!(e.value(py).is_instance( - py.import("asyncio")? + assert!(e.value_bound(py).is_instance( + py.import_bound("asyncio")? .getattr("CancelledError")? .downcast::() .unwrap() @@ -258,7 +260,7 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { fn test_mod(_py: Python, m: &PyModule) -> PyResult<()> { #![allow(deprecated)] #[pyfunction(name = "sleep")] - fn sleep_(py: Python) -> PyResult<&PyAny> { + fn sleep_(py: Python) -> PyResult> { pyo3_asyncio::async_std::future_into_py(py, async move { async_std::task::sleep(Duration::from_millis(500)).await; Ok(()) @@ -290,13 +292,13 @@ fn test_multiple_asyncio_run() -> PyResult<()> { })?; let d = [ - ("asyncio", py.import("asyncio")?.into()), + ("asyncio", py.import_bound("asyncio")?.into()), ("test_mod", wrap_pymodule!(test_mod)(py)), ] - .into_py_dict(py); + .into_py_dict_bound(py); - py.run(MULTI_ASYNCIO_CODE, Some(d), None)?; - py.run(MULTI_ASYNCIO_CODE, Some(d), None)?; + py.run_bound(MULTI_ASYNCIO_CODE, Some(&d), None)?; + py.run_bound(MULTI_ASYNCIO_CODE, Some(&d), None)?; Ok(()) }) } @@ -305,10 +307,10 @@ fn test_multiple_asyncio_run() -> PyResult<()> { fn cvars_mod(_py: Python, m: &PyModule) -> PyResult<()> { #![allow(deprecated)] #[pyfunction] - pub(crate) fn async_callback(py: Python, callback: PyObject) -> PyResult<&PyAny> { + pub(crate) fn async_callback(py: Python, callback: PyObject) -> PyResult> { pyo3_asyncio::async_std::future_into_py(py, async move { Python::with_gil(|py| { - pyo3_asyncio::async_std::into_future(callback.as_ref(py).call0()?) + pyo3_asyncio::async_std::into_future(callback.bind(py).call0()?) })? .await?; @@ -325,7 +327,7 @@ fn cvars_mod(_py: Python, m: &PyModule) -> PyResult<()> { #[pyo3_asyncio::async_std::test] async fn test_async_gen_v2() -> PyResult<()> { let stream = Python::with_gil(|py| { - let test_mod = PyModule::from_code( + let test_mod = PyModule::from_code_bound( py, ASYNC_STD_TEST_MOD, "test_rust_coroutine/async_std_test_mod.py", @@ -336,7 +338,7 @@ async fn test_async_gen_v2() -> PyResult<()> { })?; let vals = stream - .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.as_ref(py).extract()?) })) + .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) .try_collect::>() .await?; @@ -362,14 +364,14 @@ asyncio.run(main()) fn test_contextvars() -> PyResult<()> { Python::with_gil(|py| { let d = [ - ("asyncio", py.import("asyncio")?.into()), - ("contextvars", py.import("contextvars")?.into()), + ("asyncio", py.import_bound("asyncio")?.into()), + ("contextvars", py.import_bound("contextvars")?.into()), ("cvars_mod", wrap_pymodule!(cvars_mod)(py)), ] - .into_py_dict(py); + .into_py_dict_bound(py); - py.run(CONTEXTVARS_CODE, Some(d), None)?; - py.run(CONTEXTVARS_CODE, Some(d), None)?; + py.run_bound(CONTEXTVARS_CODE, Some(&d), None)?; + py.run_bound(CONTEXTVARS_CODE, Some(&d), None)?; Ok(()) }) } diff --git a/pytests/test_async_std_run_forever.rs b/pytests/test_async_std_run_forever.rs index 0f88173..ecc76f9 100644 --- a/pytests/test_async_std_run_forever.rs +++ b/pytests/test_async_std_run_forever.rs @@ -12,23 +12,23 @@ fn main() { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; let event_loop = asyncio.call_method0("new_event_loop")?; - asyncio.call_method1("set_event_loop", (event_loop,))?; + asyncio.call_method1("set_event_loop", (&event_loop,))?; - let event_loop_hdl = PyObject::from(event_loop); + let event_loop_hdl = PyObject::from(event_loop.clone()); async_std::task::spawn(async move { async_std::task::sleep(Duration::from_secs(1)).await; Python::with_gil(|py| { event_loop_hdl - .as_ref(py) + .bind(py) .call_method1( "call_soon_threadsafe", (event_loop_hdl - .as_ref(py) + .bind(py) .getattr("stop") .map_err(|e| dump_err(py, e)) .unwrap(),), diff --git a/pytests/test_async_std_uvloop.rs b/pytests/test_async_std_uvloop.rs index 92a75fc..77049cd 100644 --- a/pytests/test_async_std_uvloop.rs +++ b/pytests/test_async_std_uvloop.rs @@ -4,7 +4,7 @@ fn main() -> pyo3::PyResult<()> { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { - let uvloop = py.import("uvloop")?; + let uvloop = py.import_bound("uvloop")?; uvloop.call_method0("install")?; // store a reference for the assertion @@ -15,7 +15,7 @@ fn main() -> pyo3::PyResult<()> { Python::with_gil(|py| -> PyResult<()> { assert!(pyo3_asyncio::async_std::get_current_loop(py)?.is_instance( uvloop - .as_ref(py) + .bind(py) .getattr("Loop")? .downcast::() .unwrap() diff --git a/pytests/test_race_condition_regression.rs b/pytests/test_race_condition_regression.rs index d2e6b9e..ce1c244 100644 --- a/pytests/test_race_condition_regression.rs +++ b/pytests/test_race_condition_regression.rs @@ -1,7 +1,7 @@ use pyo3::{prelude::*, wrap_pyfunction}; #[pyfunction] -fn sleep<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { +fn sleep<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult> { let secs = secs.extract()?; pyo3_asyncio::async_std::future_into_py(py, async move { @@ -49,11 +49,11 @@ fn main() -> pyo3::PyResult<()> { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| -> PyResult<()> { - let sleeper_mod = PyModule::new(py, "rust_sleeper")?; + let sleeper_mod = PyModule::new_bound(py, "rust_sleeper")?; sleeper_mod.add_wrapped(wrap_pyfunction!(sleep))?; - let test_mod = PyModule::from_code( + let test_mod = PyModule::from_code_bound( py, RACE_CONDITION_REGRESSION_TEST, "race_condition_regression_test.py", diff --git a/pytests/test_tokio_current_thread_uvloop.rs b/pytests/test_tokio_current_thread_uvloop.rs index 5484a42..b917775 100644 --- a/pytests/test_tokio_current_thread_uvloop.rs +++ b/pytests/test_tokio_current_thread_uvloop.rs @@ -13,7 +13,7 @@ fn main() -> pyo3::PyResult<()> { }); Python::with_gil(|py| { - let uvloop = py.import("uvloop")?; + let uvloop = py.import_bound("uvloop")?; uvloop.call_method0("install")?; // store a reference for the assertion @@ -24,7 +24,7 @@ fn main() -> pyo3::PyResult<()> { Python::with_gil(|py| -> PyResult<()> { assert!(pyo3_asyncio::tokio::get_current_loop(py)?.is_instance( uvloop - .as_ref(py) + .bind(py) .getattr("Loop")? .downcast::() .unwrap() diff --git a/pytests/test_tokio_multi_thread_uvloop.rs b/pytests/test_tokio_multi_thread_uvloop.rs index 70a47a9..8cebb1c 100644 --- a/pytests/test_tokio_multi_thread_uvloop.rs +++ b/pytests/test_tokio_multi_thread_uvloop.rs @@ -5,7 +5,7 @@ fn main() -> pyo3::PyResult<()> { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { - let uvloop = py.import("uvloop")?; + let uvloop = py.import_bound("uvloop")?; uvloop.call_method0("install")?; // store a reference for the assertion @@ -16,7 +16,7 @@ fn main() -> pyo3::PyResult<()> { Python::with_gil(|py| -> PyResult<()> { assert!(pyo3_asyncio::tokio::get_current_loop(py)?.is_instance( uvloop - .as_ref(py) + .bind(py) .getattr("Loop")? .downcast::() .unwrap() diff --git a/pytests/tokio_asyncio/mod.rs b/pytests/tokio_asyncio/mod.rs index f8a14ee..1ea12d9 100644 --- a/pytests/tokio_asyncio/mod.rs +++ b/pytests/tokio_asyncio/mod.rs @@ -17,7 +17,7 @@ use futures::{StreamExt, TryStreamExt}; use crate::common; #[pyfunction] -fn sleep<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { +fn sleep<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult> { let secs = secs.extract()?; pyo3_asyncio::tokio::future_into_py(py, async move { @@ -29,11 +29,11 @@ fn sleep<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { #[pyo3_asyncio::tokio::test] async fn test_future_into_py() -> PyResult<()> { let fut = Python::with_gil(|py| { - let sleeper_mod = PyModule::new(py, "rust_sleeper")?; + let sleeper_mod = PyModule::new_bound(py, "rust_sleeper")?; sleeper_mod.add_wrapped(wrap_pyfunction!(sleep))?; - let test_mod = PyModule::from_code( + let test_mod = PyModule::from_code_bound( py, common::TEST_MOD, "test_future_into_py_mod.py", @@ -52,13 +52,15 @@ async fn test_future_into_py() -> PyResult<()> { #[pyo3_asyncio::tokio::test] async fn test_async_sleep() -> PyResult<()> { - let asyncio = - Python::with_gil(|py| py.import("asyncio").map(|asyncio| PyObject::from(asyncio)))?; + let asyncio = Python::with_gil(|py| { + py.import_bound("asyncio") + .map(|asyncio| PyObject::from(asyncio)) + })?; tokio::time::sleep(Duration::from_secs(1)).await; Python::with_gil(|py| { - pyo3_asyncio::tokio::into_future(asyncio.as_ref(py).call_method1("sleep", (1.0,))?) + pyo3_asyncio::tokio::into_future(asyncio.bind(py).call_method1("sleep", (1.0,))?) })? .await?; @@ -95,7 +97,7 @@ fn test_local_future_into_py(event_loop: PyObject) -> PyResult<()> { #[allow(deprecated)] let py_future = pyo3_asyncio::tokio::local_future_into_py_with_locals( py, - TaskLocals::new(event_loop.as_ref(py)), + TaskLocals::new(event_loop.bind(py).clone()), async move { tokio::time::sleep(Duration::from_secs(*non_send_secs)).await; Ok(()) @@ -103,7 +105,7 @@ fn test_local_future_into_py(event_loop: PyObject) -> PyResult<()> { )?; pyo3_asyncio::into_future_with_locals( - &TaskLocals::new(event_loop.as_ref(py)), + &TaskLocals::new(event_loop.into_bound(py)), py_future, ) })? @@ -149,14 +151,14 @@ async fn test_cancel() -> PyResult<()> { })?; if let Err(e) = Python::with_gil(|py| -> PyResult<_> { - py_future.as_ref(py).call_method0("cancel")?; - pyo3_asyncio::tokio::into_future(py_future.as_ref(py)) + py_future.bind(py).call_method0("cancel")?; + pyo3_asyncio::tokio::into_future(py_future.into_bound(py)) })? .await { Python::with_gil(|py| -> PyResult<()> { - assert!(e.value(py).is_instance( - py.import("asyncio")? + assert!(e.value_bound(py).is_instance( + py.import_bound("asyncio")? .getattr("CancelledError")? .downcast::() .unwrap() @@ -179,7 +181,7 @@ async fn test_cancel() -> PyResult<()> { #[allow(deprecated)] fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { let locals = Python::with_gil(|py| -> PyResult { - Ok(TaskLocals::new(event_loop.as_ref(py)).copy_context(py)?) + Ok(TaskLocals::new(event_loop.into_bound(py)).copy_context(py)?) })?; tokio::task::LocalSet::new().block_on( @@ -199,14 +201,14 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { })?; if let Err(e) = Python::with_gil(|py| -> PyResult<_> { - py_future.as_ref(py).call_method0("cancel")?; - pyo3_asyncio::tokio::into_future(py_future.as_ref(py)) + py_future.bind(py).call_method0("cancel")?; + pyo3_asyncio::tokio::into_future(py_future.into_bound(py)) })? .await { Python::with_gil(|py| -> PyResult<()> { - assert!(e.value(py).is_instance( - py.import("asyncio")? + assert!(e.value_bound(py).is_instance( + py.import_bound("asyncio")? .getattr("CancelledError")? .downcast::() .unwrap() @@ -233,7 +235,7 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { fn test_mod(_py: Python, m: &PyModule) -> PyResult<()> { #![allow(deprecated)] #[pyfunction(name = "sleep")] - fn sleep_(py: Python) -> PyResult<&PyAny> { + fn sleep_(py: Python) -> PyResult> { pyo3_asyncio::tokio::future_into_py(py, async move { tokio::time::sleep(Duration::from_millis(500)).await; Ok(()) @@ -265,13 +267,13 @@ fn test_multiple_asyncio_run() -> PyResult<()> { })?; let d = [ - ("asyncio", py.import("asyncio")?.into()), + ("asyncio", py.import_bound("asyncio")?.into()), ("test_mod", wrap_pymodule!(test_mod)(py)), ] - .into_py_dict(py); + .into_py_dict_bound(py); - py.run(TEST_CODE, Some(d), None)?; - py.run(TEST_CODE, Some(d), None)?; + py.run_bound(TEST_CODE, Some(&d), None)?; + py.run_bound(TEST_CODE, Some(&d), None)?; Ok(()) }) } @@ -280,9 +282,9 @@ fn test_multiple_asyncio_run() -> PyResult<()> { fn cvars_mod(_py: Python, m: &PyModule) -> PyResult<()> { #![allow(deprecated)] #[pyfunction] - fn async_callback(py: Python, callback: PyObject) -> PyResult<&PyAny> { + fn async_callback(py: Python, callback: PyObject) -> PyResult> { pyo3_asyncio::tokio::future_into_py(py, async move { - Python::with_gil(|py| pyo3_asyncio::tokio::into_future(callback.as_ref(py).call0()?))? + Python::with_gil(|py| pyo3_asyncio::tokio::into_future(callback.bind(py).call0()?))? .await?; Ok(()) @@ -308,7 +310,7 @@ async def gen(): #[pyo3_asyncio::tokio::test] async fn test_async_gen_v1() -> PyResult<()> { let stream = Python::with_gil(|py| { - let test_mod = PyModule::from_code( + let test_mod = PyModule::from_code_bound( py, TOKIO_TEST_MOD, "test_rust_coroutine/tokio_test_mod.py", @@ -319,7 +321,7 @@ async fn test_async_gen_v1() -> PyResult<()> { })?; let vals = stream - .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.as_ref(py).extract()?) })) + .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) .try_collect::>() .await?; @@ -332,7 +334,7 @@ async fn test_async_gen_v1() -> PyResult<()> { #[pyo3_asyncio::tokio::test] async fn test_async_gen_v2() -> PyResult<()> { let stream = Python::with_gil(|py| { - let test_mod = PyModule::from_code( + let test_mod = PyModule::from_code_bound( py, TOKIO_TEST_MOD, "test_rust_coroutine/tokio_test_mod.py", @@ -343,7 +345,7 @@ async fn test_async_gen_v2() -> PyResult<()> { })?; let vals = stream - .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.as_ref(py).extract()?) })) + .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) .try_collect::>() .await?; @@ -369,14 +371,14 @@ asyncio.run(main()) fn test_contextvars() -> PyResult<()> { Python::with_gil(|py| { let d = [ - ("asyncio", py.import("asyncio")?.into()), - ("contextvars", py.import("contextvars")?.into()), + ("asyncio", py.import_bound("asyncio")?.into()), + ("contextvars", py.import_bound("contextvars")?.into()), ("cvars_mod", wrap_pymodule!(cvars_mod)(py)), ] - .into_py_dict(py); + .into_py_dict_bound(py); - py.run(CONTEXTVARS_CODE, Some(d), None)?; - py.run(CONTEXTVARS_CODE, Some(d), None)?; + py.run_bound(CONTEXTVARS_CODE, Some(&d), None)?; + py.run_bound(CONTEXTVARS_CODE, Some(&d), None)?; Ok(()) }) } diff --git a/pytests/tokio_run_forever/mod.rs b/pytests/tokio_run_forever/mod.rs index 270622a..1bf4758 100644 --- a/pytests/tokio_run_forever/mod.rs +++ b/pytests/tokio_run_forever/mod.rs @@ -10,23 +10,23 @@ fn dump_err(py: Python<'_>, e: PyErr) { pub(super) fn test_main() { Python::with_gil(|py| { - let asyncio = py.import("asyncio")?; + let asyncio = py.import_bound("asyncio")?; let event_loop = asyncio.call_method0("new_event_loop")?; - asyncio.call_method1("set_event_loop", (event_loop,))?; + asyncio.call_method1("set_event_loop", (&event_loop,))?; - let event_loop_hdl = PyObject::from(event_loop); + let event_loop_hdl = PyObject::from(event_loop.clone()); pyo3_asyncio::tokio::get_runtime().spawn(async move { tokio::time::sleep(Duration::from_secs(1)).await; Python::with_gil(|py| { event_loop_hdl - .as_ref(py) + .bind(py) .call_method1( "call_soon_threadsafe", (event_loop_hdl - .as_ref(py) + .bind(py) .getattr("stop") .map_err(|e| dump_err(py, e)) .unwrap(),), diff --git a/src/async_std.rs b/src/async_std.rs index c8d0861..f7225a2 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -144,7 +144,7 @@ where /// This function first checks if the runtime has a task-local reference to the Python event loop. /// If not, it calls [`get_running_loop`](`crate::get_running_loop`) to get the event loop /// associated with the current OS thread. -pub fn get_current_loop(py: Python) -> PyResult<&PyAny> { +pub fn get_current_loop(py: Python) -> PyResult> { generic::get_current_loop::(py) } @@ -174,7 +174,7 @@ pub fn get_current_locals(py: Python) -> PyResult { /// # pyo3::prepare_freethreaded_python(); /// # /// # Python::with_gil(|py| -> PyResult<()> { -/// # let event_loop = py.import("asyncio")?.call_method0("new_event_loop")?; +/// # let event_loop = py.import_bound("asyncio")?.call_method0("new_event_loop")?; /// pyo3_asyncio::async_std::run_until_complete(event_loop, async move { /// async_std::task::sleep(Duration::from_secs(1)).await; /// Ok(()) @@ -182,12 +182,12 @@ pub fn get_current_locals(py: Python) -> PyResult { /// # Ok(()) /// # }).unwrap(); /// ``` -pub fn run_until_complete(event_loop: &PyAny, fut: F) -> PyResult +pub fn run_until_complete(event_loop: Bound, fut: F) -> PyResult where F: Future> + Send + 'static, T: Send + Sync + 'static, { - generic::run_until_complete::(event_loop, fut) + generic::run_until_complete::(&event_loop, fut) } /// Run the event loop until the given Future completes @@ -258,7 +258,7 @@ where /// /// /// Awaitable sleep function /// #[pyfunction] -/// fn sleep_for<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { +/// fn sleep_for<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult> { /// let secs = secs.extract()?; /// pyo3_asyncio::async_std::future_into_py_with_locals( /// py, @@ -270,7 +270,11 @@ where /// ) /// } /// ``` -pub fn future_into_py_with_locals(py: Python, locals: TaskLocals, fut: F) -> PyResult<&PyAny> +pub fn future_into_py_with_locals( + py: Python, + locals: TaskLocals, + fut: F, +) -> PyResult> where F: Future> + Send + 'static, T: IntoPy, @@ -308,7 +312,7 @@ where /// /// /// Awaitable sleep function /// #[pyfunction] -/// fn sleep_for<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { +/// fn sleep_for<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult> { /// let secs = secs.extract()?; /// pyo3_asyncio::async_std::future_into_py(py, async move { /// async_std::task::sleep(Duration::from_secs(secs)).await; @@ -316,7 +320,7 @@ where /// }) /// } /// ``` -pub fn future_into_py(py: Python, fut: F) -> PyResult<&PyAny> +pub fn future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + Send + 'static, T: IntoPy, @@ -355,7 +359,7 @@ where /// /// /// Awaitable non-send sleep function /// #[pyfunction] -/// fn sleep_for(py: Python, secs: u64) -> PyResult<&PyAny> { +/// fn sleep_for(py: Python, secs: u64) -> PyResult> { /// // Rc is non-send so it cannot be passed into pyo3_asyncio::async_std::future_into_py /// let secs = Rc::new(secs); /// Ok(pyo3_asyncio::async_std::local_future_into_py_with_locals( @@ -391,7 +395,7 @@ pub fn local_future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, -) -> PyResult<&PyAny> +) -> PyResult> where F: Future> + 'static, T: IntoPy, @@ -429,7 +433,7 @@ where /// /// /// Awaitable non-send sleep function /// #[pyfunction] -/// fn sleep_for(py: Python, secs: u64) -> PyResult<&PyAny> { +/// fn sleep_for(py: Python, secs: u64) -> PyResult> { /// // Rc is non-send so it cannot be passed into pyo3_asyncio::async_std::future_into_py /// let secs = Rc::new(secs); /// pyo3_asyncio::async_std::local_future_into_py(py, async move { @@ -457,7 +461,7 @@ where note = "Questionable whether these conversions have real-world utility (see https://github.com/awestlake87/pyo3-asyncio/issues/59#issuecomment-1008038497 and let me know if you disagree!)" )] #[allow(deprecated)] -pub fn local_future_into_py(py: Python, fut: F) -> PyResult<&PyAny> +pub fn local_future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + 'static, T: IntoPy, @@ -492,7 +496,7 @@ where /// async fn py_sleep(seconds: f32) -> PyResult<()> { /// let test_mod = Python::with_gil(|py| -> PyResult { /// Ok( -/// PyModule::from_code( +/// PyModule::from_code_bound( /// py, /// PYTHON_CODE, /// "test_into_future/test_mod.py", @@ -506,14 +510,16 @@ where /// pyo3_asyncio::async_std::into_future( /// test_mod /// .call_method1(py, "py_sleep", (seconds.into_py(py),))? -/// .as_ref(py), +/// .bind(py), /// ) /// })? /// .await?; /// Ok(()) /// } /// ``` -pub fn into_future(awaitable: &PyAny) -> PyResult> + Send> { +pub fn into_future( + awaitable: Bound, +) -> PyResult> + Send> { generic::into_future::(awaitable) } @@ -544,7 +550,7 @@ pub fn into_future(awaitable: &PyAny) -> PyResult PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -555,7 +561,7 @@ pub fn into_future(awaitable: &PyAny) -> PyResult PyResult { Ok(item?.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -568,7 +574,7 @@ pub fn into_future(awaitable: &PyAny) -> PyResult( - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult> + 'static> { generic::into_stream_v1::(gen) } @@ -601,7 +607,7 @@ pub fn into_stream_v1<'p>( /// # #[pyo3_asyncio::async_std::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -615,7 +621,7 @@ pub fn into_stream_v1<'p>( /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -629,7 +635,7 @@ pub fn into_stream_v1<'p>( #[cfg(feature = "unstable-streams")] pub fn into_stream_with_locals_v1<'p>( locals: TaskLocals, - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult> + 'static> { generic::into_stream_with_locals_v1::(locals, gen) } @@ -662,7 +668,7 @@ pub fn into_stream_with_locals_v1<'p>( /// # #[pyo3_asyncio::async_std::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -676,7 +682,7 @@ pub fn into_stream_with_locals_v1<'p>( /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -690,7 +696,7 @@ pub fn into_stream_with_locals_v1<'p>( #[cfg(feature = "unstable-streams")] pub fn into_stream_with_locals_v2<'p>( locals: TaskLocals, - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult + 'static> { generic::into_stream_with_locals_v2::(locals, gen) } @@ -722,7 +728,7 @@ pub fn into_stream_with_locals_v2<'p>( /// # #[pyo3_asyncio::async_std::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -733,7 +739,7 @@ pub fn into_stream_with_locals_v2<'p>( /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -746,7 +752,7 @@ pub fn into_stream_with_locals_v2<'p>( /// ``` #[cfg(feature = "unstable-streams")] pub fn into_stream_v2<'p>( - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult + 'static> { generic::into_stream_v2::(gen) } diff --git a/src/generic.rs b/src/generic.rs index 3afc462..8e4e871 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -87,12 +87,12 @@ pub trait LocalContextExt: Runtime { /// This function first checks if the runtime has a task-local reference to the Python event loop. /// If not, it calls [`get_running_loop`](crate::get_running_loop`) to get the event loop associated /// with the current OS thread. -pub fn get_current_loop(py: Python) -> PyResult<&PyAny> +pub fn get_current_loop(py: Python) -> PyResult> where R: ContextExt, { if let Some(locals) = R::get_task_locals() { - Ok(locals.event_loop.into_ref(py)) + Ok(locals.event_loop.into_bound(py)) } else { get_running_loop(py) } @@ -181,7 +181,7 @@ where /// # use pyo3::prelude::*; /// # /// # Python::with_gil(|py| -> PyResult<()> { -/// # let event_loop = py.import("asyncio")?.call_method0("new_event_loop")?; +/// # let event_loop = py.import_bound("asyncio")?.call_method0("new_event_loop")?; /// # #[cfg(feature = "tokio-runtime")] /// pyo3_asyncio::generic::run_until_complete::(event_loop, async move { /// tokio::time::sleep(Duration::from_secs(1)).await; @@ -190,7 +190,7 @@ where /// # Ok(()) /// # }).unwrap(); /// ``` -pub fn run_until_complete(event_loop: &PyAny, fut: F) -> PyResult +pub fn run_until_complete(event_loop: &Bound, fut: F) -> PyResult where R: Runtime + ContextExt, F: Future> + Send + 'static, @@ -201,7 +201,7 @@ where let result_rx = Arc::clone(&result_tx); let coro = future_into_py_with_locals::( py, - TaskLocals::new(event_loop).copy_context(py)?, + TaskLocals::new(event_loop.clone()).copy_context(py)?, async move { let val = fut.await?; if let Ok(mut result) = result_tx.lock() { @@ -306,15 +306,15 @@ where { let event_loop = asyncio(py)?.call_method0("new_event_loop")?; - let result = run_until_complete::(event_loop, fut); + let result = run_until_complete::(&event_loop, fut); close(event_loop)?; result } -fn cancelled(future: &PyAny) -> PyResult { - future.getattr("cancelled")?.call0()?.is_true() +fn cancelled(future: &Bound) -> PyResult { + future.getattr("cancelled")?.call0()?.is_truthy() } #[pyclass] @@ -322,7 +322,12 @@ struct CheckedCompletor; #[pymethods] impl CheckedCompletor { - fn __call__(&self, future: &PyAny, complete: &PyAny, value: &PyAny) -> PyResult<()> { + fn __call__( + &self, + future: &Bound, + complete: &Bound, + value: &Bound, + ) -> PyResult<()> { if cancelled(future)? { return Ok(()); } @@ -333,15 +338,19 @@ impl CheckedCompletor { } } -fn set_result(event_loop: &PyAny, future: &PyAny, result: PyResult) -> PyResult<()> { +fn set_result( + event_loop: &Bound, + future: &Bound, + result: PyResult, +) -> PyResult<()> { let py = event_loop.py(); - let none = py.None().into_ref(py); + let none = py.None().into_bound(py); let (complete, val) = match result { Ok(val) => (future.getattr("set_result")?, val.into_py(py)), Err(err) => (future.getattr("set_exception")?, err.into_py(py)), }; - call_soon_threadsafe(event_loop, none, (CheckedCompletor, future, complete, val))?; + call_soon_threadsafe(event_loop, &none, (CheckedCompletor, future, complete, val))?; Ok(()) } @@ -430,7 +439,7 @@ fn set_result(event_loop: &PyAny, future: &PyAny, result: PyResult) -> /// async fn py_sleep(seconds: f32) -> PyResult<()> { /// let test_mod = Python::with_gil(|py| -> PyResult { /// Ok( -/// PyModule::from_code( +/// PyModule::from_code_bound( /// py, /// PYTHON_CODE, /// "test_into_future/test_mod.py", @@ -444,7 +453,7 @@ fn set_result(event_loop: &PyAny, future: &PyAny, result: PyResult) -> /// pyo3_asyncio::generic::into_future::( /// test_mod /// .call_method1(py, "py_sleep", (seconds.into_py(py),))? -/// .as_ref(py), +/// .into_bound(py), /// ) /// })? /// .await?; @@ -452,7 +461,7 @@ fn set_result(event_loop: &PyAny, future: &PyAny, result: PyResult) -> /// } /// ``` pub fn into_future( - awaitable: &PyAny, + awaitable: Bound, ) -> PyResult> + Send> where R: Runtime + ContextExt, @@ -551,7 +560,7 @@ where /// /// /// Awaitable sleep function /// #[pyfunction] -/// fn sleep_for<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { +/// fn sleep_for<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult> { /// let secs = secs.extract()?; /// pyo3_asyncio::generic::future_into_py_with_locals::( /// py, @@ -563,11 +572,12 @@ where /// ) /// } /// ``` +#[allow(unused_must_use)] pub fn future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, -) -> PyResult<&PyAny> +) -> PyResult> where R: Runtime + ContextExt, F: Future> + Send + 'static, @@ -575,7 +585,7 @@ where { let (cancel_tx, cancel_rx) = oneshot::channel(); - let py_fut = create_future(locals.event_loop.clone().into_ref(py))?; + let py_fut = create_future(locals.event_loop.clone().into_bound(py))?; py_fut.call_method1( "add_done_callback", (PyDoneCallback { @@ -583,7 +593,7 @@ where },), )?; - let future_tx1 = PyObject::from(py_fut); + let future_tx1 = PyObject::from(py_fut.clone()); let future_tx2 = future_tx1.clone(); R::spawn(async move { @@ -597,7 +607,7 @@ where .await; Python::with_gil(move |py| { - if cancelled(future_tx1.as_ref(py)) + if cancelled(future_tx1.bind(py)) .map_err(dump_err(py)) .unwrap_or(false) { @@ -605,8 +615,8 @@ where } let _ = set_result( - locals2.event_loop(py), - future_tx1.as_ref(py), + &locals2.event_loop(py), + future_tx1.bind(py), result.map(|val| val.into_py(py)), ) .map_err(dump_err(py)); @@ -616,7 +626,7 @@ where { if e.is_panic() { Python::with_gil(move |py| { - if cancelled(future_tx2.as_ref(py)) + if cancelled(future_tx2.bind(py)) .map_err(dump_err(py)) .unwrap_or(false) { @@ -628,8 +638,8 @@ where get_panic_message(&e.into_panic()) ); let _ = set_result( - locals.event_loop.as_ref(py), - future_tx2.as_ref(py), + locals.event_loop.bind(py), + future_tx2.bind(py), Err(RustPanic::new_err(panic_message)), ) .map_err(dump_err(py)); @@ -721,7 +731,7 @@ struct PyDoneCallback { #[pymethods] impl PyDoneCallback { - pub fn __call__(&mut self, fut: &PyAny) -> PyResult<()> { + pub fn __call__(&mut self, fut: &Bound) -> PyResult<()> { let py = fut.py(); if cancelled(fut).map_err(dump_err(py)).unwrap_or(false) { @@ -822,7 +832,7 @@ impl PyDoneCallback { /// /// /// Awaitable sleep function /// #[pyfunction] -/// fn sleep_for<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { +/// fn sleep_for<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult> { /// let secs = secs.extract()?; /// pyo3_asyncio::generic::future_into_py::(py, async move { /// MyCustomRuntime::sleep(Duration::from_secs(secs)).await; @@ -830,7 +840,7 @@ impl PyDoneCallback { /// }) /// } /// ``` -pub fn future_into_py(py: Python, fut: F) -> PyResult<&PyAny> +pub fn future_into_py(py: Python, fut: F) -> PyResult> where R: Runtime + ContextExt, F: Future> + Send + 'static, @@ -949,7 +959,7 @@ where /// /// /// Awaitable sleep function /// #[pyfunction] -/// fn sleep_for(py: Python, secs: u64) -> PyResult<&PyAny> { +/// fn sleep_for(py: Python, secs: u64) -> PyResult> { /// // Rc is !Send so it cannot be passed into pyo3_asyncio::generic::future_into_py /// let secs = Rc::new(secs); /// @@ -967,11 +977,12 @@ where since = "0.18.0", note = "Questionable whether these conversions have real-world utility (see https://github.com/awestlake87/pyo3-asyncio/issues/59#issuecomment-1008038497 and let me know if you disagree!)" )] +#[allow(unused_must_use)] pub fn local_future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, -) -> PyResult<&PyAny> +) -> PyResult> where R: Runtime + SpawnLocalExt + LocalContextExt, F: Future> + 'static, @@ -979,7 +990,7 @@ where { let (cancel_tx, cancel_rx) = oneshot::channel(); - let py_fut = create_future(locals.event_loop.clone().into_ref(py))?; + let py_fut = create_future(locals.event_loop.clone().into_bound(py))?; py_fut.call_method1( "add_done_callback", (PyDoneCallback { @@ -987,7 +998,7 @@ where },), )?; - let future_tx1 = PyObject::from(py_fut); + let future_tx1 = PyObject::from(py_fut.clone()); let future_tx2 = future_tx1.clone(); R::spawn_local(async move { @@ -1001,7 +1012,7 @@ where .await; Python::with_gil(move |py| { - if cancelled(future_tx1.as_ref(py)) + if cancelled(future_tx1.bind(py)) .map_err(dump_err(py)) .unwrap_or(false) { @@ -1009,8 +1020,8 @@ where } let _ = set_result( - locals2.event_loop.as_ref(py), - future_tx1.as_ref(py), + locals2.event_loop.bind(py), + future_tx1.bind(py), result.map(|val| val.into_py(py)), ) .map_err(dump_err(py)); @@ -1020,7 +1031,7 @@ where { if e.is_panic() { Python::with_gil(move |py| { - if cancelled(future_tx2.as_ref(py)) + if cancelled(future_tx2.bind(py)) .map_err(dump_err(py)) .unwrap_or(false) { @@ -1032,8 +1043,8 @@ where get_panic_message(&e.into_panic()) ); let _ = set_result( - locals.event_loop.as_ref(py), - future_tx2.as_ref(py), + locals.event_loop.bind(py), + future_tx2.bind(py), Err(RustPanic::new_err(panic_message)), ) .map_err(dump_err(py)); @@ -1153,7 +1164,7 @@ where /// /// /// Awaitable sleep function /// #[pyfunction] -/// fn sleep_for(py: Python, secs: u64) -> PyResult<&PyAny> { +/// fn sleep_for(py: Python, secs: u64) -> PyResult> { /// // Rc is !Send so it cannot be passed into pyo3_asyncio::generic::future_into_py /// let secs = Rc::new(secs); /// @@ -1168,7 +1179,7 @@ where note = "Questionable whether these conversions have real-world utility (see https://github.com/awestlake87/pyo3-asyncio/issues/59#issuecomment-1008038497 and let me know if you disagree!)" )] #[allow(deprecated)] -pub fn local_future_into_py(py: Python, fut: F) -> PyResult<&PyAny> +pub fn local_future_into_py(py: Python, fut: F) -> PyResult> where R: Runtime + ContextExt + SpawnLocalExt + LocalContextExt, F: Future> + 'static, @@ -1257,7 +1268,7 @@ where /// /// # async fn test_async_gen() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -1271,7 +1282,7 @@ where /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -1281,9 +1292,10 @@ 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>( locals: TaskLocals, - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult> + 'static> where R: Runtime, @@ -1294,7 +1306,7 @@ where R::spawn(async move { loop { let fut = Python::with_gil(|py| -> PyResult<_> { - into_future_with_locals(&locals, anext.as_ref(py).call0()?) + into_future_with_locals(&locals, anext.bind(py).call0()?) }); let item = match fut { Ok(fut) => match fut.await { @@ -1404,7 +1416,7 @@ where /// /// # async fn test_async_gen() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -1415,7 +1427,7 @@ where /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -1426,7 +1438,7 @@ where /// ``` #[cfg(feature = "unstable-streams")] pub fn into_stream_v1<'p, R>( - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult> + 'static> where R: Runtime + ContextExt, @@ -1611,7 +1623,7 @@ async def forward(gen, sender): /// /// # async fn test_async_gen() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -1625,7 +1637,7 @@ async def forward(gen, sender): /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -1637,7 +1649,7 @@ async def forward(gen, sender): #[cfg(feature = "unstable-streams")] pub fn into_stream_with_locals_v2<'p, R>( locals: TaskLocals, - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult + 'static> where R: Runtime + ContextExt, @@ -1646,7 +1658,7 @@ where let py = gen.py(); let glue = GLUE_MOD .get_or_try_init(|| -> PyResult { - Ok(PyModule::from_code( + Ok(PyModule::from_code_bound( py, STREAM_GLUE, "pyo3_asyncio/pyo3_asyncio_glue.py", @@ -1654,7 +1666,7 @@ where )? .into()) })? - .as_ref(py); + .bind(py); let (tx, rx) = mpsc::channel(10); @@ -1759,7 +1771,7 @@ where /// /// # async fn test_async_gen() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -1770,7 +1782,7 @@ where /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -1781,7 +1793,7 @@ where /// ``` #[cfg(feature = "unstable-streams")] pub fn into_stream_v2<'p, R>( - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult + 'static> where R: Runtime + ContextExt, diff --git a/src/lib.rs b/src/lib.rs index 1570522..d661f37 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,7 +88,7 @@ //! //! # #[cfg(feature = "tokio-runtime")] //! #[pyfunction] -//! fn sleep(py: Python) -> PyResult<&PyAny> { +//! fn sleep(py: Python) -> PyResult> { //! // Construct the task locals structure with the current running loop and context //! let locals = pyo3_asyncio::TaskLocals::with_running_loop(py)?.copy_context(py)?; //! @@ -100,7 +100,7 @@ //! // event loop from earlier. //! pyo3_asyncio::into_future_with_locals( //! &locals, -//! py.import("asyncio")?.call_method1("sleep", (1,))? +//! py.import_bound("asyncio")?.call_method1("sleep", (1,))? //! ) //! })?; //! @@ -155,7 +155,7 @@ //! //! # #[cfg(feature = "tokio-runtime")] //! #[pyfunction] -//! fn sleep(py: Python) -> PyResult<&PyAny> { +//! fn sleep(py: Python) -> PyResult> { //! // get the current event loop through task-local data //! // OR `asyncio.get_running_loop` and `contextvars.copy_context` //! let locals = pyo3_asyncio::tokio::get_current_locals(py)?; @@ -169,7 +169,7 @@ //! pyo3_asyncio::into_future_with_locals( //! // Now we can get the current locals through task-local data //! &pyo3_asyncio::tokio::get_current_locals(py)?, -//! py.import("asyncio")?.call_method1("sleep", (1,))? +//! py.import_bound("asyncio")?.call_method1("sleep", (1,))? //! ) //! })?; //! @@ -182,7 +182,7 @@ //! //! # #[cfg(feature = "tokio-runtime")] //! #[pyfunction] -//! fn wrap_sleep(py: Python) -> PyResult<&PyAny> { +//! fn wrap_sleep(py: Python) -> PyResult> { //! // get the current event loop through task-local data //! // OR `asyncio.get_running_loop` and `contextvars.copy_context` //! let locals = pyo3_asyncio::tokio::get_current_locals(py)?; @@ -240,11 +240,11 @@ //! //! # #[cfg(feature = "tokio-runtime")] //! #[pyfunction] -//! fn sleep(py: Python) -> PyResult<&PyAny> { +//! fn sleep(py: Python) -> PyResult> { //! pyo3_asyncio::tokio::future_into_py(py, async move { //! let py_sleep = Python::with_gil(|py| { //! pyo3_asyncio::tokio::into_future( -//! py.import("asyncio")?.call_method1("sleep", (1,))? +//! py.import_bound("asyncio")?.call_method1("sleep", (1,))? //! ) //! })?; //! @@ -256,7 +256,7 @@ //! //! # #[cfg(feature = "tokio-runtime")] //! #[pyfunction] -//! fn wrap_sleep(py: Python) -> PyResult<&PyAny> { +//! fn wrap_sleep(py: Python) -> PyResult> { //! pyo3_asyncio::tokio::future_into_py(py, async move { //! let py_sleep = Python::with_gil(|py| { //! pyo3_asyncio::tokio::into_future(sleep(py)?) @@ -363,8 +363,8 @@ pub mod err; pub mod generic; #[pymodule] -fn pyo3_asyncio(py: Python, m: &PyModule) -> PyResult<()> { - m.add("RustPanic", py.get_type::())?; +fn pyo3_asyncio(py: Python, m: &Bound) -> PyResult<()> { + m.add("RustPanic", py.get_type_bound::())?; Ok(()) } @@ -408,20 +408,20 @@ static CONTEXTVARS: OnceCell = OnceCell::new(); static ENSURE_FUTURE: OnceCell = OnceCell::new(); static GET_RUNNING_LOOP: OnceCell = OnceCell::new(); -fn ensure_future<'p>(py: Python<'p>, awaitable: &'p PyAny) -> PyResult<&'p PyAny> { +fn ensure_future<'p>(py: Python<'p>, awaitable: &Bound<'p, PyAny>) -> PyResult> { ENSURE_FUTURE .get_or_try_init(|| -> PyResult { Ok(asyncio(py)?.getattr("ensure_future")?.into()) })? - .as_ref(py) + .bind(py) .call1((awaitable,)) } -fn create_future(event_loop: &PyAny) -> PyResult<&PyAny> { +fn create_future(event_loop: Bound) -> PyResult> { event_loop.call_method0("create_future") } -fn close(event_loop: &PyAny) -> PyResult<()> { +fn close(event_loop: Bound) -> PyResult<()> { event_loop.call_method1( "run_until_complete", (event_loop.call_method0("shutdown_asyncgens")?,), @@ -440,16 +440,16 @@ fn close(event_loop: &PyAny) -> PyResult<()> { Ok(()) } -fn asyncio(py: Python) -> PyResult<&PyAny> { +fn asyncio(py: Python) -> PyResult<&Bound> { ASYNCIO - .get_or_try_init(|| Ok(py.import("asyncio")?.into())) - .map(|asyncio| asyncio.as_ref(py)) + .get_or_try_init(|| Ok(py.import_bound("asyncio")?.into())) + .map(|asyncio| asyncio.bind(py)) } /// Get a reference to the Python Event Loop from Rust /// /// Equivalent to `asyncio.get_running_loop()` in Python 3.7+. -pub fn get_running_loop(py: Python) -> PyResult<&PyAny> { +pub fn get_running_loop(py: Python) -> PyResult> { // Ideally should call get_running_loop, but calls get_event_loop for compatibility when // get_running_loop is not available. GET_RUNNING_LOOP @@ -458,17 +458,17 @@ pub fn get_running_loop(py: Python) -> PyResult<&PyAny> { Ok(asyncio.getattr("get_running_loop")?.into()) })? - .as_ref(py) + .bind(py) .call0() } -fn contextvars(py: Python) -> PyResult<&PyAny> { +fn contextvars(py: Python) -> PyResult<&Bound> { Ok(CONTEXTVARS - .get_or_try_init(|| py.import("contextvars").map(|m| m.into()))? - .as_ref(py)) + .get_or_try_init(|| py.import_bound("contextvars").map(|m| m.into()))? + .bind(py)) } -fn copy_context(py: Python) -> PyResult<&PyAny> { +fn copy_context(py: Python) -> PyResult> { contextvars(py)?.call_method0("copy_context") } @@ -483,10 +483,10 @@ pub struct TaskLocals { impl TaskLocals { /// At a minimum, TaskLocals must store the event loop. - pub fn new(event_loop: &PyAny) -> Self { + pub fn new(event_loop: Bound) -> Self { Self { - event_loop: event_loop.into(), context: event_loop.py().None(), + event_loop: event_loop.into(), } } @@ -496,7 +496,7 @@ impl TaskLocals { } /// Manually provide the contextvars for the current task. - pub fn with_context(self, context: &PyAny) -> Self { + pub fn with_context(self, context: Bound) -> Self { Self { context: context.into(), ..self @@ -509,13 +509,13 @@ impl TaskLocals { } /// Get a reference to the event loop - pub fn event_loop<'p>(&self, py: Python<'p>) -> &'p PyAny { - self.event_loop.clone().into_ref(py) + pub fn event_loop<'p>(&self, py: Python<'p>) -> Bound<'p, PyAny> { + self.event_loop.clone().into_bound(py) } /// Get a reference to the python context - pub fn context<'p>(&self, py: Python<'p>) -> &'p PyAny { - self.context.clone().into_ref(py) + pub fn context<'p>(&self, py: Python<'p>) -> Bound<'p, PyAny> { + self.context.clone().into_bound(py) } } @@ -527,7 +527,7 @@ struct PyTaskCompleter { #[pymethods] impl PyTaskCompleter { #[pyo3(signature = (task))] - pub fn __call__(&mut self, task: &PyAny) -> PyResult<()> { + pub fn __call__(&mut self, task: &Bound) -> PyResult<()> { debug_assert!(task.call_method0("done")?.extract()?); let result = match task.call_method0("result") { Ok(val) => Ok(val.into()), @@ -558,7 +558,7 @@ struct PyEnsureFuture { impl PyEnsureFuture { pub fn __call__(&mut self) -> PyResult<()> { Python::with_gil(|py| { - let task = ensure_future(py, self.awaitable.as_ref(py))?; + let task = ensure_future(py, self.awaitable.bind(py))?; let on_complete = PyTaskCompleter { tx: self.tx.take() }; task.call_method1("add_done_callback", (on_complete,))?; @@ -568,16 +568,16 @@ impl PyEnsureFuture { } fn call_soon_threadsafe( - event_loop: &PyAny, - context: &PyAny, + event_loop: &Bound, + context: &Bound, args: impl IntoPy>, ) -> PyResult<()> { let py = event_loop.py(); - let kwargs = PyDict::new(py); + let kwargs = PyDict::new_bound(py); kwargs.set_item("context", context)?; - event_loop.call_method("call_soon_threadsafe", args, Some(kwargs))?; + event_loop.call_method("call_soon_threadsafe", args, Some(&kwargs))?; Ok(()) } @@ -610,7 +610,7 @@ fn call_soon_threadsafe( /// async fn py_sleep(seconds: f32) -> PyResult<()> { /// let test_mod = Python::with_gil(|py| -> PyResult { /// Ok( -/// PyModule::from_code( +/// PyModule::from_code_bound( /// py, /// PYTHON_CODE, /// "test_into_future/test_mod.py", @@ -625,7 +625,7 @@ fn call_soon_threadsafe( /// &pyo3_asyncio::tokio::get_current_locals(py)?, /// test_mod /// .call_method1(py, "py_sleep", (seconds.into_py(py),))? -/// .as_ref(py), +/// .bind(py), /// ) /// })? /// .await?; @@ -634,14 +634,14 @@ fn call_soon_threadsafe( /// ``` pub fn into_future_with_locals( locals: &TaskLocals, - awaitable: &PyAny, + awaitable: Bound, ) -> PyResult> + Send> { let py = awaitable.py(); let (tx, rx) = oneshot::channel(); call_soon_threadsafe( - locals.event_loop(py), - locals.context(py), + &locals.event_loop(py), + &locals.context(py), (PyEnsureFuture { awaitable: awaitable.into(), tx: Some(tx), @@ -652,7 +652,7 @@ pub fn into_future_with_locals( match rx.await { Ok(item) => item, Err(_) => Python::with_gil(|py| { - Err(PyErr::from_value( + Err(PyErr::from_value_bound( asyncio(py)?.call_method0("CancelledError")?, )) }), diff --git a/src/tokio.rs b/src/tokio.rs index 804b2a6..8bde8a0 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -158,7 +158,7 @@ where /// This function first checks if the runtime has a task-local reference to the Python event loop. /// If not, it calls [`get_running_loop`](`crate::get_running_loop`) to get the event loop /// associated with the current OS thread. -pub fn get_current_loop(py: Python) -> PyResult<&PyAny> { +pub fn get_current_loop(py: Python) -> PyResult> { generic::get_current_loop::(py) } @@ -219,7 +219,7 @@ fn multi_thread() -> Builder { /// # /// # pyo3::prepare_freethreaded_python(); /// # Python::with_gil(|py| -> PyResult<()> { -/// # let event_loop = py.import("asyncio")?.call_method0("new_event_loop")?; +/// # let event_loop = py.import_bound("asyncio")?.call_method0("new_event_loop")?; /// pyo3_asyncio::tokio::run_until_complete(event_loop, async move { /// tokio::time::sleep(Duration::from_secs(1)).await; /// Ok(()) @@ -227,12 +227,12 @@ fn multi_thread() -> Builder { /// # Ok(()) /// # }).unwrap(); /// ``` -pub fn run_until_complete(event_loop: &PyAny, fut: F) -> PyResult +pub fn run_until_complete(event_loop: Bound, fut: F) -> PyResult where F: Future> + Send + 'static, T: Send + Sync + 'static, { - generic::run_until_complete::(event_loop, fut) + generic::run_until_complete::(&event_loop, fut) } /// Run the event loop until the given Future completes @@ -300,7 +300,7 @@ where /// /// /// Awaitable sleep function /// #[pyfunction] -/// fn sleep_for<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { +/// fn sleep_for<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult> { /// let secs = secs.extract()?; /// pyo3_asyncio::tokio::future_into_py_with_locals( /// py, @@ -312,7 +312,11 @@ where /// ) /// } /// ``` -pub fn future_into_py_with_locals(py: Python, locals: TaskLocals, fut: F) -> PyResult<&PyAny> +pub fn future_into_py_with_locals( + py: Python, + locals: TaskLocals, + fut: F, +) -> PyResult> where F: Future> + Send + 'static, T: IntoPy, @@ -350,7 +354,7 @@ where /// /// /// Awaitable sleep function /// #[pyfunction] -/// fn sleep_for<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> { +/// fn sleep_for<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult> { /// let secs = secs.extract()?; /// pyo3_asyncio::tokio::future_into_py(py, async move { /// tokio::time::sleep(Duration::from_secs(secs)).await; @@ -358,7 +362,7 @@ where /// }) /// } /// ``` -pub fn future_into_py(py: Python, fut: F) -> PyResult<&PyAny> +pub fn future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + Send + 'static, T: IntoPy, @@ -397,7 +401,7 @@ where /// /// /// Awaitable non-send sleep function /// #[pyfunction] -/// fn sleep_for(py: Python, secs: u64) -> PyResult<&PyAny> { +/// fn sleep_for(py: Python, secs: u64) -> PyResult> { /// // Rc is non-send so it cannot be passed into pyo3_asyncio::tokio::future_into_py /// let secs = Rc::new(secs); /// @@ -449,7 +453,7 @@ pub fn local_future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, -) -> PyResult<&PyAny> +) -> PyResult> where F: Future> + 'static, T: IntoPy, @@ -487,7 +491,7 @@ where /// /// /// Awaitable non-send sleep function /// #[pyfunction] -/// fn sleep_for(py: Python, secs: u64) -> PyResult<&PyAny> { +/// fn sleep_for(py: Python, secs: u64) -> PyResult> { /// // Rc is non-send so it cannot be passed into pyo3_asyncio::tokio::future_into_py /// let secs = Rc::new(secs); /// pyo3_asyncio::tokio::local_future_into_py(py, async move { @@ -530,7 +534,7 @@ where note = "Questionable whether these conversions have real-world utility (see https://github.com/awestlake87/pyo3-asyncio/issues/59#issuecomment-1008038497 and let me know if you disagree!)" )] #[allow(deprecated)] -pub fn local_future_into_py(py: Python, fut: F) -> PyResult<&PyAny> +pub fn local_future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + 'static, T: IntoPy, @@ -565,7 +569,7 @@ where /// async fn py_sleep(seconds: f32) -> PyResult<()> { /// let test_mod = Python::with_gil(|py| -> PyResult { /// Ok( -/// PyModule::from_code( +/// PyModule::from_code_bound( /// py, /// PYTHON_CODE, /// "test_into_future/test_mod.py", @@ -579,14 +583,16 @@ where /// pyo3_asyncio::tokio::into_future( /// test_mod /// .call_method1(py, "py_sleep", (seconds.into_py(py),))? -/// .as_ref(py), +/// .bind(py), /// ) /// })? /// .await?; /// Ok(()) /// } /// ``` -pub fn into_future(awaitable: &PyAny) -> PyResult> + Send> { +pub fn into_future( + awaitable: Bound, +) -> PyResult> + Send> { generic::into_future::(awaitable) } @@ -618,7 +624,7 @@ pub fn into_future(awaitable: &PyAny) -> PyResult PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -632,7 +638,7 @@ pub fn into_future(awaitable: &PyAny) -> PyResult PyResult { Ok(item?.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -646,7 +652,7 @@ pub fn into_future(awaitable: &PyAny) -> PyResult( locals: TaskLocals, - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult> + 'static> { generic::into_stream_with_locals_v1::(locals, gen) } @@ -678,7 +684,7 @@ pub fn into_stream_with_locals_v1<'p>( /// # #[pyo3_asyncio::tokio::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -689,7 +695,7 @@ pub fn into_stream_with_locals_v1<'p>( /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -702,7 +708,7 @@ pub fn into_stream_with_locals_v1<'p>( /// ``` #[cfg(feature = "unstable-streams")] pub fn into_stream_v1<'p>( - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult> + 'static> { generic::into_stream_v1::(gen) } @@ -735,7 +741,7 @@ pub fn into_stream_v1<'p>( /// # #[pyo3_asyncio::tokio::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -749,7 +755,7 @@ pub fn into_stream_v1<'p>( /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -763,7 +769,7 @@ pub fn into_stream_v1<'p>( #[cfg(feature = "unstable-streams")] pub fn into_stream_with_locals_v2<'p>( locals: TaskLocals, - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult + 'static> { generic::into_stream_with_locals_v2::(locals, gen) } @@ -795,7 +801,7 @@ pub fn into_stream_with_locals_v2<'p>( /// # #[pyo3_asyncio::tokio::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code( +/// let test_mod = PyModule::from_code_bound( /// py, /// TEST_MOD, /// "test_rust_coroutine/test_mod.py", @@ -806,7 +812,7 @@ pub fn into_stream_with_locals_v2<'p>( /// })?; /// /// let vals = stream -/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.as_ref(py).extract()?) })) +/// .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) /// .try_collect::>() /// .await?; /// @@ -819,7 +825,7 @@ pub fn into_stream_with_locals_v2<'p>( /// ``` #[cfg(feature = "unstable-streams")] pub fn into_stream_v2<'p>( - gen: &'p PyAny, + gen: Bound<'p, PyAny>, ) -> PyResult + 'static> { generic::into_stream_v2::(gen) }