Skip to content

Commit a04389b

Browse files
authored
Merge pull request #55 from awestlake87/release-0.15
Release 0.15
2 parents 1f231dc + 9a04848 commit a04389b

15 files changed

+1614
-985
lines changed

Cargo.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "pyo3-asyncio"
33
description = "PyO3 utilities for Python's Asyncio library"
4-
version = "0.14.0"
4+
version = "0.15.0"
55
authors = ["Andrew J Westlake <[email protected]>"]
66
readme = "README.md"
77
keywords = ["pyo3", "python", "ffi", "async", "asyncio"]
@@ -107,18 +107,18 @@ futures = "0.3"
107107
inventory = "0.1"
108108
once_cell = "1.5"
109109
pin-project-lite = "0.2"
110-
pyo3 = "0.14"
111-
pyo3-asyncio-macros = { path = "pyo3-asyncio-macros", version = "=0.14.0", optional = true }
110+
pyo3 = "0.15"
111+
pyo3-asyncio-macros = { path = "pyo3-asyncio-macros", version = "=0.15.0", optional = true }
112112

113113
[dev-dependencies]
114-
pyo3 = { version = "0.14", features = ["macros"] }
114+
pyo3 = { version = "0.15", features = ["macros"] }
115115

116116
[dependencies.async-std]
117-
version = "1.9"
117+
version = "1.10"
118118
features = ["unstable"]
119119
optional = true
120120

121121
[dependencies.tokio]
122-
version = "1.9"
122+
version = "1.13"
123123
features = ["full"]
124124
optional = true

README.md

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
> PyO3 Asyncio is a _brand new_ part of the broader PyO3 ecosystem. Feel free to open any issues for feature requests or bugfixes for this crate.
1919
20-
__If you're a new-comer, the best way to get started is to read through the primer below! For `v0.13` users I highly recommend reading through the [migration section](#migrating-from-013-to-014) to get a general idea of what's changed in `v0.14`.__
20+
__If you're a new-comer, the best way to get started is to read through the primer below! For `v0.13` and `v0.14` users I highly recommend reading through the [migration section](#migration-guide) to get a general idea of what's changed in `v0.14` and `v0.15`.__
2121

2222
## PyO3 Asyncio Primer
2323

@@ -142,7 +142,7 @@ use pyo3::{prelude::*, wrap_pyfunction};
142142
fn rust_sleep(py: Python) -> PyResult<&PyAny> {
143143
pyo3_asyncio::async_std::future_into_py(py, async {
144144
async_std::task::sleep(std::time::Duration::from_secs(1)).await;
145-
Ok(Python::with_gil(|py| py.None()))
145+
Ok(())
146146
})
147147
}
148148

@@ -166,7 +166,7 @@ use pyo3::{prelude::*, wrap_pyfunction};
166166
fn rust_sleep(py: Python) -> PyResult<&PyAny> {
167167
pyo3_asyncio::tokio::future_into_py(py, async {
168168
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
169-
Ok(Python::with_gil(|py| py.None()))
169+
Ok(())
170170
})
171171
}
172172

@@ -283,7 +283,7 @@ async fn rust_sleep() {
283283
fn call_rust_sleep(py: Python) -> PyResult<&PyAny> {
284284
pyo3_asyncio::async_std::future_into_py(py, async move {
285285
rust_sleep().await;
286-
Ok(Python::with_gil(|py| py.None()))
286+
Ok(())
287287
})
288288
}
289289
```
@@ -433,7 +433,7 @@ use pyo3::{prelude::*, wrap_pyfunction};
433433
fn rust_sleep(py: Python) -> PyResult<&PyAny> {
434434
pyo3_asyncio::tokio::future_into_py(py, async {
435435
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
436-
Ok(Python::with_gil(|py| py.None()))
436+
Ok(())
437437
})
438438
}
439439

@@ -521,7 +521,8 @@ fn main() -> PyResult<()> {
521521
- Managing event loop references can be tricky with pyo3-asyncio. See [Event Loop References](https://awestlake87.github.io/pyo3-asyncio/master/doc/pyo3_asyncio/#event-loop-references) in the API docs to get a better intuition for how event loop references are managed in this library.
522522
- Testing pyo3-asyncio libraries and applications requires a custom test harness since Python requires control over the main thread. You can find a testing guide in the [API docs for the `testing` module](https://awestlake87.github.io/pyo3-asyncio/master/doc/pyo3_asyncio/testing)
523523

524-
## Migrating from 0.13 to 0.14
524+
## Migration Guide
525+
### Migrating from 0.13 to 0.14
525526

526527
So what's changed from `v0.13` to `v0.14`?
527528

@@ -615,7 +616,42 @@ __Before you get started, I personally recommend taking a look at [Event Loop Re
615616
- Replace `pyo3_asyncio::get_event_loop` with `pyo3_asyncio::<runtime>::get_current_loop`
616617
5. After all conversions have been replaced with their `v0.14` counterparts, `pyo3_asyncio::try_init` can safely be removed.
617618

618-
> The `v0.13` API will likely still be supported in version `v0.15`, but no solid guarantees after that point.
619+
> The `v0.13` API has been removed in version `v0.15`
620+
621+
### Migrating from 0.14 to 0.15
622+
623+
There have been a few changes to the API in order to support proper cancellation from Python and the `contextvars` module.
624+
625+
- Any instance of `cancellable_future_into_py` and `local_cancellable_future_into_py` conversions can be replaced with their`future_into_py` and `local_future_into_py` counterparts.
626+
> Cancellation support became the default behaviour in 0.15.
627+
- Instances of `*_with_loop` conversions should be replaced with the newer `*_with_locals` conversions.
628+
```rust no_run
629+
use pyo3::prelude::*;
630+
631+
Python::with_gil(|py| -> PyResult<()> {
632+
let event_loop = pyo3_asyncio::get_running_loop(py)?;
633+
634+
// *_with_loop conversions in 0.14
635+
let fut = pyo3_asyncio::tokio::future_into_py_with_loop(
636+
event_loop,
637+
async move { Ok(Python::with_gil(|py| py.None())) }
638+
)?;
639+
// should be replaced with *_with_locals in 0.15
640+
//
641+
// contextvars can be copied with `copy_context` or supplied
642+
// manually via `with_context`
643+
let fut = pyo3_asyncio::tokio::future_into_py_with_locals(
644+
py,
645+
pyo3_asyncio::TaskLocals::new(event_loop).copy_context(py)?,
646+
async move { Ok(()) }
647+
)?;
648+
649+
Ok(())
650+
});
651+
```
652+
- `scope` and `scope_local` variants now accept `TaskLocals` instead of `event_loop`. You can usually just replace the `event_loop` with `pyo3_asyncio::TaskLocals::new(event_loop).copy_context(py)?`.
653+
- Return types for `future_into_py`, `future_into_py_with_locals` `local_future_into_py`, and `local_future_into_py_with_locals` are now constrained by the bound `IntoPy<PyObject>` instead of requiring the return type to be `PyObject`. This can make the return types for futures more flexible, but inference can also fail when the concrete type is ambiguous (for example when using `into()`). Sometimes the `into()` can just be removed,
654+
- `run`, and `run_until_complete` can now return any `Send + 'static` value.
619655

620656
## Known Problems
621657

pyo3-asyncio-macros/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "pyo3-asyncio-macros"
33
description = "Proc Macro Attributes for PyO3 Asyncio"
4-
version = "0.14.0"
4+
version = "0.15.0"
55
authors = ["Andrew J Westlake <[email protected]>"]
66
readme = "../README.md"
77
keywords = ["pyo3", "python", "ffi", "async", "asyncio"]

pytests/common/mod.rs

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::{thread, time::Duration};
22

33
use pyo3::prelude::*;
4+
use pyo3_asyncio::TaskLocals;
45

56
pub(super) const TEST_MOD: &'static str = r#"
67
import asyncio
@@ -17,8 +18,8 @@ pub(super) async fn test_into_future(event_loop: PyObject) -> PyResult<()> {
1718
let test_mod =
1819
PyModule::from_code(py, TEST_MOD, "test_rust_coroutine/test_mod.py", "test_mod")?;
1920

20-
pyo3_asyncio::into_future_with_loop(
21-
event_loop.as_ref(py),
21+
pyo3_asyncio::into_future_with_locals(
22+
&TaskLocals::new(event_loop.as_ref(py)),
2223
test_mod.call_method1("py_sleep", (1.into_py(py),))?,
2324
)
2425
})?;
@@ -28,20 +29,6 @@ pub(super) async fn test_into_future(event_loop: PyObject) -> PyResult<()> {
2829
Ok(())
2930
}
3031

31-
#[allow(deprecated)]
32-
pub(super) async fn test_into_future_0_13() -> PyResult<()> {
33-
let fut = Python::with_gil(|py| {
34-
let test_mod =
35-
PyModule::from_code(py, TEST_MOD, "test_rust_coroutine/test_mod.py", "test_mod")?;
36-
37-
pyo3_asyncio::into_future(test_mod.call_method1("py_sleep", (1.into_py(py),))?)
38-
})?;
39-
40-
fut.await?;
41-
42-
Ok(())
43-
}
44-
4532
pub(super) fn test_blocking_sleep() -> PyResult<()> {
4633
thread::sleep(Duration::from_secs(1));
4734
Ok(())
@@ -61,7 +48,7 @@ pub(super) async fn test_other_awaitables(event_loop: PyObject) -> PyResult<()>
6148
),
6249
)?;
6350

64-
pyo3_asyncio::into_future_with_loop(event_loop.as_ref(py), task)
51+
pyo3_asyncio::into_future_with_locals(&TaskLocals::new(event_loop.as_ref(py)), task)
6552
})?;
6653

6754
fut.await?;

0 commit comments

Comments
 (0)