Skip to content

Commit 8b0f70e

Browse files
authored
Merge pull request #80 from awestlake87/release-0.17
Release 0.17 Prep
2 parents bc2d75d + cbe194e commit 8b0f70e

File tree

15 files changed

+270
-101
lines changed

15 files changed

+270
-101
lines changed

.devcontainer/Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/rust/.devcontainer/base.Dockerfile
2+
3+
# [Choice] Debian OS version (use bullseye on local arm64/Apple Silicon): buster, bullseye
4+
ARG VARIANT="buster"
5+
FROM mcr.microsoft.com/vscode/devcontainers/rust:0-${VARIANT}
6+
7+
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
8+
&& apt-get -y install python3-dev python3-pip
9+
10+
RUN python3 -m pip install uvloop

.devcontainer/devcontainer.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
2+
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/rust
3+
{
4+
"name": "Rust",
5+
"build": {
6+
"dockerfile": "Dockerfile",
7+
"args": {
8+
// Use the VARIANT arg to pick a Debian OS version: buster, bullseye
9+
// Use bullseye when on local on arm64/Apple Silicon.
10+
"VARIANT": "buster"
11+
}
12+
},
13+
"runArgs": [
14+
"--cap-add=SYS_PTRACE",
15+
"--security-opt",
16+
"seccomp=unconfined"
17+
],
18+
19+
// Configure tool-specific properties.
20+
"customizations": {
21+
// Configure properties specific to VS Code.
22+
"vscode": {
23+
// Set *default* container specific settings.json values on container create.
24+
"settings": {
25+
"lldb.executable": "/usr/bin/lldb",
26+
// VS Code don't watch files under ./target
27+
"files.watcherExclude": {
28+
"**/target/**": true
29+
},
30+
"rust-analyzer.checkOnSave.command": "clippy"
31+
},
32+
33+
// Add the IDs of extensions you want installed when the container is created.
34+
"extensions": [
35+
"vadimcn.vscode-lldb",
36+
"mutantdino.resourcemonitor",
37+
"rust-lang.rust-analyzer",
38+
"tamasfe.even-better-toml",
39+
"serayuzgur.crates"
40+
]
41+
}
42+
},
43+
44+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
45+
// "forwardPorts": [],
46+
47+
// Use 'postCreateCommand' to run commands after the container is created.
48+
// "postCreateCommand": "rustc --version",
49+
50+
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
51+
"remoteUser": "vscode",
52+
"features": {
53+
"git": "latest",
54+
"git-lfs": "latest"
55+
}
56+
}

.github/workflows/ci.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
steps:
1818
- uses: actions/checkout@v2
1919
- uses: actions/setup-python@v2
20-
- run: pip install black==19.10b0
20+
- run: pip install black==22.8.0
2121
- uses: actions-rs/toolchain@v1
2222
with:
2323
toolchain: stable
@@ -110,6 +110,7 @@ jobs:
110110
python-architecture: "x64",
111111
rust-target: "x86_64-unknown-linux-gnu",
112112
}
113+
msrv: "nightly"
113114
extra_features: "nightly"
114115

115116
steps:
@@ -133,6 +134,16 @@ jobs:
133134
name: Prepare LD_LIBRARY_PATH (Ubuntu only)
134135
run: echo LD_LIBRARY_PATH=${pythonLocation}/lib >> $GITHUB_ENV
135136

137+
- if: matrix.msrv == 'MSRV'
138+
name: Prepare minimal package versions (MSRV only)
139+
run: |
140+
set -x
141+
cargo update -p tokio --precise 1.13.1
142+
cargo update -p indexmap --precise 1.6.2
143+
cargo update -p parking_lot:0.12.1 --precise 0.11.2
144+
cargo update -p async-global-executor --precise 2.2.0
145+
cargo update -p once_cell --precise 1.14.0
146+
136147
- name: Build (no features)
137148
run: cargo build --no-default-features --verbose --target ${{ matrix.platform.rust-target }}
138149

@@ -145,6 +156,14 @@ jobs:
145156
run: |
146157
python -m pip install -U uvloop
147158
159+
- if: ${{ matrix.msrv != 'MSRV' && matrix.python-version != '3.11-dev' && !startsWith(matrix.python-version, 'pypy') }}
160+
name: Test
161+
run: cargo test --all-features --target ${{ matrix.platform.rust-target }}
162+
163+
- if: ${{ matrix.msrv == 'MSRV' && matrix.python-version != '3.11-dev' && !startsWith(matrix.python-version, 'pypy') }}
164+
name: Test (MSRV, --no-default-features)
165+
run: cargo test --no-default-features --features tokio-runtime,async-std-runtime,attributes,unstable-streams --target ${{ matrix.platform.rust-target }}
166+
148167
env:
149168
RUST_BACKTRACE: 1
150169
RUSTFLAGS: "-D warnings"

Cargo.toml

Lines changed: 17 additions & 10 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.16.0"
4+
version = "0.17.0"
55
authors = ["Andrew J Westlake <[email protected]>"]
66
readme = "README.md"
77
keywords = ["pyo3", "python", "ffi", "async", "asyncio"]
@@ -18,7 +18,7 @@ members = ["pyo3-asyncio-macros"]
1818

1919
[features]
2020
async-std-runtime = ["async-std"]
21-
attributes = ["pyo3-asyncio-macros", "inventory"]
21+
attributes = ["pyo3-asyncio-macros"]
2222
testing = ["clap", "inventory"]
2323
tokio-runtime = ["tokio"]
2424
unstable-streams = ["async-channel"]
@@ -102,25 +102,32 @@ path = "pytests/test_tokio_multi_thread_uvloop.rs"
102102
harness = false
103103
required-features = ["tokio-runtime", "testing"]
104104

105+
106+
[[test]]
107+
name = "test_race_condition_regression"
108+
path = "pytests/test_race_condition_regression.rs"
109+
harness = false
110+
required-features = ["async-std-runtime", "testing"]
111+
105112
[dependencies]
106113
async-channel = { version = "1.6", optional = true }
107-
clap = { version = "3.1.5", optional = true }
114+
clap = { version = "3.2", optional = true }
108115
futures = "0.3"
109-
inventory = { version = "0.2", optional = true }
110-
once_cell = "1.5"
116+
inventory = { version = "0.3", optional = true }
117+
once_cell = "1.14"
111118
pin-project-lite = "0.2"
112-
pyo3 = "0.16"
113-
pyo3-asyncio-macros = { path = "pyo3-asyncio-macros", version = "=0.16.0", optional = true }
119+
pyo3 = "0.17"
120+
pyo3-asyncio-macros = { path = "pyo3-asyncio-macros", version = "=0.17.0", optional = true }
114121

115122
[dev-dependencies]
116-
pyo3 = { version = "0.16", features = ["macros"] }
123+
pyo3 = { version = "0.17", features = ["macros"] }
117124

118125
[dependencies.async-std]
119-
version = "1.10"
126+
version = "1.12"
120127
features = ["unstable"]
121128
optional = true
122129

123130
[dependencies.tokio]
124-
version = "1.13"
131+
version = "1.13"
125132
features = ["full"]
126133
optional = true

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ Here we initialize the runtime, import Python's `asyncio` library and run the gi
5252
```toml
5353
# Cargo.toml dependencies
5454
[dependencies]
55-
pyo3 = { version = "0.16" }
56-
pyo3-asyncio = { version = "0.16", features = ["attributes", "async-std-runtime"] }
55+
pyo3 = { version = "0.17" }
56+
pyo3-asyncio = { version = "0.17", features = ["attributes", "async-std-runtime"] }
5757
async-std = "1.9"
5858
```
5959

@@ -82,8 +82,8 @@ attribute.
8282
```toml
8383
# Cargo.toml dependencies
8484
[dependencies]
85-
pyo3 = { version = "0.16" }
86-
pyo3-asyncio = { version = "0.16", features = ["attributes", "tokio-runtime"] }
85+
pyo3 = { version = "0.17" }
86+
pyo3-asyncio = { version = "0.17", features = ["attributes", "tokio-runtime"] }
8787
tokio = "1.9"
8888
```
8989

@@ -127,17 +127,17 @@ For `async-std`:
127127

128128
```toml
129129
[dependencies]
130-
pyo3 = { version = "0.16", features = ["extension-module"] }
131-
pyo3-asyncio = { version = "0.16", features = ["async-std-runtime"] }
130+
pyo3 = { version = "0.17", features = ["extension-module"] }
131+
pyo3-asyncio = { version = "0.17", features = ["async-std-runtime"] }
132132
async-std = "1.9"
133133
```
134134

135135
For `tokio`:
136136

137137
```toml
138138
[dependencies]
139-
pyo3 = { version = "0.16", features = ["extension-module"] }
140-
pyo3-asyncio = { version = "0.16", features = ["tokio-runtime"] }
139+
pyo3 = { version = "0.17", features = ["extension-module"] }
140+
pyo3-asyncio = { version = "0.17", features = ["tokio-runtime"] }
141141
tokio = "1.9"
142142
```
143143

@@ -431,8 +431,8 @@ name = "my_async_module"
431431
crate-type = ["cdylib"]
432432

433433
[dependencies]
434-
pyo3 = { version = "0.16", features = ["extension-module"] }
435-
pyo3-asyncio = { version = "0.16", features = ["tokio-runtime"] }
434+
pyo3 = { version = "0.17", features = ["extension-module"] }
435+
pyo3-asyncio = { version = "0.17", features = ["tokio-runtime"] }
436436
async-std = "1.9"
437437
tokio = "1.9"
438438
```
@@ -491,8 +491,8 @@ event loop before we can install the `uvloop` policy.
491491
```toml
492492
[dependencies]
493493
async-std = "1.9"
494-
pyo3 = "0.16"
495-
pyo3-asyncio = { version = "0.16", features = ["async-std-runtime"] }
494+
pyo3 = "0.17"
495+
pyo3-asyncio = { version = "0.17", features = ["async-std-runtime"] }
496496
```
497497

498498
```rust no_run

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.16.0"
4+
version = "0.17.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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use pyo3::prelude::*;
44
use pyo3_asyncio::TaskLocals;
55

66
pub(super) const TEST_MOD: &'static str = r#"
7-
import asyncio
7+
import asyncio
88
99
async def py_sleep(duration):
1010
await asyncio.sleep(duration)

pytests/test_async_std_asyncio.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use std::{
99
use async_std::task;
1010
use pyo3::{
1111
prelude::*,
12-
proc_macro::pymodule,
1312
types::{IntoPyDict, PyType},
1413
wrap_pyfunction, wrap_pymodule,
1514
};
@@ -174,12 +173,12 @@ async fn test_cancel() -> PyResult<()> {
174173

175174
#[cfg(feature = "unstable-streams")]
176175
const ASYNC_STD_TEST_MOD: &str = r#"
177-
import asyncio
176+
import asyncio
178177
179178
async def gen():
180179
for i in range(10):
181180
await asyncio.sleep(0.1)
182-
yield i
181+
yield i
183182
"#;
184183

185184
#[cfg(feature = "unstable-streams")]
@@ -257,15 +256,15 @@ fn test_local_cancel(event_loop: PyObject) -> PyResult<()> {
257256
#[pymodule]
258257
fn test_mod(_py: Python, m: &PyModule) -> PyResult<()> {
259258
#![allow(deprecated)]
260-
#[pyfunction]
261-
fn sleep(py: Python) -> PyResult<&PyAny> {
259+
#[pyfunction(name = "sleep")]
260+
fn sleep_(py: Python) -> PyResult<&PyAny> {
262261
pyo3_asyncio::async_std::future_into_py(py, async move {
263262
async_std::task::sleep(Duration::from_millis(500)).await;
264263
Ok(())
265264
})
266265
}
267266

268-
m.add_function(wrap_pyfunction!(sleep, m)?)?;
267+
m.add_function(wrap_pyfunction!(sleep_, m)?)?;
269268

270269
Ok(())
271270
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use pyo3::{prelude::*, wrap_pyfunction};
2+
3+
#[pyfunction]
4+
fn sleep<'p>(py: Python<'p>, secs: &'p PyAny) -> PyResult<&'p PyAny> {
5+
let secs = secs.extract()?;
6+
7+
pyo3_asyncio::async_std::future_into_py(py, async move {
8+
async_std::task::sleep(std::time::Duration::from_secs_f64(secs)).await;
9+
Ok(())
10+
})
11+
}
12+
13+
const RACE_CONDITION_REGRESSION_TEST: &str = r#"
14+
import asyncio
15+
import random
16+
17+
async def trigger_race_condition(rust_sleeper, delay):
18+
coro = asyncio.wrap_future(rust_sleeper(0.1))
19+
await asyncio.sleep(delay)
20+
coro.cancel()
21+
22+
def main(rust_sleeper):
23+
race_condition_triggered = False
24+
25+
for i in range(1000):
26+
delay = random.uniform(0.099, 0.101)
27+
loop = asyncio.new_event_loop()
28+
loop.set_debug(True)
29+
30+
def custom_exception_handler(loop, context):
31+
nonlocal race_condition_triggered
32+
race_condition_triggered = True
33+
34+
try:
35+
loop.set_exception_handler(custom_exception_handler)
36+
loop.run_until_complete(trigger_race_condition(rust_sleeper, delay))
37+
38+
if race_condition_triggered:
39+
raise Exception("Race condition triggered")
40+
41+
finally:
42+
loop.run_until_complete(loop.shutdown_asyncgens())
43+
if hasattr(loop, 'shutdown_default_executor'):
44+
loop.run_until_complete(loop.shutdown_default_executor())
45+
loop.close()
46+
"#;
47+
48+
fn main() -> pyo3::PyResult<()> {
49+
pyo3::prepare_freethreaded_python();
50+
51+
Python::with_gil(|py| -> PyResult<()> {
52+
let sleeper_mod = PyModule::new(py, "rust_sleeper")?;
53+
54+
sleeper_mod.add_wrapped(wrap_pyfunction!(sleep))?;
55+
56+
let test_mod = PyModule::from_code(
57+
py,
58+
RACE_CONDITION_REGRESSION_TEST,
59+
"race_condition_regression_test.py",
60+
"race_condition_regression_test",
61+
)?;
62+
63+
test_mod.call_method1("main", (sleeper_mod.getattr("sleep")?,))?;
64+
Ok(())
65+
})
66+
}

0 commit comments

Comments
 (0)