Skip to content

Commit 9a04848

Browse files
author
Andrew J Westlake
committed
Added migration guide for 0.14 to 0.15
1 parent 4b159df commit 9a04848

File tree

3 files changed

+49
-13
lines changed

3 files changed

+49
-13
lines changed

README.md

Lines changed: 39 additions & 3 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

@@ -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

pytests/test_async_std_asyncio.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ async fn test_local_future_into_py() -> PyResult<()> {
117117

118118
let py_future = pyo3_asyncio::async_std::local_future_into_py(py, async move {
119119
async_std::task::sleep(Duration::from_secs(*non_send_secs)).await;
120-
Ok(Python::with_gil(|py| py.None()))
120+
Ok(())
121121
})?;
122122

123123
pyo3_asyncio::async_std::into_future(py_future)
@@ -137,7 +137,7 @@ async fn test_cancel() -> PyResult<()> {
137137
async_std::task::sleep(Duration::from_secs(1)).await;
138138
*completed.lock().unwrap() = true;
139139

140-
Ok(Python::with_gil(|py| py.None()))
140+
Ok(())
141141
})?
142142
.into())
143143
})?;
@@ -183,7 +183,7 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> {
183183
async_std::task::sleep(Duration::from_secs(1)).await;
184184
*completed.lock().unwrap() = true;
185185

186-
Ok(Python::with_gil(|py| py.None()))
186+
Ok(())
187187
})?
188188
.into())
189189
})?;
@@ -224,7 +224,7 @@ fn test_mod(_py: Python, m: &PyModule) -> PyResult<()> {
224224
fn sleep(py: Python) -> PyResult<&PyAny> {
225225
pyo3_asyncio::async_std::future_into_py(py, async move {
226226
async_std::task::sleep(Duration::from_millis(500)).await;
227-
Ok(Python::with_gil(|py| py.None()))
227+
Ok(())
228228
})
229229
}
230230

@@ -273,7 +273,7 @@ fn cvars_mod(_py: Python, m: &PyModule) -> PyResult<()> {
273273
})?
274274
.await?;
275275

276-
Ok(Python::with_gil(|py| py.None()))
276+
Ok(())
277277
})
278278
}
279279

pytests/tokio_asyncio/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fn test_local_future_into_py(event_loop: PyObject) -> PyResult<()> {
9595
TaskLocals::new(event_loop.as_ref(py)),
9696
async move {
9797
tokio::time::sleep(Duration::from_secs(*non_send_secs)).await;
98-
Ok(Python::with_gil(|py| py.None()))
98+
Ok(())
9999
},
100100
)?;
101101

@@ -140,7 +140,7 @@ async fn test_cancel() -> PyResult<()> {
140140
tokio::time::sleep(Duration::from_secs(1)).await;
141141
*completed.lock().unwrap() = true;
142142

143-
Ok(Python::with_gil(|py| py.None()))
143+
Ok(())
144144
})?
145145
.into())
146146
})?;
@@ -187,7 +187,7 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> {
187187
Ok(pyo3_asyncio::tokio::local_future_into_py(py, async move {
188188
tokio::time::sleep(Duration::from_secs(1)).await;
189189
*completed.lock().unwrap() = true;
190-
Ok(Python::with_gil(|py| py.None()))
190+
Ok(())
191191
})?
192192
.into())
193193
})?;
@@ -230,7 +230,7 @@ fn test_mod(_py: Python, m: &PyModule) -> PyResult<()> {
230230
fn sleep(py: Python) -> PyResult<&PyAny> {
231231
pyo3_asyncio::tokio::future_into_py(py, async move {
232232
tokio::time::sleep(Duration::from_millis(500)).await;
233-
Ok(Python::with_gil(|py| py.None()))
233+
Ok(())
234234
})
235235
}
236236

@@ -277,7 +277,7 @@ fn cvars_mod(_py: Python, m: &PyModule) -> PyResult<()> {
277277
Python::with_gil(|py| pyo3_asyncio::tokio::into_future(callback.as_ref(py).call0()?))?
278278
.await?;
279279

280-
Ok(Python::with_gil(|py| py.None()))
280+
Ok(())
281281
})
282282
}
283283

0 commit comments

Comments
 (0)