Skip to content

Commit

Permalink
Merge pull request #3669 from davidhewitt/gevent
Browse files Browse the repository at this point in the history
add test which is broken with gevent
  • Loading branch information
adamreichold authored Dec 24, 2023
2 parents e99058a + 49d7718 commit 7d24584
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
1 change: 1 addition & 0 deletions pytests/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ classifiers = [

[project.optional-dependencies]
dev = [
"gevent>=23.9.1",
"hypothesis>=3.55",
"pytest-asyncio>=0.21",
"pytest-benchmark>=3.4",
Expand Down
16 changes: 15 additions & 1 deletion pytests/src/misc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use pyo3::prelude::*;
use pyo3::{prelude::*, types::PyDict};
use std::borrow::Cow;

#[pyfunction]
Expand All @@ -17,10 +17,24 @@ fn accepts_bool(val: bool) -> bool {
val
}

#[pyfunction]
fn get_item_and_run_callback(dict: Bound<'_, PyDict>, callback: Bound<'_, PyAny>) -> PyResult<()> {
// This function gives the opportunity to run a pure-Python callback so that
// gevent can instigate a context switch. This had problematic interactions
// with PyO3's removed "GIL Pool".
// For context, see https://github.com/PyO3/pyo3/issues/3668
let item = dict.get_item("key")?.expect("key not found in dict");
let string = item.to_string();
callback.call0()?;
assert_eq!(item.to_string(), string);
Ok(())
}

#[pymodule]
pub fn misc(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(issue_219, m)?)?;
m.add_function(wrap_pyfunction!(get_type_full_name, m)?)?;
m.add_function(wrap_pyfunction!(accepts_bool, m)?)?;
m.add_function(wrap_pyfunction!(get_item_and_run_callback, m)?)?;
Ok(())
}
37 changes: 37 additions & 0 deletions pytests/tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import platform
import sys

import gevent
import pyo3_pytests.misc
import pytest

Expand Down Expand Up @@ -64,3 +65,39 @@ def test_accepts_numpy_bool():
assert pyo3_pytests.misc.accepts_bool(False) is False
assert pyo3_pytests.misc.accepts_bool(numpy.bool_(True)) is True
assert pyo3_pytests.misc.accepts_bool(numpy.bool_(False)) is False


class ArbitraryClass:
worker_id: int
iteration: int

def __init__(self, worker_id: int, iteration: int):
self.worker_id = worker_id
self.iteration = iteration

def __repr__(self):
return f"ArbitraryClass({self.worker_id}, {self.iteration})"

def __del__(self):
print("del", self.worker_id, self.iteration)


def test_gevent():
def worker(worker_id: int) -> None:
for iteration in range(2):
d = {"key": ArbitraryClass(worker_id, iteration)}

def arbitrary_python_code():
# remove the dictionary entry so that the class value can be
# garbage collected
del d["key"]
print("gevent sleep", worker_id, iteration)
gevent.sleep(0)
print("after gevent sleep", worker_id, iteration)

print("start", worker_id, iteration)
pyo3_pytests.misc.get_item_and_run_callback(d, arbitrary_python_code)
print("end", worker_id, iteration)

workers = [gevent.spawn(worker, i) for i in range(2)]
gevent.joinall(workers)

0 comments on commit 7d24584

Please sign in to comment.