From 3ce009763aebe768aa51d45cf4b825c7f60b8d88 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 18 Nov 2024 11:23:36 +0000 Subject: [PATCH 01/10] Bump to 0.23 --- Cargo.toml | 8 ++++---- README.md | 22 +++++++++++----------- pyo3-async-runtimes-macros/Cargo.toml | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 00fe4e0..c5bb6b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pyo3-async-runtimes" description = "PyO3 bridges from Rust runtimes to Python's Asyncio library" -version = "0.22.0" +version = "0.23.0" authors = [ "Andrew J Westlake ", "David Hewitt ", @@ -120,11 +120,11 @@ futures = "0.3" inventory = { version = "0.3", optional = true } once_cell = "1.14" pin-project-lite = "0.2" -pyo3 = "0.22" -pyo3-async-runtimes-macros = { path = "pyo3-async-runtimes-macros", version = "=0.22.0", optional = true } +pyo3 = "0.23" +pyo3-async-runtimes-macros = { path = "pyo3-async-runtimes-macros", version = "=0.23.0", optional = true } [dev-dependencies] -pyo3 = { version = "0.22", features = ["macros"] } +pyo3 = { version = "0.23", features = ["macros"] } [dependencies.async-std] version = "1.12" diff --git a/README.md b/README.md index 1eb3376..0b95bee 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ Here we initialize the runtime, import Python's `asyncio` library and run the gi ```toml # Cargo.toml dependencies [dependencies] -pyo3 = { version = "0.22" } -pyo3-async-runtimes = { version = "0.22", features = ["attributes", "async-std-runtime"] } +pyo3 = { version = "0.23" } +pyo3-async-runtimes = { version = "0.23", features = ["attributes", "async-std-runtime"] } async-std = "1.13" ``` @@ -84,8 +84,8 @@ attribute. ```toml # Cargo.toml dependencies [dependencies] -pyo3 = { version = "0.22" } -pyo3-async-runtimes = { version = "0.22", features = ["attributes", "tokio-runtime"] } +pyo3 = { version = "0.23" } +pyo3-async-runtimes = { version = "0.23", features = ["attributes", "tokio-runtime"] } tokio = "1.40" ``` @@ -130,8 +130,8 @@ For `async-std`: ```toml [dependencies] -pyo3 = { version = "0.22", features = ["extension-module"] } -pyo3-async-runtimes = { version = "0.22", features = ["async-std-runtime"] } +pyo3 = { version = "0.23", features = ["extension-module"] } +pyo3-async-runtimes = { version = "0.23", features = ["async-std-runtime"] } async-std = "1.13" ``` @@ -140,7 +140,7 @@ For `tokio`: ```toml [dependencies] pyo3 = { version = "0.20", features = ["extension-module"] } -pyo3-async-runtimes = { version = "0.22", features = ["tokio-runtime"] } +pyo3-async-runtimes = { version = "0.23", features = ["tokio-runtime"] } tokio = "1.40" ``` @@ -434,8 +434,8 @@ name = "my_async_module" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.22", features = ["extension-module"] } -pyo3-async-runtimes = { version = "0.22", features = ["tokio-runtime"] } +pyo3 = { version = "0.23", features = ["extension-module"] } +pyo3-async-runtimes = { version = "0.23", features = ["tokio-runtime"] } async-std = "1.13" tokio = "1.40" ``` @@ -494,8 +494,8 @@ event loop before we can install the `uvloop` policy. ```toml [dependencies] async-std = "1.13" -pyo3 = "0.22" -pyo3-async-runtimes = { version = "0.22", features = ["async-std-runtime"] } +pyo3 = "0.23" +pyo3-async-runtimes = { version = "0.23", features = ["async-std-runtime"] } ``` ```rust no_run diff --git a/pyo3-async-runtimes-macros/Cargo.toml b/pyo3-async-runtimes-macros/Cargo.toml index dee21df..91f1b15 100644 --- a/pyo3-async-runtimes-macros/Cargo.toml +++ b/pyo3-async-runtimes-macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pyo3-async-runtimes-macros" description = "Proc Macro Attributes for `pyo3-async-runtimes`" -version = "0.22.0" +version = "0.23.0" authors = [ "Andrew J Westlake ", "David Hewitt ", From 0af51f86bb3d4b287055f0649b3791da78320c4e Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 18 Nov 2024 11:53:31 +0000 Subject: [PATCH 02/10] Attempt to bump to 0.23 --- src/async_std.rs | 18 ++++++++-------- src/generic.rs | 56 ++++++++++++++++++++++++++++-------------------- src/lib.rs | 24 ++++++++++----------- src/testing.rs | 2 +- src/tokio.rs | 18 ++++++++-------- 5 files changed, 64 insertions(+), 54 deletions(-) diff --git a/src/async_std.rs b/src/async_std.rs index 80b0053..32e5990 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -9,7 +9,7 @@ //! //! ```toml //! [dependencies.pyo3-async-runtimes] -//! version = "0.22" +//! version = "0.23" //! features = ["unstable-streams"] //! ``` @@ -272,14 +272,14 @@ where /// ) /// } /// ``` -pub fn future_into_py_with_locals( +pub fn future_into_py_with_locals<'py, F, T>( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + Send + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { generic::future_into_py_with_locals::(py, locals, fut) } @@ -322,10 +322,10 @@ where /// }) /// } /// ``` -pub fn future_into_py(py: Python, fut: F) -> PyResult> +pub fn future_into_py<'py, F, T>(py: Python, fut: F) -> PyResult> where F: Future> + Send + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { generic::future_into_py::(py, fut) } @@ -393,14 +393,14 @@ 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_with_locals( +pub fn local_future_into_py_with_locals<'py, F, T>( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { generic::local_future_into_py_with_locals::(py, locals, fut) } @@ -463,10 +463,10 @@ 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> +pub fn local_future_into_py<'py, F, T>(py: Python, fut: F) -> PyResult> where F: Future> + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { generic::local_future_into_py::(py, fut) } diff --git a/src/generic.rs b/src/generic.rs index 759e3f5..3eb3d62 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -9,11 +9,12 @@ //! //! ```toml //! [dependencies.pyo3-async-runtimes] -//! version = "0.22" +//! version = "0.23" //! features = ["unstable-streams"] //! ``` use std::{ + ffi::CString, future::Future, pin::Pin, sync::{Arc, Mutex}, @@ -31,6 +32,7 @@ use futures::{channel::mpsc, SinkExt}; use once_cell::sync::OnceCell; use pin_project_lite::pin_project; use pyo3::prelude::*; +use pyo3::BoundObject; #[cfg(feature = "unstable-streams")] use std::marker::PhantomData; @@ -347,8 +349,11 @@ fn set_result( 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)), + Ok(val) => (future.getattr("set_result")?, val.into_pyobject(py)?), + Err(err) => ( + future.getattr("set_exception")?, + err.into_pyobject(py)?.into_any(), + ), }; call_soon_threadsafe(event_loop, &none, (CheckedCompletor, future, complete, val))?; @@ -573,7 +578,7 @@ where /// } /// ``` #[allow(unused_must_use)] -pub fn future_into_py_with_locals( +pub fn future_into_py_with_locals<'py, R, F, T>( py: Python, locals: TaskLocals, fut: F, @@ -581,7 +586,7 @@ pub fn future_into_py_with_locals( where R: Runtime + ContextExt, F: Future> + Send + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { let (cancel_tx, cancel_rx) = oneshot::channel(); @@ -617,7 +622,7 @@ where let _ = set_result( &locals2.event_loop(py), future_tx1.bind(py), - result.map(|val| val.into_py(py)), + result.map(|val| val.into_pyobject(py).unwrap()), ) .map_err(dump_err(py)); }); @@ -686,10 +691,10 @@ impl Cancellable { } } -impl Future for Cancellable +impl<'py, F, T> Future for Cancellable where F: Future>, - T: IntoPy, + T: IntoPyObject<'py>, { type Output = F::Output; @@ -840,11 +845,11 @@ impl PyDoneCallback { /// }) /// } /// ``` -pub fn future_into_py(py: Python, fut: F) -> PyResult> +pub fn future_into_py<'py, R, F, T>(py: Python, fut: F) -> PyResult> where R: Runtime + ContextExt, F: Future> + Send + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { future_into_py_with_locals::(py, get_current_locals::(py)?, fut) } @@ -978,7 +983,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(unused_must_use)] -pub fn local_future_into_py_with_locals( +pub fn local_future_into_py_with_locals<'py, R, F, T>( py: Python, locals: TaskLocals, fut: F, @@ -986,7 +991,7 @@ pub fn local_future_into_py_with_locals( where R: Runtime + SpawnLocalExt + LocalContextExt, F: Future> + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { let (cancel_tx, cancel_rx) = oneshot::channel(); @@ -1179,11 +1184,11 @@ 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> +pub fn local_future_into_py<'py, R, F, T>(py: Python, fut: F) -> PyResult> where R: Runtime + ContextExt + SpawnLocalExt + LocalContextExt, F: Future> + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { local_future_into_py_with_locals::(py, get_current_locals::(py)?, fut) } @@ -1502,15 +1507,20 @@ where #[pyclass] struct SenderGlue { locals: TaskLocals, - tx: Box, + tx: Arc>, } #[pymethods] impl SenderGlue { pub fn send(&mut self, item: PyObject) -> PyResult { - Python::with_gil(|py| self.tx.send(py, self.locals.clone_ref(py), item)) + Python::with_gil(|py| { + self.tx + .lock() + .unwrap() + .send(py, self.locals.clone_ref(py), item) + }) } pub fn close(&mut self) -> PyResult<()> { - self.tx.close() + self.tx.lock().unwrap().close() } } @@ -1648,11 +1658,11 @@ where let py = gen.py(); let glue = GLUE_MOD .get_or_try_init(|| -> PyResult { - Ok(PyModule::from_code_bound( + Ok(PyModule::from_code( py, - STREAM_GLUE, - "pyo3_async_runtimes/pyo3_async_runtimes_glue.py", - "pyo3_async_runtimes_glue", + &CString::new(STREAM_GLUE).unwrap(), + &CString::new("pyo3_async_runtimes/pyo3_async_runtimes_glue.py").unwrap(), + &CString::new("pyo3_async_runtimes_glue").unwrap(), )? .into()) })? @@ -1670,10 +1680,10 @@ where gen, SenderGlue { locals, - tx: Box::new(GenericSender { + tx: Arc::new(Mutex::new(GenericSender { runtime: PhantomData::, tx, - }), + })), }, ), )?, diff --git a/src/lib.rs b/src/lib.rs index d399297..6178b76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -300,7 +300,7 @@ //! //! ```toml //! [dependencies.pyo3-async-runtimes] -//! version = "0.22" +//! version = "0.23" //! features = ["attributes"] //! ``` //! @@ -313,7 +313,7 @@ //! //! ```toml //! [dependencies.pyo3-async-runtimes] -//! version = "0.22" +//! version = "0.23" //! features = ["async-std-runtime"] //! ``` //! @@ -326,7 +326,7 @@ //! //! ```toml //! [dependencies.pyo3-async-runtimes] -//! version = "0.22" +//! version = "0.23" //! features = ["tokio-runtime"] //! ``` //! @@ -339,7 +339,7 @@ //! //! ```toml //! [dependencies.pyo3-async-runtimes] -//! version = "0.22" +//! version = "0.23" //! features = ["testing"] //! ``` @@ -364,7 +364,7 @@ pub mod generic; #[pymodule] fn pyo3_async_runtimes(py: Python, m: &Bound) -> PyResult<()> { - m.add("RustPanic", py.get_type_bound::())?; + m.add("RustPanic", py.get_type::())?; Ok(()) } @@ -442,7 +442,7 @@ fn close(event_loop: Bound) -> PyResult<()> { fn asyncio(py: Python) -> PyResult<&Bound> { ASYNCIO - .get_or_try_init(|| Ok(py.import_bound("asyncio")?.into())) + .get_or_try_init(|| Ok(py.import("asyncio")?.into())) .map(|asyncio| asyncio.bind(py)) } @@ -464,7 +464,7 @@ pub fn get_running_loop(py: Python) -> PyResult> { fn contextvars(py: Python) -> PyResult<&Bound> { Ok(CONTEXTVARS - .get_or_try_init(|| py.import_bound("contextvars").map(|m| m.into()))? + .get_or_try_init(|| py.import("contextvars").map(|m| m.into()))? .bind(py)) } @@ -576,14 +576,14 @@ impl PyEnsureFuture { } } -fn call_soon_threadsafe( - event_loop: &Bound, +fn call_soon_threadsafe<'py>( + event_loop: &'py Bound, context: &Bound, - args: impl IntoPy>, + args: impl IntoPyObject<'py, Target = PyTuple>, ) -> PyResult<()> { let py = event_loop.py(); - let kwargs = PyDict::new_bound(py); + let kwargs = PyDict::new(py); kwargs.set_item("context", context)?; event_loop.call_method("call_soon_threadsafe", args, Some(&kwargs))?; @@ -661,7 +661,7 @@ pub fn into_future_with_locals( match rx.await { Ok(item) => item, Err(_) => Python::with_gil(|py| { - Err(PyErr::from_value_bound( + Err(PyErr::from_value( asyncio(py)?.call_method0("CancelledError")?, )) }), diff --git a/src/testing.rs b/src/testing.rs index 90e90eb..8bfc55f 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -64,7 +64,7 @@ //! Also add the `testing` and `attributes` features to the `pyo3-async-runtimes` dependency and select your preferred runtime: //! //! ```toml -//! pyo3-async-runtimes = { version = "0.22", features = ["testing", "attributes", "async-std-runtime"] } +//! pyo3-async-runtimes = { version = "0.23", features = ["testing", "attributes", "async-std-runtime"] } //! ``` //! //! At this point, you should be able to run the test via `cargo test` diff --git a/src/tokio.rs b/src/tokio.rs index f435ea5..9e1f704 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -9,7 +9,7 @@ //! //! ```toml //! [dependencies.pyo3-async-runtimes] -//! version = "0.22" +//! version = "0.23" //! features = ["unstable-streams"] //! ``` @@ -315,14 +315,14 @@ where /// ) /// } /// ``` -pub fn future_into_py_with_locals( +pub fn future_into_py_with_locals<'py, F, T>( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + Send + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { generic::future_into_py_with_locals::(py, locals, fut) } @@ -365,10 +365,10 @@ where /// }) /// } /// ``` -pub fn future_into_py(py: Python, fut: F) -> PyResult> +pub fn future_into_py<'py, F, T>(py: Python, fut: F) -> PyResult> where F: Future> + Send + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { generic::future_into_py::(py, fut) } @@ -452,14 +452,14 @@ 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_with_locals( +pub fn local_future_into_py_with_locals<'py, F, T>( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { generic::local_future_into_py_with_locals::(py, locals, fut) } @@ -537,10 +537,10 @@ 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> +pub fn local_future_into_py<'py, F, T>(py: Python, fut: F) -> PyResult> where F: Future> + 'static, - T: IntoPy, + T: IntoPyObject<'py>, { generic::local_future_into_py::(py, fut) } From 195804db60b76909395d6b52694c15c5dcc43e53 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 18 Nov 2024 12:36:31 +0000 Subject: [PATCH 03/10] Another approach --- src/async_std.rs | 28 ++++++++++++++----------- src/generic.rs | 54 ++++++++++++++++++++++++++++-------------------- src/tokio.rs | 28 ++++++++++++++----------- 3 files changed, 64 insertions(+), 46 deletions(-) diff --git a/src/async_std.rs b/src/async_std.rs index 32e5990..1bd868a 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -272,16 +272,17 @@ where /// ) /// } /// ``` -pub fn future_into_py_with_locals<'py, F, T>( +pub fn future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + Send + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - generic::future_into_py_with_locals::(py, locals, fut) + generic::future_into_py_with_locals::(py, locals, fut) } /// Convert a Rust Future into a Python awaitable @@ -322,12 +323,13 @@ where /// }) /// } /// ``` -pub fn future_into_py<'py, F, T>(py: Python, fut: F) -> PyResult> +pub fn future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + Send + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - generic::future_into_py::(py, fut) + generic::future_into_py::(py, fut) } /// Convert a `!Send` Rust Future into a Python awaitable @@ -393,16 +395,17 @@ 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_with_locals<'py, F, T>( +pub fn local_future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - generic::local_future_into_py_with_locals::(py, locals, fut) + generic::local_future_into_py_with_locals::(py, locals, fut) } /// Convert a `!Send` Rust Future into a Python awaitable @@ -463,12 +466,13 @@ 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, F, T>(py: Python, fut: F) -> PyResult> +pub fn local_future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - generic::local_future_into_py::(py, fut) + generic::local_future_into_py::(py, fut) } /// Convert a Python `awaitable` into a Rust Future diff --git a/src/generic.rs b/src/generic.rs index 3eb3d62..78f3f42 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -201,7 +201,7 @@ where let py = event_loop.py(); let result_tx = Arc::new(Mutex::new(None)); let result_rx = Arc::clone(&result_tx); - let coro = future_into_py_with_locals::( + let coro = future_into_py_with_locals::( py, TaskLocals::new(event_loop.clone()).copy_context(py)?, async move { @@ -578,7 +578,7 @@ where /// } /// ``` #[allow(unused_must_use)] -pub fn future_into_py_with_locals<'py, R, F, T>( +pub fn future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, @@ -586,7 +586,8 @@ pub fn future_into_py_with_locals<'py, R, F, T>( where R: Runtime + ContextExt, F: Future> + Send + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { let (cancel_tx, cancel_rx) = oneshot::channel(); @@ -622,7 +623,9 @@ where let _ = set_result( &locals2.event_loop(py), future_tx1.bind(py), - result.map(|val| val.into_pyobject(py).unwrap()), + result.and_then(|val| { + Ok(val.into_pyobject(py).map_err(Into::into)?.unbind().into()) + }), ) .map_err(dump_err(py)); }); @@ -845,13 +848,14 @@ impl PyDoneCallback { /// }) /// } /// ``` -pub fn future_into_py<'py, R, F, T>(py: Python, fut: F) -> PyResult> +pub fn future_into_py(py: Python, fut: F) -> PyResult> where R: Runtime + ContextExt, F: Future> + Send + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - future_into_py_with_locals::(py, get_current_locals::(py)?, fut) + future_into_py_with_locals::(py, get_current_locals::(py)?, fut) } /// Convert a `!Send` Rust Future into a Python awaitable with a generic runtime and manual @@ -983,7 +987,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(unused_must_use)] -pub fn local_future_into_py_with_locals<'py, R, F, T>( +pub fn local_future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, @@ -991,7 +995,8 @@ pub fn local_future_into_py_with_locals<'py, R, F, T>( where R: Runtime + SpawnLocalExt + LocalContextExt, F: Future> + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { let (cancel_tx, cancel_rx) = oneshot::channel(); @@ -1027,7 +1032,9 @@ where let _ = set_result( locals2.event_loop.bind(py), future_tx1.bind(py), - result.map(|val| val.into_py(py)), + result.and_then(|val| { + Ok(val.into_pyobject(py).map_err(Into::into)?.unbind().into()) + }), ) .map_err(dump_err(py)); }); @@ -1184,13 +1191,14 @@ 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, R, F, T>(py: Python, fut: F) -> PyResult> +pub fn local_future_into_py(py: Python, fut: F) -> PyResult> where R: Runtime + ContextExt + SpawnLocalExt + LocalContextExt, F: Future> + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - local_future_into_py_with_locals::(py, get_current_locals::(py)?, fut) + local_future_into_py_with_locals::(py, get_current_locals::(py)?, fut) } /// unstable-streams Convert an async generator into a stream @@ -1472,25 +1480,27 @@ where { 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)), + Ok(_) => true.into_pyobject(py), Err(e) => { if e.is_full() { let mut tx = self.tx.clone(); Python::with_gil(move |py| { - Ok( - future_into_py_with_locals::(py, locals, async move { + Ok(future_into_py_with_locals::( + py, + locals, + async move { if tx.flush().await.is_err() { // receiving side disconnected - return Python::with_gil(|py| Ok(false.into_py(py))); + return Python::with_gil(|py| Ok(false)); } if tx.send(item).await.is_err() { // receiving side disconnected - return Python::with_gil(|py| Ok(false.into_py(py))); + return Python::with_gil(|py| Ok(false)); } - Python::with_gil(|py| Ok(true.into_py(py))) - })? - .into(), - ) + Python::with_gil(|py| Ok(true)) + }, + )? + .into()) }) } else { Ok(false.into_py(py)) diff --git a/src/tokio.rs b/src/tokio.rs index 9e1f704..452f640 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -315,16 +315,17 @@ where /// ) /// } /// ``` -pub fn future_into_py_with_locals<'py, F, T>( +pub fn future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + Send + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - generic::future_into_py_with_locals::(py, locals, fut) + generic::future_into_py_with_locals::(py, locals, fut) } /// Convert a Rust Future into a Python awaitable @@ -365,12 +366,13 @@ where /// }) /// } /// ``` -pub fn future_into_py<'py, F, T>(py: Python, fut: F) -> PyResult> +pub fn future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + Send + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - generic::future_into_py::(py, fut) + generic::future_into_py::(py, fut) } /// Convert a `!Send` Rust Future into a Python awaitable @@ -452,16 +454,17 @@ 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_with_locals<'py, F, T>( +pub fn local_future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - generic::local_future_into_py_with_locals::(py, locals, fut) + generic::local_future_into_py_with_locals::(py, locals, fut) } /// Convert a `!Send` Rust Future into a Python awaitable @@ -537,12 +540,13 @@ 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, F, T>(py: Python, fut: F) -> PyResult> +pub fn local_future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + 'static, - T: IntoPyObject<'py>, + T: for<'py> IntoPyObject<'py, Target = P>, + P: AsRef, { - generic::local_future_into_py::(py, fut) + generic::local_future_into_py::(py, fut) } /// Convert a Python `awaitable` into a Rust Future From 0c9e8583cd73f0ec56e8cb4784caef9f9bff2cef Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 18 Nov 2024 12:49:44 +0000 Subject: [PATCH 04/10] update --- src/generic.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/generic.rs b/src/generic.rs index 78f3f42..ed06302 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -1480,7 +1480,7 @@ where { fn send(&mut self, py: Python, locals: TaskLocals, item: PyObject) -> PyResult { match self.tx.try_send(item.clone_ref(py)) { - Ok(_) => true.into_pyobject(py), + Ok(_) => Ok(true.into_pyobject(py)?.as_ref().unbind()), Err(e) => { if e.is_full() { let mut tx = self.tx.clone(); @@ -1491,19 +1491,23 @@ where async move { if tx.flush().await.is_err() { // receiving side disconnected - return Python::with_gil(|py| Ok(false)); + return Python::with_gil(|py| { + Ok(false.into_pyobject(py)?.as_ref().unbind()) + }); } if tx.send(item).await.is_err() { // receiving side disconnected - return Python::with_gil(|py| Ok(false)); + return Python::with_gil(|py| { + Ok(false.into_pyobject(py)?.as_ref().unbind()) + }); } - Python::with_gil(|py| Ok(true)) + Python::with_gil(|py| Ok(true.into_pyobject(py)?.as_ref().unbind())) }, )? .into()) }) } else { - Ok(false.into_py(py)) + Ok(false.into_pyobject(py)?.as_ref().unbind()) } } } From 679a4c6057014e305fdf44c5c14d194c2e81376f Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Mon, 18 Nov 2024 13:04:23 +0000 Subject: [PATCH 05/10] fix compile! --- src/async_std.rs | 28 ++++++++++------------ src/generic.rs | 60 +++++++++++++++++++++++------------------------- src/tokio.rs | 28 ++++++++++------------ 3 files changed, 53 insertions(+), 63 deletions(-) diff --git a/src/async_std.rs b/src/async_std.rs index 1bd868a..16930ad 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -272,17 +272,16 @@ where /// ) /// } /// ``` -pub fn future_into_py_with_locals( +pub fn future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + Send + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - generic::future_into_py_with_locals::(py, locals, fut) + generic::future_into_py_with_locals::(py, locals, fut) } /// Convert a Rust Future into a Python awaitable @@ -323,13 +322,12 @@ where /// }) /// } /// ``` -pub fn future_into_py(py: Python, fut: F) -> PyResult> +pub fn future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + Send + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - generic::future_into_py::(py, fut) + generic::future_into_py::(py, fut) } /// Convert a `!Send` Rust Future into a Python awaitable @@ -395,17 +393,16 @@ 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_with_locals( +pub fn local_future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - generic::local_future_into_py_with_locals::(py, locals, fut) + generic::local_future_into_py_with_locals::(py, locals, fut) } /// Convert a `!Send` Rust Future into a Python awaitable @@ -466,13 +463,12 @@ 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> +pub fn local_future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - generic::local_future_into_py::(py, fut) + generic::local_future_into_py::(py, fut) } /// Convert a Python `awaitable` into a Rust Future diff --git a/src/generic.rs b/src/generic.rs index ed06302..0579146 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -201,7 +201,7 @@ where let py = event_loop.py(); let result_tx = Arc::new(Mutex::new(None)); let result_rx = Arc::clone(&result_tx); - let coro = future_into_py_with_locals::( + let coro = future_into_py_with_locals::( py, TaskLocals::new(event_loop.clone()).copy_context(py)?, async move { @@ -578,7 +578,7 @@ where /// } /// ``` #[allow(unused_must_use)] -pub fn future_into_py_with_locals( +pub fn future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, @@ -586,8 +586,7 @@ pub fn future_into_py_with_locals( where R: Runtime + ContextExt, F: Future> + Send + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { let (cancel_tx, cancel_rx) = oneshot::channel(); @@ -623,8 +622,9 @@ where let _ = set_result( &locals2.event_loop(py), future_tx1.bind(py), - result.and_then(|val| { - Ok(val.into_pyobject(py).map_err(Into::into)?.unbind().into()) + result.and_then(|val| match val.into_pyobject(py) { + Ok(obj) => Ok(obj.into_any().unbind()), + Err(err) => Err(err.into()), }), ) .map_err(dump_err(py)); @@ -848,14 +848,13 @@ impl PyDoneCallback { /// }) /// } /// ``` -pub fn future_into_py(py: Python, fut: F) -> PyResult> +pub fn future_into_py(py: Python, fut: F) -> PyResult> where R: Runtime + ContextExt, F: Future> + Send + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - future_into_py_with_locals::(py, get_current_locals::(py)?, fut) + future_into_py_with_locals::(py, get_current_locals::(py)?, fut) } /// Convert a `!Send` Rust Future into a Python awaitable with a generic runtime and manual @@ -987,7 +986,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(unused_must_use)] -pub fn local_future_into_py_with_locals( +pub fn local_future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, @@ -995,8 +994,7 @@ pub fn local_future_into_py_with_locals( where R: Runtime + SpawnLocalExt + LocalContextExt, F: Future> + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { let (cancel_tx, cancel_rx) = oneshot::channel(); @@ -1032,8 +1030,9 @@ where let _ = set_result( locals2.event_loop.bind(py), future_tx1.bind(py), - result.and_then(|val| { - Ok(val.into_pyobject(py).map_err(Into::into)?.unbind().into()) + result.and_then(|val| match val.into_pyobject(py) { + Ok(obj) => Ok(obj.into_any().unbind()), + Err(err) => Err(err.into()), }), ) .map_err(dump_err(py)); @@ -1191,14 +1190,13 @@ 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> +pub fn local_future_into_py(py: Python, fut: F) -> PyResult> where R: Runtime + ContextExt + SpawnLocalExt + LocalContextExt, F: Future> + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - local_future_into_py_with_locals::(py, get_current_locals::(py)?, fut) + local_future_into_py_with_locals::(py, get_current_locals::(py)?, fut) } /// unstable-streams Convert an async generator into a stream @@ -1480,34 +1478,34 @@ where { fn send(&mut self, py: Python, locals: TaskLocals, item: PyObject) -> PyResult { match self.tx.try_send(item.clone_ref(py)) { - Ok(_) => Ok(true.into_pyobject(py)?.as_ref().unbind()), + Ok(_) => Ok(true.into_pyobject(py)?.into_any().unbind()), Err(e) => { if e.is_full() { let mut tx = self.tx.clone(); Python::with_gil(move |py| { - Ok(future_into_py_with_locals::( - py, - locals, - async move { + Ok( + future_into_py_with_locals::(py, locals, async move { if tx.flush().await.is_err() { // receiving side disconnected return Python::with_gil(|py| { - Ok(false.into_pyobject(py)?.as_ref().unbind()) + Ok(false.into_pyobject(py)?.into_any().unbind()) }); } if tx.send(item).await.is_err() { // receiving side disconnected return Python::with_gil(|py| { - Ok(false.into_pyobject(py)?.as_ref().unbind()) + Ok(false.into_pyobject(py)?.into_any().unbind()) }); } - Python::with_gil(|py| Ok(true.into_pyobject(py)?.as_ref().unbind())) - }, - )? - .into()) + Python::with_gil(|py| { + Ok(true.into_pyobject(py)?.into_any().unbind()) + }) + })? + .into(), + ) }) } else { - Ok(false.into_pyobject(py)?.as_ref().unbind()) + Ok(false.into_pyobject(py)?.into_any().unbind()) } } } diff --git a/src/tokio.rs b/src/tokio.rs index 452f640..69f6c63 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -315,17 +315,16 @@ where /// ) /// } /// ``` -pub fn future_into_py_with_locals( +pub fn future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + Send + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - generic::future_into_py_with_locals::(py, locals, fut) + generic::future_into_py_with_locals::(py, locals, fut) } /// Convert a Rust Future into a Python awaitable @@ -366,13 +365,12 @@ where /// }) /// } /// ``` -pub fn future_into_py(py: Python, fut: F) -> PyResult> +pub fn future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + Send + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - generic::future_into_py::(py, fut) + generic::future_into_py::(py, fut) } /// Convert a `!Send` Rust Future into a Python awaitable @@ -454,17 +452,16 @@ 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_with_locals( +pub fn local_future_into_py_with_locals( py: Python, locals: TaskLocals, fut: F, ) -> PyResult> where F: Future> + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - generic::local_future_into_py_with_locals::(py, locals, fut) + generic::local_future_into_py_with_locals::(py, locals, fut) } /// Convert a `!Send` Rust Future into a Python awaitable @@ -540,13 +537,12 @@ 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> +pub fn local_future_into_py(py: Python, fut: F) -> PyResult> where F: Future> + 'static, - T: for<'py> IntoPyObject<'py, Target = P>, - P: AsRef, + T: for<'py> IntoPyObject<'py>, { - generic::local_future_into_py::(py, fut) + generic::local_future_into_py::(py, fut) } /// Convert a Python `awaitable` into a Rust Future From 204fcadd5db4cffc0309838bf6ed3d1872bce96d Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Tue, 19 Nov 2024 15:04:19 +0000 Subject: [PATCH 06/10] move cstring inside conditional import --- src/generic.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/generic.rs b/src/generic.rs index 0579146..755e090 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -14,7 +14,6 @@ //! ``` use std::{ - ffi::CString, future::Future, pin::Pin, sync::{Arc, Mutex}, @@ -1666,6 +1665,8 @@ pub fn into_stream_with_locals_v2( where R: Runtime + ContextExt, { + use std::ffi::CString; + static GLUE_MOD: OnceCell = OnceCell::new(); let py = gen.py(); let glue = GLUE_MOD From e3883da2927cd6037e8da93a35d4d002781a1601 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Tue, 19 Nov 2024 23:21:10 +0000 Subject: [PATCH 07/10] address comment --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6178b76..6a852e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -577,7 +577,7 @@ impl PyEnsureFuture { } fn call_soon_threadsafe<'py>( - event_loop: &'py Bound, + event_loop: &Bound<'py, PyAny>, context: &Bound, args: impl IntoPyObject<'py, Target = PyTuple>, ) -> PyResult<()> { From ab65a062ba28cfdb8f766dbd4658712823f45df0 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Tue, 19 Nov 2024 23:32:05 +0000 Subject: [PATCH 08/10] update examples and tests --- README.md | 12 ++-- examples/async_std.rs | 4 +- examples/tokio.rs | 6 +- examples/tokio_current_thread.rs | 6 +- examples/tokio_multi_thread.rs | 6 +- pytests/common/mod.rs | 17 ++++-- pytests/test_async_std_asyncio.rs | 64 ++++++++++----------- pytests/test_async_std_run_forever.rs | 2 +- pytests/test_async_std_uvloop.rs | 2 +- pytests/test_race_condition_regression.rs | 12 ++-- pytests/test_tokio_current_thread_uvloop.rs | 2 +- pytests/test_tokio_multi_thread_uvloop.rs | 2 +- pytests/tokio_asyncio/mod.rs | 64 ++++++++++----------- pytests/tokio_run_forever/mod.rs | 2 +- src/async_std.rs | 2 +- src/generic.rs | 2 +- src/lib.rs | 6 +- src/tokio.rs | 2 +- 18 files changed, 111 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index 0b95bee..f987308 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ use pyo3::prelude::*; #[pyo3_async_runtimes::async_std::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import_bound("asyncio")?; + let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_async_runtimes::async_std::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) })?; @@ -97,7 +97,7 @@ use pyo3::prelude::*; #[pyo3_async_runtimes::tokio::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import_bound("asyncio")?; + let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_async_runtimes::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) })?; @@ -240,7 +240,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_bound("example")?; + let example = py.import("example")?; // calling the py_sleep method like a normal function // returns a coroutine @@ -359,7 +359,7 @@ async fn main() -> PyResult<()> { // PyO3 is initialized - Ready to go let fut = Python::with_gil(|py| -> PyResult<_> { - let asyncio = py.import_bound("asyncio")?; + let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_async_runtimes::async_std::into_future( @@ -507,7 +507,7 @@ fn main() -> PyResult<()> { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { - let uvloop = py.import_bound("uvloop")?; + let uvloop = py.import("uvloop")?; uvloop.call_method0("install")?; // store a reference for the assertion @@ -604,7 +604,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_bound("asyncio")?; + let asyncio = py.import("asyncio")?; let event_loop = asyncio.call_method0("new_event_loop")?; asyncio.call_method1("set_event_loop", (&event_loop,))?; diff --git a/examples/async_std.rs b/examples/async_std.rs index fc3af87..254d057 100644 --- a/examples/async_std.rs +++ b/examples/async_std.rs @@ -3,11 +3,11 @@ use pyo3::prelude::*; #[pyo3_async_runtimes::async_std::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import_bound("asyncio")?; + let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_async_runtimes::async_std::into_future( - asyncio.call_method1("sleep", (1.into_py(py),))?, + asyncio.call_method1("sleep", (1.into_pyobject(py).unwrap(),))?, ) })?; diff --git a/examples/tokio.rs b/examples/tokio.rs index c005136..31581d6 100644 --- a/examples/tokio.rs +++ b/examples/tokio.rs @@ -3,10 +3,12 @@ use pyo3::prelude::*; #[pyo3_async_runtimes::tokio::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import_bound("asyncio")?; + let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future - pyo3_async_runtimes::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) + pyo3_async_runtimes::tokio::into_future( + asyncio.call_method1("sleep", (1.into_pyobject(py).unwrap(),))?, + ) })?; println!("sleeping for 1s"); diff --git a/examples/tokio_current_thread.rs b/examples/tokio_current_thread.rs index 776bc86..d076bd0 100644 --- a/examples/tokio_current_thread.rs +++ b/examples/tokio_current_thread.rs @@ -3,10 +3,12 @@ use pyo3::prelude::*; #[pyo3_async_runtimes::tokio::main(flavor = "current_thread")] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import_bound("asyncio")?; + let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future - pyo3_async_runtimes::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) + pyo3_async_runtimes::tokio::into_future( + asyncio.call_method1("sleep", (1.into_pyobject(py).unwrap(),))?, + ) })?; println!("sleeping for 1s"); diff --git a/examples/tokio_multi_thread.rs b/examples/tokio_multi_thread.rs index 733dd8c..c828977 100644 --- a/examples/tokio_multi_thread.rs +++ b/examples/tokio_multi_thread.rs @@ -3,10 +3,12 @@ use pyo3::prelude::*; #[pyo3_async_runtimes::tokio::main(flavor = "multi_thread", worker_threads = 10)] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { - let asyncio = py.import_bound("asyncio")?; + let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future - pyo3_async_runtimes::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) + pyo3_async_runtimes::tokio::into_future( + asyncio.call_method1("sleep", (1.into_pyobject(py).unwrap(),))?, + ) })?; println!("sleeping for 1s"); diff --git a/pytests/common/mod.rs b/pytests/common/mod.rs index 91008e9..67b7213 100644 --- a/pytests/common/mod.rs +++ b/pytests/common/mod.rs @@ -1,9 +1,10 @@ +use std::ffi::CString; use std::{thread, time::Duration}; use pyo3::prelude::*; use pyo3_async_runtimes::TaskLocals; -pub(super) const TEST_MOD: &'static str = r#" +pub(super) const TEST_MOD: &str = r#" import asyncio async def py_sleep(duration): @@ -15,12 +16,16 @@ 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_bound(py, TEST_MOD, "test_rust_coroutine/test_mod.py", "test_mod")?; + let test_mod = PyModule::from_code( + py, + &CString::new(TEST_MOD).unwrap(), + &CString::new("test_rust_coroutine/test_mod.py").unwrap(), + &CString::new("test_mod").unwrap(), + )?; pyo3_async_runtimes::into_future_with_locals( &TaskLocals::new(event_loop.into_bound(py)), - test_mod.call_method1("py_sleep", (1.into_py(py),))?, + test_mod.call_method1("py_sleep", (1.into_pyobject(py).unwrap(),))?, ) })?; @@ -36,8 +41,8 @@ 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_bound("functools")?; - let time = py.import_bound("time")?; + let functools = py.import("functools")?; + let time = py.import("time")?; // spawn a blocking sleep in the threadpool executor - returns a task, not a coroutine let task = event_loop.bind(py).call_method1( diff --git a/pytests/test_async_std_asyncio.rs b/pytests/test_async_std_asyncio.rs index 0f4afed..cdd36a7 100644 --- a/pytests/test_async_std_asyncio.rs +++ b/pytests/test_async_std_asyncio.rs @@ -1,5 +1,6 @@ mod common; +use std::ffi::CString; use std::{ rc::Rc, sync::{Arc, Mutex}, @@ -30,15 +31,15 @@ fn sleep<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult PyResult<()> { let fut = Python::with_gil(|py| { - let sleeper_mod = PyModule::new_bound(py, "rust_sleeper")?; + let sleeper_mod = PyModule::new(py, "rust_sleeper")?; sleeper_mod.add_wrapped(wrap_pyfunction!(sleep))?; - let test_mod = PyModule::from_code_bound( + let test_mod = PyModule::from_code( py, - common::TEST_MOD, - "test_future_into_py_mod.py", - "test_future_into_py_mod", + &CString::new(common::TEST_MOD).unwrap(), + &CString::new("test_future_into_py_mod.py").unwrap(), + &CString::new("test_future_into_py_mod").unwrap(), )?; pyo3_async_runtimes::async_std::into_future( @@ -53,10 +54,7 @@ async fn test_future_into_py() -> PyResult<()> { #[pyo3_async_runtimes::async_std::test] async fn test_async_sleep() -> PyResult<()> { - let asyncio = Python::with_gil(|py| { - py.import_bound("asyncio") - .map(|asyncio| PyObject::from(asyncio)) - })?; + let asyncio = Python::with_gil(|py| py.import("asyncio").map(PyObject::from))?; task::sleep(Duration::from_secs(1)).await; @@ -157,8 +155,8 @@ async fn test_cancel() -> PyResult<()> { .await { Python::with_gil(|py| -> PyResult<()> { - assert!(e.value_bound(py).is_instance( - py.import_bound("asyncio")? + assert!(e.value(py).is_instance( + py.import("asyncio")? .getattr("CancelledError")? .downcast::() .unwrap() @@ -191,18 +189,18 @@ async def gen(): #[pyo3_async_runtimes::async_std::test] async fn test_async_gen_v1() -> PyResult<()> { let stream = Python::with_gil(|py| { - let test_mod = PyModule::from_code_bound( + let test_mod = PyModule::from_code( py, - ASYNC_STD_TEST_MOD, - "test_rust_coroutine/async_std_test_mod.py", - "async_std_test_mod", + &CString::new(ASYNC_STD_TEST_MOD).unwrap(), + &CString::new("test_rust_coroutine/async_std_test_mod.py").unwrap(), + &CString::new("async_std_test_mod").unwrap(), )?; pyo3_async_runtimes::async_std::into_stream_v1(test_mod.call_method0("gen")?) })?; let vals = stream - .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) + .map(|item| Python::with_gil(|py| -> PyResult { item?.bind(py).extract() })) .try_collect::>() .await?; @@ -214,7 +212,7 @@ async fn test_async_gen_v1() -> PyResult<()> { #[pyo3_async_runtimes::async_std::test] fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { let locals = Python::with_gil(|py| -> PyResult { - Ok(TaskLocals::new(event_loop.into_bound(py)).copy_context(py)?) + TaskLocals::new(event_loop.into_bound(py)).copy_context(py) })?; async_std::task::block_on(pyo3_async_runtimes::async_std::scope_local(locals, async { let completed = Arc::new(Mutex::new(false)); @@ -239,8 +237,8 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { .await { Python::with_gil(|py| -> PyResult<()> { - assert!(e.value_bound(py).is_instance( - py.import_bound("asyncio")? + assert!(e.value(py).is_instance( + py.import("asyncio")? .getattr("CancelledError")? .downcast::() .unwrap() @@ -297,13 +295,13 @@ fn test_multiple_asyncio_run() -> PyResult<()> { })?; let d = [ - ("asyncio", py.import_bound("asyncio")?.into()), + ("asyncio", py.import("asyncio")?.into()), ("test_mod", wrap_pymodule!(test_mod)(py)), ] - .into_py_dict_bound(py); + .into_py_dict(py)?; - py.run_bound(MULTI_ASYNCIO_CODE, Some(&d), None)?; - py.run_bound(MULTI_ASYNCIO_CODE, Some(&d), None)?; + py.run(&CString::new(MULTI_ASYNCIO_CODE).unwrap(), Some(&d), None)?; + py.run(&CString::new(MULTI_ASYNCIO_CODE).unwrap(), Some(&d), None)?; Ok(()) }) } @@ -332,18 +330,18 @@ fn cvars_mod(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyo3_async_runtimes::async_std::test] async fn test_async_gen_v2() -> PyResult<()> { let stream = Python::with_gil(|py| { - let test_mod = PyModule::from_code_bound( + let test_mod = PyModule::from_code( py, - ASYNC_STD_TEST_MOD, - "test_rust_coroutine/async_std_test_mod.py", - "async_std_test_mod", + &CString::new(ASYNC_STD_TEST_MOD).unwrap(), + &CString::new("test_rust_coroutine/async_std_test_mod.py").unwrap(), + &CString::new("async_std_test_mod").unwrap(), )?; pyo3_async_runtimes::async_std::into_stream_v2(test_mod.call_method0("gen")?) })?; let vals = stream - .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) + .map(|item| Python::with_gil(|py| -> PyResult { item.bind(py).extract() })) .try_collect::>() .await?; @@ -369,14 +367,14 @@ asyncio.run(main()) fn test_contextvars() -> PyResult<()> { Python::with_gil(|py| { let d = [ - ("asyncio", py.import_bound("asyncio")?.into()), - ("contextvars", py.import_bound("contextvars")?.into()), + ("asyncio", py.import("asyncio")?.into()), + ("contextvars", py.import("contextvars")?.into()), ("cvars_mod", wrap_pymodule!(cvars_mod)(py)), ] - .into_py_dict_bound(py); + .into_py_dict(py)?; - py.run_bound(CONTEXTVARS_CODE, Some(&d), None)?; - py.run_bound(CONTEXTVARS_CODE, Some(&d), None)?; + py.run(&CString::new(CONTEXTVARS_CODE).unwrap(), Some(&d), None)?; + py.run(&CString::new(CONTEXTVARS_CODE).unwrap(), Some(&d), None)?; Ok(()) }) } diff --git a/pytests/test_async_std_run_forever.rs b/pytests/test_async_std_run_forever.rs index ecc76f9..70928bc 100644 --- a/pytests/test_async_std_run_forever.rs +++ b/pytests/test_async_std_run_forever.rs @@ -12,7 +12,7 @@ fn main() { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { - let asyncio = py.import_bound("asyncio")?; + let asyncio = py.import("asyncio")?; let event_loop = asyncio.call_method0("new_event_loop")?; asyncio.call_method1("set_event_loop", (&event_loop,))?; diff --git a/pytests/test_async_std_uvloop.rs b/pytests/test_async_std_uvloop.rs index 57e9a73..972cebd 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_bound("uvloop")?; + let uvloop = py.import("uvloop")?; uvloop.call_method0("install")?; // store a reference for the assertion diff --git a/pytests/test_race_condition_regression.rs b/pytests/test_race_condition_regression.rs index 5a382aa..cfd2c71 100644 --- a/pytests/test_race_condition_regression.rs +++ b/pytests/test_race_condition_regression.rs @@ -1,3 +1,5 @@ +use std::ffi::CString; + use pyo3::{prelude::*, wrap_pyfunction}; #[pyfunction] @@ -49,15 +51,15 @@ fn main() -> pyo3::PyResult<()> { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| -> PyResult<()> { - let sleeper_mod = PyModule::new_bound(py, "rust_sleeper")?; + let sleeper_mod = PyModule::new(py, "rust_sleeper")?; sleeper_mod.add_wrapped(wrap_pyfunction!(sleep))?; - let test_mod = PyModule::from_code_bound( + let test_mod = PyModule::from_code( py, - RACE_CONDITION_REGRESSION_TEST, - "race_condition_regression_test.py", - "race_condition_regression_test", + &CString::new(RACE_CONDITION_REGRESSION_TEST).unwrap(), + &CString::new("race_condition_regression_test.py").unwrap(), + &CString::new("race_condition_regression_test").unwrap(), )?; test_mod.call_method1("main", (sleeper_mod.getattr("sleep")?,))?; diff --git a/pytests/test_tokio_current_thread_uvloop.rs b/pytests/test_tokio_current_thread_uvloop.rs index 04f3cbc..2d1b47d 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_bound("uvloop")?; + let uvloop = py.import("uvloop")?; uvloop.call_method0("install")?; // store a reference for the assertion diff --git a/pytests/test_tokio_multi_thread_uvloop.rs b/pytests/test_tokio_multi_thread_uvloop.rs index 29b8263..f664919 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_bound("uvloop")?; + let uvloop = py.import("uvloop")?; uvloop.call_method0("install")?; // store a reference for the assertion diff --git a/pytests/tokio_asyncio/mod.rs b/pytests/tokio_asyncio/mod.rs index 740619e..afb31f7 100644 --- a/pytests/tokio_asyncio/mod.rs +++ b/pytests/tokio_asyncio/mod.rs @@ -1,3 +1,4 @@ +use std::ffi::CString; use std::{ rc::Rc, sync::{Arc, Mutex}, @@ -29,15 +30,15 @@ fn sleep<'p>(py: Python<'p>, secs: Bound<'p, PyAny>) -> PyResult PyResult<()> { let fut = Python::with_gil(|py| { - let sleeper_mod = PyModule::new_bound(py, "rust_sleeper")?; + let sleeper_mod = PyModule::new(py, "rust_sleeper")?; sleeper_mod.add_wrapped(wrap_pyfunction!(sleep))?; - let test_mod = PyModule::from_code_bound( + let test_mod = PyModule::from_code( py, - common::TEST_MOD, - "test_future_into_py_mod.py", - "test_future_into_py_mod", + &CString::new(common::TEST_MOD).unwrap(), + &CString::new("test_future_into_py_mod.py").unwrap(), + &CString::new("test_future_into_py_mod").unwrap(), )?; pyo3_async_runtimes::tokio::into_future( @@ -52,10 +53,7 @@ async fn test_future_into_py() -> PyResult<()> { #[pyo3_async_runtimes::tokio::test] async fn test_async_sleep() -> PyResult<()> { - let asyncio = Python::with_gil(|py| { - py.import_bound("asyncio") - .map(|asyncio| PyObject::from(asyncio)) - })?; + let asyncio = Python::with_gil(|py| py.import("asyncio").map(PyObject::from))?; tokio::time::sleep(Duration::from_secs(1)).await; @@ -163,8 +161,8 @@ async fn test_cancel() -> PyResult<()> { .await { Python::with_gil(|py| -> PyResult<()> { - assert!(e.value_bound(py).is_instance( - py.import_bound("asyncio")? + assert!(e.value(py).is_instance( + py.import("asyncio")? .getattr("CancelledError")? .downcast::() .unwrap() @@ -187,7 +185,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.into_bound(py)).copy_context(py)?) + TaskLocals::new(event_loop.into_bound(py)).copy_context(py) })?; tokio::task::LocalSet::new().block_on( @@ -215,8 +213,8 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> { .await { Python::with_gil(|py| -> PyResult<()> { - assert!(e.value_bound(py).is_instance( - py.import_bound("asyncio")? + assert!(e.value(py).is_instance( + py.import("asyncio")? .getattr("CancelledError")? .downcast::() .unwrap() @@ -275,13 +273,13 @@ fn test_multiple_asyncio_run() -> PyResult<()> { })?; let d = [ - ("asyncio", py.import_bound("asyncio")?.into()), + ("asyncio", py.import("asyncio")?.into()), ("test_mod", wrap_pymodule!(test_mod)(py)), ] - .into_py_dict_bound(py); + .into_py_dict(py)?; - py.run_bound(TEST_CODE, Some(&d), None)?; - py.run_bound(TEST_CODE, Some(&d), None)?; + py.run(&CString::new(TEST_CODE).unwrap(), Some(&d), None)?; + py.run(&CString::new(TEST_CODE).unwrap(), Some(&d), None)?; Ok(()) }) } @@ -320,18 +318,18 @@ async def gen(): #[pyo3_async_runtimes::tokio::test] async fn test_async_gen_v1() -> PyResult<()> { let stream = Python::with_gil(|py| { - let test_mod = PyModule::from_code_bound( + let test_mod = PyModule::from_code( py, - TOKIO_TEST_MOD, - "test_rust_coroutine/tokio_test_mod.py", - "tokio_test_mod", + &CString::new(TOKIO_TEST_MOD).unwrap(), + &CString::new("test_rust_coroutine/tokio_test_mod.py").unwrap(), + &CString::new("tokio_test_mod").unwrap(), )?; pyo3_async_runtimes::tokio::into_stream_v1(test_mod.call_method0("gen")?) })?; let vals = stream - .map(|item| Python::with_gil(|py| -> PyResult { Ok(item?.bind(py).extract()?) })) + .map(|item| Python::with_gil(|py| -> PyResult { item?.bind(py).extract() })) .try_collect::>() .await?; @@ -344,18 +342,18 @@ async fn test_async_gen_v1() -> PyResult<()> { #[pyo3_async_runtimes::tokio::test] async fn test_async_gen_v2() -> PyResult<()> { let stream = Python::with_gil(|py| { - let test_mod = PyModule::from_code_bound( + let test_mod = PyModule::from_code( py, - TOKIO_TEST_MOD, - "test_rust_coroutine/tokio_test_mod.py", - "tokio_test_mod", + &CString::new(TOKIO_TEST_MOD).unwrap(), + &CString::new("test_rust_coroutine/tokio_test_mod.py").unwrap(), + &CString::new("tokio_test_mod").unwrap(), )?; pyo3_async_runtimes::tokio::into_stream_v2(test_mod.call_method0("gen")?) })?; let vals = stream - .map(|item| Python::with_gil(|py| -> PyResult { Ok(item.bind(py).extract()?) })) + .map(|item| Python::with_gil(|py| -> PyResult { item.bind(py).extract() })) .try_collect::>() .await?; @@ -381,14 +379,14 @@ asyncio.run(main()) fn test_contextvars() -> PyResult<()> { Python::with_gil(|py| { let d = [ - ("asyncio", py.import_bound("asyncio")?.into()), - ("contextvars", py.import_bound("contextvars")?.into()), + ("asyncio", py.import("asyncio")?.into()), + ("contextvars", py.import("contextvars")?.into()), ("cvars_mod", wrap_pymodule!(cvars_mod)(py)), ] - .into_py_dict_bound(py); + .into_py_dict(py)?; - py.run_bound(CONTEXTVARS_CODE, Some(&d), None)?; - py.run_bound(CONTEXTVARS_CODE, Some(&d), None)?; + py.run(&CString::new(CONTEXTVARS_CODE).unwrap(), Some(&d), None)?; + py.run(&CString::new(CONTEXTVARS_CODE).unwrap(), Some(&d), None)?; Ok(()) }) } diff --git a/pytests/tokio_run_forever/mod.rs b/pytests/tokio_run_forever/mod.rs index ca4742a..c067d1f 100644 --- a/pytests/tokio_run_forever/mod.rs +++ b/pytests/tokio_run_forever/mod.rs @@ -10,7 +10,7 @@ fn dump_err(py: Python<'_>, e: PyErr) { pub(super) fn test_main() { Python::with_gil(|py| { - let asyncio = py.import_bound("asyncio")?; + let asyncio = py.import("asyncio")?; let event_loop = asyncio.call_method0("new_event_loop")?; asyncio.call_method1("set_event_loop", (&event_loop,))?; diff --git a/src/async_std.rs b/src/async_std.rs index 16930ad..4937b22 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -176,7 +176,7 @@ pub fn get_current_locals(py: Python) -> PyResult { /// # pyo3::prepare_freethreaded_python(); /// # /// # Python::with_gil(|py| -> PyResult<()> { -/// # let event_loop = py.import_bound("asyncio")?.call_method0("new_event_loop")?; +/// # let event_loop = py.import("asyncio")?.call_method0("new_event_loop")?; /// pyo3_async_runtimes::async_std::run_until_complete(event_loop, async move { /// async_std::task::sleep(Duration::from_secs(1)).await; /// Ok(()) diff --git a/src/generic.rs b/src/generic.rs index 755e090..b1b020a 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -182,7 +182,7 @@ where /// # use pyo3::prelude::*; /// # /// # Python::with_gil(|py| -> PyResult<()> { -/// # let event_loop = py.import_bound("asyncio")?.call_method0("new_event_loop")?; +/// # let event_loop = py.import("asyncio")?.call_method0("new_event_loop")?; /// # #[cfg(feature = "tokio-runtime")] /// pyo3_async_runtimes::generic::run_until_complete::(&event_loop, async move { /// tokio::time::sleep(Duration::from_secs(1)).await; diff --git a/src/lib.rs b/src/lib.rs index 6a852e6..d8f68c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,7 +100,7 @@ //! // event loop from earlier. //! pyo3_async_runtimes::into_future_with_locals( //! &locals, -//! py.import_bound("asyncio")?.call_method1("sleep", (1,))? +//! py.import("asyncio")?.call_method1("sleep", (1,))? //! ) //! })?; //! @@ -169,7 +169,7 @@ //! pyo3_async_runtimes::into_future_with_locals( //! // Now we can get the current locals through task-local data //! &pyo3_async_runtimes::tokio::get_current_locals(py)?, -//! py.import_bound("asyncio")?.call_method1("sleep", (1,))? +//! py.import("asyncio")?.call_method1("sleep", (1,))? //! ) //! })?; //! @@ -244,7 +244,7 @@ //! pyo3_async_runtimes::tokio::future_into_py(py, async move { //! let py_sleep = Python::with_gil(|py| { //! pyo3_async_runtimes::tokio::into_future( -//! py.import_bound("asyncio")?.call_method1("sleep", (1,))? +//! py.import("asyncio")?.call_method1("sleep", (1,))? //! ) //! })?; //! diff --git a/src/tokio.rs b/src/tokio.rs index 69f6c63..cbfe9ab 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -222,7 +222,7 @@ fn multi_thread() -> Builder { /// # /// # pyo3::prepare_freethreaded_python(); /// # Python::with_gil(|py| -> PyResult<()> { -/// # let event_loop = py.import_bound("asyncio")?.call_method0("new_event_loop")?; +/// # let event_loop = py.import("asyncio")?.call_method0("new_event_loop")?; /// pyo3_async_runtimes::tokio::run_until_complete(event_loop, async move { /// tokio::time::sleep(Duration::from_secs(1)).await; /// Ok(()) From 72489bbc462c223363cca17aa1dbe649be8207f9 Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Tue, 19 Nov 2024 23:40:01 +0000 Subject: [PATCH 09/10] Update docstrings --- src/async_std.rs | 44 ++++++++++++++++++++++++-------------------- src/generic.rs | 45 +++++++++++++++++++++++++-------------------- src/lib.rs | 8 ++++---- src/tokio.rs | 45 +++++++++++++++++++++++++-------------------- 4 files changed, 78 insertions(+), 64 deletions(-) diff --git a/src/async_std.rs b/src/async_std.rs index 4937b22..ea99e9a 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -485,6 +485,7 @@ where /// /// ``` /// use std::time::Duration; +/// use std::ffi::CString; /// /// use pyo3::prelude::*; /// @@ -498,11 +499,11 @@ where /// async fn py_sleep(seconds: f32) -> PyResult<()> { /// let test_mod = Python::with_gil(|py| -> PyResult { /// Ok( -/// PyModule::from_code_bound( +/// PyModule::from_code( /// py, -/// PYTHON_CODE, -/// "test_into_future/test_mod.py", -/// "test_mod" +/// &CString::new(PYTHON_CODE).unwrap(), +/// &CString::new("test_into_future/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap() /// )? /// .into() /// ) @@ -552,11 +553,11 @@ pub fn into_future( /// # #[pyo3_async_runtimes::async_std::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::async_std::into_stream_v1(test_mod.call_method0("gen")?) @@ -595,6 +596,7 @@ pub fn into_stream_v1( /// ``` /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -609,11 +611,11 @@ pub fn into_stream_v1( /// # #[pyo3_async_runtimes::async_std::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::async_std::into_stream_with_locals_v1( @@ -656,6 +658,7 @@ pub fn into_stream_with_locals_v1( /// ``` /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -670,11 +673,11 @@ pub fn into_stream_with_locals_v1( /// # #[pyo3_async_runtimes::async_std::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::async_std::into_stream_with_locals_v2( @@ -716,6 +719,7 @@ pub fn into_stream_with_locals_v2( /// ``` /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -730,11 +734,11 @@ pub fn into_stream_with_locals_v2( /// # #[pyo3_async_runtimes::async_std::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::async_std::into_stream_v2(test_mod.call_method0("gen")?) diff --git a/src/generic.rs b/src/generic.rs index b1b020a..753c03d 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -372,6 +372,7 @@ fn set_result( /// /// ```no_run /// # use std::{any::Any, pin::Pin, future::Future, task::{Context, Poll}, time::Duration}; +/// # use std::ffi::CString; /// # /// # use pyo3::prelude::*; /// # @@ -443,11 +444,11 @@ fn set_result( /// async fn py_sleep(seconds: f32) -> PyResult<()> { /// let test_mod = Python::with_gil(|py| -> PyResult { /// Ok( -/// PyModule::from_code_bound( +/// PyModule::from_code( /// py, -/// PYTHON_CODE, -/// "test_into_future/test_mod.py", -/// "test_mod" +/// &CString::new(PYTHON_CODE).unwrap(), +/// &CString::new("test_into_future/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )? /// .into() /// ) @@ -1266,6 +1267,7 @@ where /// /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -1278,11 +1280,11 @@ where /// /// # async fn test_async_gen() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::generic::into_stream_with_locals_v1::( @@ -1414,6 +1416,7 @@ where /// /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -1426,11 +1429,11 @@ where /// /// # async fn test_async_gen() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::generic::into_stream_v1::(test_mod.call_method0("gen")?) @@ -1622,6 +1625,7 @@ async def forward(gen, sender): /// /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -1634,11 +1638,11 @@ async def forward(gen, sender): /// /// # async fn test_async_gen() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::generic::into_stream_with_locals_v2::( @@ -1772,6 +1776,7 @@ where /// /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -1784,11 +1789,11 @@ where /// /// # async fn test_async_gen() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::generic::into_stream_v2::(test_mod.call_method0("gen")?) diff --git a/src/lib.rs b/src/lib.rs index d8f68c5..e56f6b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -619,11 +619,11 @@ fn call_soon_threadsafe<'py>( /// async fn py_sleep(seconds: f32) -> PyResult<()> { /// let test_mod = Python::with_gil(|py| -> PyResult { /// Ok( -/// PyModule::from_code_bound( +/// PyModule::from_code( /// py, -/// PYTHON_CODE, -/// "test_into_future/test_mod.py", -/// "test_mod" +/// &CString::new(PYTHON_CODE).unwrap(), +/// &CString::new("test_into_future/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )? /// .into() /// ) diff --git a/src/tokio.rs b/src/tokio.rs index cbfe9ab..724beb4 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -559,6 +559,7 @@ where /// /// ``` /// use std::time::Duration; +/// use std::ffi::CString; /// /// use pyo3::prelude::*; /// @@ -572,11 +573,11 @@ where /// async fn py_sleep(seconds: f32) -> PyResult<()> { /// let test_mod = Python::with_gil(|py| -> PyResult { /// Ok( -/// PyModule::from_code_bound( +/// PyModule::from_code( /// py, -/// PYTHON_CODE, -/// "test_into_future/test_mod.py", -/// "test_mod" +/// &CString::new(PYTHON_CODE).unwrap(), +/// &CString::new("test_into_future/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )? /// .into() /// ) @@ -613,6 +614,7 @@ pub fn into_future( /// ``` /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -627,11 +629,11 @@ pub fn into_future( /// # #[pyo3_async_runtimes::tokio::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::tokio::into_stream_with_locals_v1( @@ -673,6 +675,7 @@ pub fn into_stream_with_locals_v1( /// ``` /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -687,11 +690,11 @@ pub fn into_stream_with_locals_v1( /// # #[pyo3_async_runtimes::tokio::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::tokio::into_stream_v1(test_mod.call_method0("gen")?) @@ -730,6 +733,7 @@ pub fn into_stream_v1( /// ``` /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -744,11 +748,11 @@ pub fn into_stream_v1( /// # #[pyo3_async_runtimes::tokio::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::tokio::into_stream_with_locals_v2( @@ -790,6 +794,7 @@ pub fn into_stream_with_locals_v2( /// ``` /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio @@ -804,11 +809,11 @@ pub fn into_stream_with_locals_v2( /// # #[pyo3_async_runtimes::tokio::main] /// # async fn main() -> PyResult<()> { /// let stream = Python::with_gil(|py| { -/// let test_mod = PyModule::from_code_bound( +/// let test_mod = PyModule::from_code( /// py, -/// TEST_MOD, -/// "test_rust_coroutine/test_mod.py", -/// "test_mod", +/// &CString::new(TEST_MOD).unwrap(), +/// &CString::new("test_rust_coroutine/test_mod.py").unwrap(), +/// &CString::new("test_mod").unwrap(), /// )?; /// /// pyo3_async_runtimes::tokio::into_stream_v2(test_mod.call_method0("gen")?) From 9f0d899d529e30b40af867454873a7138b95b0eb Mon Sep 17 00:00:00 2001 From: Kyle Barron Date: Tue, 19 Nov 2024 23:46:46 +0000 Subject: [PATCH 10/10] fixes --- README.md | 6 +++--- src/async_std.rs | 3 ++- src/generic.rs | 2 +- src/lib.rs | 3 ++- src/tokio.rs | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f987308..b98403a 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future - pyo3_async_runtimes::async_std::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) + pyo3_async_runtimes::async_std::into_future(asyncio.call_method1("sleep", (1.into_pyobject(py).unwrap(),))?) })?; fut.await?; @@ -99,7 +99,7 @@ async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future - pyo3_async_runtimes::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) + pyo3_async_runtimes::tokio::into_future(asyncio.call_method1("sleep", (1.into_pyobject(py).unwrap(),))?) })?; fut.await?; @@ -363,7 +363,7 @@ async fn main() -> PyResult<()> { // convert asyncio.sleep into a Rust Future pyo3_async_runtimes::async_std::into_future( - asyncio.call_method1("sleep", (1.into_py(py),))? + asyncio.call_method1("sleep", (1.into_pyobject(py).unwrap(),))? ) })?; diff --git a/src/async_std.rs b/src/async_std.rs index ea99e9a..34c9401 100644 --- a/src/async_std.rs +++ b/src/async_std.rs @@ -512,7 +512,7 @@ where /// Python::with_gil(|py| { /// pyo3_async_runtimes::async_std::into_future( /// test_mod -/// .call_method1(py, "py_sleep", (seconds.into_py(py),))? +/// .call_method1(py, "py_sleep", (seconds.into_pyobject(py).unwrap(),))? /// .into_bound(py), /// ) /// })? @@ -539,6 +539,7 @@ pub fn into_future( /// ``` /// use pyo3::prelude::*; /// use futures::{StreamExt, TryStreamExt}; +/// use std::ffi::CString; /// /// const TEST_MOD: &str = r#" /// import asyncio diff --git a/src/generic.rs b/src/generic.rs index 753c03d..3f96f08 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -457,7 +457,7 @@ fn set_result( /// Python::with_gil(|py| { /// pyo3_async_runtimes::generic::into_future::( /// test_mod -/// .call_method1(py, "py_sleep", (seconds.into_py(py),))? +/// .call_method1(py, "py_sleep", (seconds.into_pyobject(py).unwrap(),))? /// .into_bound(py), /// ) /// })? diff --git a/src/lib.rs b/src/lib.rs index e56f6b4..480e8a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -605,6 +605,7 @@ fn call_soon_threadsafe<'py>( /// /// ``` /// use std::time::Duration; +/// use std::ffi::CString; /// /// use pyo3::prelude::*; /// @@ -633,7 +634,7 @@ fn call_soon_threadsafe<'py>( /// pyo3_async_runtimes::into_future_with_locals( /// &pyo3_async_runtimes::tokio::get_current_locals(py)?, /// test_mod -/// .call_method1(py, "py_sleep", (seconds.into_py(py),))? +/// .call_method1(py, "py_sleep", (seconds.into_pyobject(py).unwrap(),))? /// .into_bound(py), /// ) /// })? diff --git a/src/tokio.rs b/src/tokio.rs index 724beb4..47e6da0 100644 --- a/src/tokio.rs +++ b/src/tokio.rs @@ -586,7 +586,7 @@ where /// Python::with_gil(|py| { /// pyo3_async_runtimes::tokio::into_future( /// test_mod -/// .call_method1(py, "py_sleep", (seconds.into_py(py),))? +/// .call_method1(py, "py_sleep", (seconds.into_pyobject(py).unwrap(),))? /// .into_bound(py), /// ) /// })?