Merge pull request #3669 from davidhewitt/gevent

add test which is broken with gevent
This commit is contained in:
Adam Reichold 2023-12-24 09:25:29 +00:00 committed by GitHub
commit 7d245842d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 1 deletions

View file

@ -20,6 +20,7 @@ classifiers = [
[project.optional-dependencies] [project.optional-dependencies]
dev = [ dev = [
"gevent>=23.9.1",
"hypothesis>=3.55", "hypothesis>=3.55",
"pytest-asyncio>=0.21", "pytest-asyncio>=0.21",
"pytest-benchmark>=3.4", "pytest-benchmark>=3.4",

View file

@ -1,4 +1,4 @@
use pyo3::prelude::*; use pyo3::{prelude::*, types::PyDict};
use std::borrow::Cow; use std::borrow::Cow;
#[pyfunction] #[pyfunction]
@ -17,10 +17,24 @@ fn accepts_bool(val: bool) -> bool {
val 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] #[pymodule]
pub fn misc(_py: Python<'_>, m: &PyModule) -> PyResult<()> { pub fn misc(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(issue_219, m)?)?; m.add_function(wrap_pyfunction!(issue_219, m)?)?;
m.add_function(wrap_pyfunction!(get_type_full_name, m)?)?; m.add_function(wrap_pyfunction!(get_type_full_name, m)?)?;
m.add_function(wrap_pyfunction!(accepts_bool, m)?)?; m.add_function(wrap_pyfunction!(accepts_bool, m)?)?;
m.add_function(wrap_pyfunction!(get_item_and_run_callback, m)?)?;
Ok(()) Ok(())
} }

View file

@ -2,6 +2,7 @@ import importlib
import platform import platform
import sys import sys
import gevent
import pyo3_pytests.misc import pyo3_pytests.misc
import pytest import pytest
@ -64,3 +65,39 @@ def test_accepts_numpy_bool():
assert pyo3_pytests.misc.accepts_bool(False) is False 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_(True)) is True
assert pyo3_pytests.misc.accepts_bool(numpy.bool_(False)) is False 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)