Use Python:;with_gil in tests

This commit is contained in:
mejrs 2022-07-19 19:34:23 +02:00
parent 2b6d59f889
commit 984fdf57c7
40 changed files with 2621 additions and 2737 deletions

View File

@ -5,8 +5,7 @@ use pyo3::types::IntoPyDict;
use std::collections::{BTreeMap, HashMap};
fn iter_dict(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let mut sum = 0;
@ -16,18 +15,18 @@ fn iter_dict(b: &mut Bencher<'_>) {
sum += i;
}
});
})
}
fn dict_new(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 50_000;
b.iter(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py));
});
}
fn dict_get_item(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 50_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let mut sum = 0;
@ -36,31 +35,32 @@ fn dict_get_item(b: &mut Bencher<'_>) {
sum += dict.get_item(i).unwrap().extract::<usize>().unwrap();
}
});
});
}
fn extract_hashmap(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
b.iter(|| HashMap::<u64, u64>::extract(dict));
});
}
fn extract_btreemap(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
b.iter(|| BTreeMap::<u64, u64>::extract(dict));
});
}
#[cfg(feature = "hashbrown")]
fn extract_hashbrown_map(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
b.iter(|| hashbrown::HashMap::<u64, u64>::extract(dict));
});
}
fn criterion_benchmark(c: &mut Criterion) {

View File

@ -13,7 +13,7 @@ fn bench_clean_gilpool_new(b: &mut Bencher<'_>) {
fn bench_clean_acquire_gil(b: &mut Bencher<'_>) {
// Acquiring first GIL will also create a "clean" GILPool, so this measures the Python overhead.
b.iter(|| {
let _ = Python::acquire_gil();
let _ = Python::with_gil(|_| {});
});
}
@ -25,7 +25,7 @@ fn bench_dirty_acquire_gil(b: &mut Bencher<'_>) {
let _ = obj.clone();
},
|_| {
let _ = Python::acquire_gil();
let _ = Python::with_gil(|_| {});
},
BatchSize::NumBatches(1),
);

View File

@ -4,8 +4,7 @@ use pyo3::prelude::*;
use pyo3::types::PyList;
fn iter_list(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let list = PyList::new(py, 0..LEN);
let mut sum = 0;
@ -15,18 +14,18 @@ fn iter_list(b: &mut Bencher<'_>) {
sum += i;
}
});
});
}
fn list_new(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 50_000;
b.iter(|| PyList::new(py, 0..LEN));
});
}
fn list_get_item(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 50_000;
let list = PyList::new(py, 0..LEN);
let mut sum = 0;
@ -35,12 +34,12 @@ fn list_get_item(b: &mut Bencher<'_>) {
sum += list.get_item(i).unwrap().extract::<usize>().unwrap();
}
});
});
}
#[cfg(not(Py_LIMITED_API))]
fn list_get_item_unchecked(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 50_000;
let list = PyList::new(py, 0..LEN);
let mut sum = 0;
@ -51,6 +50,7 @@ fn list_get_item_unchecked(b: &mut Bencher<'_>) {
}
}
});
});
}
fn criterion_benchmark(c: &mut Criterion) {

View File

@ -27,14 +27,14 @@ impl MyClass {
}
pub fn first_time_init(b: &mut criterion::Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
b.iter(|| {
// This is using an undocumented internal PyO3 API to measure pyclass performance; please
// don't use this in your own code!
let ty = LazyStaticType::new();
ty.get_or_init::<MyClass>(py);
});
});
}
fn criterion_benchmark(c: &mut Criterion) {

View File

@ -3,13 +3,13 @@ use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use pyo3::prelude::*;
fn drop_many_objects(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
b.iter(|| {
for _ in 0..1000 {
std::mem::drop(py.None());
}
});
});
}
fn criterion_benchmark(c: &mut Criterion) {

View File

@ -5,8 +5,7 @@ use pyo3::types::PySet;
use std::collections::{BTreeSet, HashSet};
fn iter_set(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
let mut sum = 0;
@ -16,31 +15,32 @@ fn iter_set(b: &mut Bencher<'_>) {
sum += i;
}
});
});
}
fn extract_hashset(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
b.iter(|| HashSet::<u64>::extract(set));
});
}
fn extract_btreeset(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
b.iter(|| BTreeSet::<u64>::extract(set));
});
}
#[cfg(feature = "hashbrown")]
fn extract_hashbrown_set(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
b.iter(|| hashbrown::HashSet::<u64>::extract(set));
});
}
fn criterion_benchmark(c: &mut Criterion) {

View File

@ -4,8 +4,7 @@ use pyo3::prelude::*;
use pyo3::types::PyTuple;
fn iter_tuple(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 100_000;
let tuple = PyTuple::new(py, 0..LEN);
let mut sum = 0;
@ -15,18 +14,18 @@ fn iter_tuple(b: &mut Bencher<'_>) {
sum += i;
}
});
});
}
fn tuple_new(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 50_000;
b.iter(|| PyTuple::new(py, 0..LEN));
});
}
fn tuple_get_item(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 50_000;
let tuple = PyTuple::new(py, 0..LEN);
let mut sum = 0;
@ -35,12 +34,12 @@ fn tuple_get_item(b: &mut Bencher<'_>) {
sum += tuple.get_item(i).unwrap().extract::<usize>().unwrap();
}
});
});
}
#[cfg(not(Py_LIMITED_API))]
fn tuple_get_item_unchecked(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 50_000;
let tuple = PyTuple::new(py, 0..LEN);
let mut sum = 0;
@ -51,6 +50,7 @@ fn tuple_get_item_unchecked(b: &mut Bencher<'_>) {
}
}
});
});
}
fn criterion_benchmark(c: &mut Criterion) {

View File

@ -796,12 +796,12 @@ mod tests {
#[test]
fn set_typeerror() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let err: PyErr = exceptions::PyTypeError::new_err(());
err.restore(py);
assert!(PyErr::occurred(py));
drop(PyErr::fetch(py));
});
}
#[test]

View File

@ -41,15 +41,14 @@ impl UnaryArithmetic {
#[test]
fn unary_arithmetic() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
py_run!(py, c, "assert repr(+c) == 'UA(2.7)'");
py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'");
py_run!(py, c, "assert repr(round(c)) == 'UA(3)'");
py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'");
});
}
#[pyclass]
@ -135,8 +134,7 @@ impl InPlaceOperations {
#[test]
fn inplace_operations() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let init = |value, code| {
let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
py_run!(py, c, code);
@ -155,6 +153,7 @@ fn inplace_operations() {
3,
"d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
);
});
}
#[pyclass]
@ -205,9 +204,7 @@ impl BinaryArithmetic {
#[test]
fn binary_arithmetic() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, BinaryArithmetic {}).unwrap();
py_run!(py, c, "assert c + c == 'BA + BA'");
py_run!(py, c, "assert c.__add__(c) == 'BA + BA'");
@ -235,6 +232,7 @@ fn binary_arithmetic() {
py_expect_exception!(py, c, "1 ** c", PyTypeError);
py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'");
});
}
#[pyclass]
@ -281,9 +279,7 @@ impl RhsArithmetic {
#[test]
fn rhs_arithmetic() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, RhsArithmetic {}).unwrap();
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
py_run!(py, c, "assert 1 + c == '1 + RA'");
@ -303,6 +299,7 @@ fn rhs_arithmetic() {
py_run!(py, c, "assert 1 | c == '1 | RA'");
py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
py_run!(py, c, "assert 1 ** c == '1 ** RA'");
});
}
#[pyclass]
@ -411,9 +408,7 @@ impl LhsAndRhs {
#[test]
fn lhs_fellback_to_rhs() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, LhsAndRhs {}).unwrap();
// If the light hand value is `LhsAndRhs`, LHS is used.
py_run!(py, c, "assert c + 1 == 'LR + 1'");
@ -437,6 +432,7 @@ fn lhs_fellback_to_rhs() {
py_run!(py, c, "assert 1 | c == '1 | RA'");
py_run!(py, c, "assert 1 ** c == '1 ** RA'");
py_run!(py, c, "assert 1 @ c == '1 @ RA'");
});
}
#[pyclass]
@ -480,9 +476,7 @@ impl RichComparisons2 {
#[test]
fn rich_comparisons() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, RichComparisons {}).unwrap();
py_run!(py, c, "assert (c < c) == 'RC < RC'");
py_run!(py, c, "assert (c < 1) == 'RC < 1'");
@ -502,13 +496,12 @@ fn rich_comparisons() {
py_run!(py, c, "assert (c >= c) == 'RC >= RC'");
py_run!(py, c, "assert (c >= 1) == 'RC >= 1'");
py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
});
}
#[test]
fn rich_comparisons_python_3_type_error() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
py_expect_exception!(py, c2, "c2 < c2", PyTypeError);
py_expect_exception!(py, c2, "c2 < 1", PyTypeError);
@ -528,6 +521,7 @@ fn rich_comparisons_python_3_type_error() {
py_expect_exception!(py, c2, "c2 >= c2", PyTypeError);
py_expect_exception!(py, c2, "c2 >= 1", PyTypeError);
py_expect_exception!(py, c2, "1 >= c2", PyTypeError);
});
}
// Checks that binary operations for which the arguments don't match the
@ -608,8 +602,7 @@ mod return_not_implemented {
}
fn _test_binary_dunder(dunder: &str) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
py_run!(
py,
@ -619,13 +612,13 @@ mod return_not_implemented {
dunder
)
);
});
}
fn _test_binary_operator(operator: &str, dunder: &str) {
_test_binary_dunder(dunder);
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
py_expect_exception!(
py,
@ -633,6 +626,7 @@ mod return_not_implemented {
&format!("class Other: pass\nc2 {} Other()", operator),
PyTypeError
);
});
}
fn _test_inplace_binary_operator(operator: &str, dunder: &str) {

View File

@ -44,13 +44,12 @@ impl PyNumberProtocol for UnaryArithmetic {
#[test]
fn unary_arithmetic() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
py_run!(py, c, "assert repr(+c) == 'UA(2.7)'");
py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'");
});
}
#[pyclass]
@ -115,8 +114,7 @@ impl PyNumberProtocol for InPlaceOperations {
}
#[test]
fn inplace_operations() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let init = |value, code| {
let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
py_run!(py, c, code);
@ -135,6 +133,7 @@ fn inplace_operations() {
3,
"d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
);
});
}
#[pyproto]
@ -182,9 +181,7 @@ impl PyNumberProtocol for BinaryArithmetic {
#[test]
fn binary_arithmetic() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, BinaryArithmetic {}).unwrap();
py_run!(py, c, "assert c + c == 'BA + BA'");
py_run!(py, c, "assert c.__add__(c) == 'BA + BA'");
@ -211,6 +208,7 @@ fn binary_arithmetic() {
py_run!(py, c, "assert 1 ** c == '1 ** BA (mod: None)'");
py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'");
});
}
#[pyclass]
@ -261,9 +259,7 @@ impl PyNumberProtocol for RhsArithmetic {
#[test]
fn rhs_arithmetic() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, RhsArithmetic {}).unwrap();
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
py_run!(py, c, "assert 1 + c == '1 + RA'");
@ -285,6 +281,7 @@ fn rhs_arithmetic() {
py_run!(py, c, "assert 1 | c == '1 | RA'");
py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
py_run!(py, c, "assert 1 ** c == '1 ** RA'");
});
}
#[pyclass]
@ -396,9 +393,7 @@ impl PyObjectProtocol for LhsAndRhs {
#[test]
fn lhs_fellback_to_rhs() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, LhsAndRhs {}).unwrap();
// If the light hand value is `LhsAndRhs`, LHS is used.
py_run!(py, c, "assert c + 1 == 'LR + 1'");
@ -424,6 +419,7 @@ fn lhs_fellback_to_rhs() {
py_run!(py, c, "assert 1 | c == '1 | RA'");
py_run!(py, c, "assert 1 ** c == '1 ** RA'");
py_run!(py, c, "assert 1 @ c == '1 @ RA'");
});
}
#[pyclass]
@ -467,9 +463,7 @@ impl PyObjectProtocol for RichComparisons2 {
#[test]
fn rich_comparisons() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, RichComparisons {}).unwrap();
py_run!(py, c, "assert (c < c) == 'RC < RC'");
py_run!(py, c, "assert (c < 1) == 'RC < 1'");
@ -489,13 +483,12 @@ fn rich_comparisons() {
py_run!(py, c, "assert (c >= c) == 'RC >= RC'");
py_run!(py, c, "assert (c >= 1) == 'RC >= 1'");
py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
});
}
#[test]
fn rich_comparisons_python_3_type_error() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
py_expect_exception!(py, c2, "c2 < c2", PyTypeError);
py_expect_exception!(py, c2, "c2 < 1", PyTypeError);
@ -515,6 +508,7 @@ fn rich_comparisons_python_3_type_error() {
py_expect_exception!(py, c2, "c2 >= c2", PyTypeError);
py_expect_exception!(py, c2, "c2 >= 1", PyTypeError);
py_expect_exception!(py, c2, "1 >= c2", PyTypeError);
});
}
// Checks that binary operations for which the arguments don't match the
@ -598,8 +592,7 @@ mod return_not_implemented {
}
fn _test_binary_dunder(dunder: &str) {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
py_run!(
py,
@ -609,13 +602,13 @@ mod return_not_implemented {
dunder
)
);
});
}
fn _test_binary_operator(operator: &str, dunder: &str) {
_test_binary_dunder(dunder);
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
py_expect_exception!(
py,
@ -623,6 +616,7 @@ mod return_not_implemented {
&format!("class Other: pass\nc2 {} Other()", operator),
PyTypeError
);
});
}
fn _test_inplace_binary_operator(operator: &str, dunder: &str) {

View File

@ -87,8 +87,7 @@ fn test_buffer() {
let drop_called = Arc::new(AtomicBool::new(false));
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let instance = Py::new(
py,
TestBufferClass {
@ -99,6 +98,7 @@ fn test_buffer() {
.unwrap();
let env = [("ob", instance)].into_py_dict(py);
py_assert!(py, *env, "bytes(ob) == b' 23'");
});
}
assert!(drop_called.load(Ordering::Relaxed));
@ -110,8 +110,7 @@ fn test_buffer_referenced() {
let buf = {
let input = vec![b' ', b'2', b'3'];
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let instance: PyObject = TestBufferClass {
vec: input.clone(),
drop_called: drop_called.clone(),
@ -122,14 +121,14 @@ fn test_buffer_referenced() {
assert_eq!(buf.to_vec(py).unwrap(), input);
drop(instance);
buf
})
};
assert!(!drop_called.load(Ordering::Relaxed));
{
let _py = Python::acquire_gil().python();
Python::with_gil(|_| {
drop(buf);
}
});
assert!(drop_called.load(Ordering::Relaxed));
}

View File

@ -85,9 +85,7 @@ impl Drop for TestBufferClass {
fn test_buffer() {
let drop_called = Arc::new(AtomicBool::new(false));
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let instance = Py::new(
py,
TestBufferClass {
@ -98,7 +96,7 @@ fn test_buffer() {
.unwrap();
let env = [("ob", instance)].into_py_dict(py);
py_assert!(py, *env, "bytes(ob) == b' 23'");
}
});
assert!(drop_called.load(Ordering::Relaxed));
}
@ -107,10 +105,9 @@ fn test_buffer() {
fn test_buffer_referenced() {
let drop_called = Arc::new(AtomicBool::new(false));
let buf = {
let buf: PyBuffer<u8> = {
let input = vec![b' ', b'2', b'3'];
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let instance: PyObject = TestBufferClass {
vec: input.clone(),
drop_called: drop_called.clone(),
@ -121,14 +118,14 @@ fn test_buffer_referenced() {
assert_eq!(buf.to_vec(py).unwrap(), input);
drop(instance);
buf
})
};
assert!(!drop_called.load(Ordering::Relaxed));
{
let _py = Python::acquire_gil().python();
Python::with_gil(|_| {
drop(buf);
}
});
assert!(drop_called.load(Ordering::Relaxed));
}

View File

@ -12,11 +12,10 @@ fn bytes_pybytes_conversion(bytes: &[u8]) -> &[u8] {
#[test]
fn test_pybytes_bytes_conversion() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let f = wrap_pyfunction!(bytes_pybytes_conversion)(py).unwrap();
py_assert!(py, f, "f(b'Hello World') == b'Hello World'");
});
}
#[pyfunction]
@ -26,33 +25,26 @@ fn bytes_vec_conversion(py: Python<'_>, bytes: Vec<u8>) -> &PyBytes {
#[test]
fn test_pybytes_vec_conversion() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();
py_assert!(py, f, "f(b'Hello World') == b'Hello World'");
});
}
#[test]
fn test_bytearray_vec_conversion() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();
py_assert!(py, f, "f(bytearray(b'Hello World')) == b'Hello World'");
});
}
#[test]
fn test_py_as_bytes() {
let pyobj: pyo3::Py<pyo3::types::PyBytes>;
let data: &[u8];
let pyobj: pyo3::Py<pyo3::types::PyBytes> =
Python::with_gil(|py| pyo3::types::PyBytes::new(py, b"abc").into_py(py));
{
let gil = Python::acquire_gil();
let py = gil.python();
pyobj = pyo3::types::PyBytes::new(py, b"abc").into_py(py);
data = pyobj.as_bytes(py);
}
let data = Python::with_gil(|py| pyobj.as_bytes(py));
assert_eq!(data, b"abc");
}

View File

@ -54,8 +54,7 @@ impl Foo {
#[test]
fn class_attributes() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let foo_obj = py.get_type::<Foo>();
py_assert!(py, foo_obj, "foo_obj.MY_CONST == 'foobar'");
py_assert!(py, foo_obj, "foo_obj.RENAMED_CONST == 'foobar_2'");
@ -63,6 +62,7 @@ fn class_attributes() {
py_assert!(py, foo_obj, "foo_obj.B == 'bar'");
py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1");
py_assert!(py, foo_obj, "foo_obj.a_foo_with_py.x == 1");
});
}
// Ignored because heap types are not immutable:
@ -70,10 +70,10 @@ fn class_attributes() {
#[test]
#[ignore]
fn class_attributes_are_immutable() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let foo_obj = py.get_type::<Foo>();
py_expect_exception!(py, foo_obj, "foo_obj.a = 6", PyTypeError);
});
}
#[pymethods]
@ -86,14 +86,13 @@ impl Bar {
#[test]
fn recursive_class_attributes() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let foo_obj = py.get_type::<Foo>();
let bar_obj = py.get_type::<Bar>();
py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1");
py_assert!(py, foo_obj, "foo_obj.bar.x == 2");
py_assert!(py, bar_obj, "bar_obj.a_foo.x == 3");
});
}
#[test]

View File

@ -11,13 +11,13 @@ struct EmptyClass {}
#[test]
fn empty_class() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<EmptyClass>();
// By default, don't allow creating instances from python.
assert!(typeobj.call((), None).is_err());
py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
});
}
#[pyclass]
@ -56,9 +56,7 @@ struct ClassWithDocs {
#[test]
fn class_with_docstr() {
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<ClassWithDocs>();
py_run!(
py,
@ -80,7 +78,7 @@ fn class_with_docstr() {
typeobj,
"assert typeobj.writeonly.__doc__ == 'Write-only property field'"
);
}
});
}
#[pyclass(name = "CustomName")]
@ -104,8 +102,7 @@ impl EmptyClass2 {
#[test]
fn custom_names() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<EmptyClass2>();
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
py_assert!(py, typeobj, "typeobj.custom_fn.__name__ == 'custom_fn'");
@ -122,6 +119,7 @@ fn custom_names() {
py_assert!(py, typeobj, "not hasattr(typeobj, 'bar')");
py_assert!(py, typeobj, "not hasattr(typeobj, 'bar_static')");
py_assert!(py, typeobj, "not hasattr(typeobj, 'foo')");
});
}
#[pyclass]
@ -137,12 +135,12 @@ impl RawIdents {
#[test]
fn test_raw_idents() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<RawIdents>();
py_assert!(py, typeobj, "not hasattr(typeobj, 'r#fn')");
py_assert!(py, typeobj, "hasattr(typeobj, 'fn')");
py_assert!(py, typeobj, "hasattr(typeobj, 'type')");
});
}
#[pyclass]
@ -154,8 +152,7 @@ struct EmptyClassInModule {}
#[test]
#[ignore]
fn empty_class_in_module() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let module = PyModule::new(py, "test_module.nested").unwrap();
module.add_class::<EmptyClassInModule>().unwrap();
@ -171,6 +168,7 @@ fn empty_class_in_module() {
// We currently have no way of determining a canonical module, so builtins is better
// than using whatever calls init first.
assert_eq!(module, "builtins");
});
}
#[pyclass]
@ -191,11 +189,11 @@ impl ClassWithObjectField {
#[test]
fn class_with_object_field() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let ty = py.get_type::<ClassWithObjectField>();
py_assert!(py, ty, "ty(5).value == 5");
py_assert!(py, ty, "ty(None).value == None");
});
}
#[pyclass(unsendable, subclass)]
@ -355,8 +353,7 @@ struct DunderDictSupport {
#[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn dunder_dict_support() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(
py,
DunderDictSupport {
@ -372,14 +369,14 @@ fn dunder_dict_support() {
assert inst.a == 1
"#
);
});
}
// Accessing inst.__dict__ only supported in limited API from Python 3.10
#[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]
fn access_dunder_dict() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(
py,
DunderDictSupport {
@ -395,6 +392,7 @@ fn access_dunder_dict() {
assert inst.__dict__ == {'a': 1}
"#
);
});
}
// If the base class has dict support, child class also has dict
@ -406,8 +404,7 @@ struct InheritDict {
#[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn inherited_dict() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(
py,
(
@ -426,6 +423,7 @@ fn inherited_dict() {
assert inst.a == 1
"#
);
});
}
#[pyclass(weakref, dict)]
@ -437,8 +435,7 @@ struct WeakRefDunderDictSupport {
#[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn weakref_dunder_dict_support() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(
py,
WeakRefDunderDictSupport {
@ -451,6 +448,7 @@ fn weakref_dunder_dict_support() {
inst,
"import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1"
);
});
}
#[pyclass(weakref, subclass)]
@ -461,8 +459,7 @@ struct WeakRefSupport {
#[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn weakref_support() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(
py,
WeakRefSupport {
@ -475,6 +472,7 @@ fn weakref_support() {
inst,
"import weakref; assert weakref.ref(inst)() is inst"
);
});
}
// If the base class has weakref support, child class also has weakref.
@ -486,8 +484,7 @@ struct InheritWeakRef {
#[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn inherited_weakref() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(
py,
(
@ -503,4 +500,5 @@ fn inherited_weakref() {
inst,
"import weakref; assert weakref.ref(inst)() is inst"
);
});
}

View File

@ -16,9 +16,7 @@ struct Cloneable {
fn test_cloneable_pyclass() {
let c = Cloneable { x: 10 };
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let py_c = Py::new(py, c.clone()).unwrap().to_object(py);
let c2: Cloneable = py_c.extract(py).unwrap();
@ -30,6 +28,7 @@ fn test_cloneable_pyclass() {
}
let mrc: PyRefMut<'_, Cloneable> = py_c.extract(py).unwrap();
assert_eq!(&c, &*mrc);
});
}
#[pyclass(subclass)]
@ -63,9 +62,7 @@ struct PolymorphicContainer {
#[test]
fn test_polymorphic_container_stores_base_class() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let p = PyCell::new(
py,
PolymorphicContainer {
@ -76,13 +73,12 @@ fn test_polymorphic_container_stores_base_class() {
.to_object(py);
py_assert!(py, p, "p.inner.foo() == 'BaseClass'");
});
}
#[test]
fn test_polymorphic_container_stores_sub_class() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let p = PyCell::new(
py,
PolymorphicContainer {
@ -104,13 +100,12 @@ fn test_polymorphic_container_stores_sub_class() {
.unwrap();
py_assert!(py, p, "p.inner.foo() == 'SubClass'");
});
}
#[test]
fn test_polymorphic_container_does_not_accept_other_types() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let p = PyCell::new(
py,
PolymorphicContainer {
@ -125,13 +120,12 @@ fn test_polymorphic_container_does_not_accept_other_types() {
assert!(setattr(1i32.into_py(py)).is_err());
assert!(setattr(py.None()).is_err());
assert!(setattr((1i32, 2i32).into_py(py)).is_err());
});
}
#[test]
fn test_pyref_as_base() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let cell = PyCell::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap();
// First try PyRefMut
@ -146,13 +140,12 @@ fn test_pyref_as_base() {
let sub: PyRef<'_, SubClass> = cell.borrow();
let base: PyRef<'_, BaseClass> = sub.into_super();
assert_eq!(999, base.value);
});
}
#[test]
fn test_pycell_deref() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let cell = PyCell::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap();
// Should be able to deref as PyAny
@ -162,4 +155,5 @@ fn test_pycell_deref() {
.unwrap(),
"SubClass"
);
});
}

View File

@ -16,14 +16,14 @@ impl EmptyClassWithNew {
#[test]
fn empty_class_with_new() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<EmptyClassWithNew>();
assert!(typeobj
.call((), None)
.unwrap()
.cast_as::<PyCell<EmptyClassWithNew>>()
.is_ok());
});
}
#[pyclass]
@ -87,13 +87,13 @@ impl NewWithOneArg {
#[test]
fn new_with_one_arg() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<NewWithOneArg>();
let wrp = typeobj.call((42,), None).unwrap();
let obj = wrp.cast_as::<PyCell<NewWithOneArg>>().unwrap();
let obj_ref = obj.borrow();
assert_eq!(obj_ref._data, 42);
});
}
#[pyclass]
@ -115,8 +115,7 @@ impl NewWithTwoArgs {
#[test]
fn new_with_two_args() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<NewWithTwoArgs>();
let wrp = typeobj
.call((10, 20), None)
@ -126,6 +125,7 @@ fn new_with_two_args() {
let obj_ref = obj.borrow();
assert_eq!(obj_ref._data1, 10);
assert_eq!(obj_ref._data2, 20);
});
}
#[pyclass(subclass)]
@ -146,8 +146,7 @@ impl SuperClass {
/// See https://github.com/PyO3/pyo3/issues/947 for the corresponding bug.
#[test]
fn subclass_new() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let super_cls = py.get_type::<SuperClass>();
let source = pyo3::indoc::indoc!(
r#"
@ -167,6 +166,7 @@ assert c.from_rust is False
py.run(source, Some(globals), None)
.map_err(|e| e.print(py))
.unwrap();
});
}
#[pyclass]
@ -191,9 +191,9 @@ impl NewWithCustomError {
#[test]
fn new_with_custom_error() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<NewWithCustomError>();
let err = typeobj.call0().unwrap_err();
assert_eq!(err.to_string(), "ValueError: custom error");
});
}

View File

@ -55,31 +55,30 @@ macro_rules! assert_check_only {
#[test]
fn test_date_check() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "date", "2018, 1, 1").unwrap();
unsafe { PyDateTime_IMPORT() }
assert_check_exact!(PyDate_Check, PyDate_CheckExact, obj);
assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_obj);
assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_sub_obj);
});
}
#[test]
fn test_time_check() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "time", "12, 30, 15").unwrap();
unsafe { PyDateTime_IMPORT() }
assert_check_exact!(PyTime_Check, PyTime_CheckExact, obj);
assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_obj);
assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_sub_obj);
});
}
#[test]
fn test_datetime_check() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "datetime", "2018, 1, 1, 13, 30, 15")
.map_err(|e| e.print(py))
.unwrap();
@ -89,18 +88,19 @@ fn test_datetime_check() {
assert_check_exact!(PyDateTime_Check, PyDateTime_CheckExact, obj);
assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_obj);
assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_sub_obj);
});
}
#[test]
fn test_delta_check() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "timedelta", "1, -3").unwrap();
unsafe { PyDateTime_IMPORT() }
assert_check_exact!(PyDelta_Check, PyDelta_CheckExact, obj);
assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_obj);
assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_sub_obj);
});
}
#[test]
@ -108,8 +108,7 @@ fn test_datetime_utc() {
use assert_approx_eq::assert_approx_eq;
use pyo3::types::PyDateTime;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let utc = timezone_utc(py);
let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(utc)).unwrap();
@ -122,6 +121,7 @@ fn test_datetime_utc() {
.extract()
.unwrap();
assert_approx_eq!(offset, 0f32);
});
}
static INVALID_DATES: &[(i32, u8, u8)] = &[
@ -143,26 +143,26 @@ static INVALID_TIMES: &[(u8, u8, u8, u32)] =
fn test_pydate_out_of_bounds() {
use pyo3::types::PyDate;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
for val in INVALID_DATES {
let (year, month, day) = val;
let dt = PyDate::new(py, *year, *month, *day);
dt.unwrap_err();
}
});
}
#[test]
fn test_pytime_out_of_bounds() {
use pyo3::types::PyTime;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
for val in INVALID_TIMES {
let (hour, minute, second, microsecond) = val;
let dt = PyTime::new(py, *hour, *minute, *second, *microsecond, None);
dt.unwrap_err();
}
});
}
#[test]
@ -170,8 +170,7 @@ fn test_pydatetime_out_of_bounds() {
use pyo3::types::PyDateTime;
use std::iter;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let valid_time = (0, 0, 0, 0);
let valid_date = (2018, 1, 1);
@ -197,4 +196,5 @@ fn test_pydatetime_out_of_bounds() {
);
dt.unwrap_err();
}
});
}

View File

@ -4,8 +4,7 @@ use pyo3::types::IntoPyDict;
#[test]
#[cfg_attr(target_arch = "wasm32", ignore)] // Not sure why this fails.
fn iter_dict_nosegv() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
const LEN: usize = 10_000_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let mut sum = 0;
@ -14,4 +13,5 @@ fn iter_dict_nosegv() {
sum += i;
}
assert_eq!(sum, 49_999_995_000_000);
});
}

View File

@ -28,12 +28,12 @@ fn return_enum() -> MyEnum {
#[test]
fn test_return_enum() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let f = wrap_pyfunction!(return_enum)(py).unwrap();
let mynum = py.get_type::<MyEnum>();
py_run!(py, f mynum, "assert f() == mynum.Variant")
});
}
#[pyfunction]

View File

@ -20,8 +20,7 @@ fn fail_to_open_file() -> PyResult<()> {
#[cfg_attr(target_arch = "wasm32", ignore)] // Not sure why this fails.
#[cfg(not(target_os = "windows"))]
fn test_filenotfounderror() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let fail_to_open_file = wrap_pyfunction!(fail_to_open_file)(py).unwrap();
py_run!(
@ -34,6 +33,7 @@ fn test_filenotfounderror() {
assert str(e) == "No such file or directory (os error 2)"
"#
);
});
}
#[derive(Debug)]
@ -65,9 +65,9 @@ fn call_fail_with_custom_error() -> PyResult<()> {
#[test]
fn test_custom_error() {
let gil = Python::acquire_gil();
let py = gil.python();
let call_fail_with_custom_error = wrap_pyfunction!(call_fail_with_custom_error)(py).unwrap();
Python::with_gil(|py| {
let call_fail_with_custom_error =
wrap_pyfunction!(call_fail_with_custom_error)(py).unwrap();
py_run!(
py,
@ -79,6 +79,7 @@ fn test_custom_error() {
assert str(e) == "Oh no!"
"#
);
});
}
#[test]

View File

@ -15,27 +15,21 @@ struct ClassWithFreelist {}
#[test]
fn class_with_freelist() {
let ptr;
{
let gil = Python::acquire_gil();
let py = gil.python();
let ptr = Python::with_gil(|py| {
let inst = Py::new(py, ClassWithFreelist {}).unwrap();
let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap();
ptr = inst.as_ptr();
let ptr = inst.as_ptr();
drop(inst);
}
{
let gil = Python::acquire_gil();
let py = gil.python();
ptr
});
Python::with_gil(|py| {
let inst3 = Py::new(py, ClassWithFreelist {}).unwrap();
assert_eq!(ptr, inst3.as_ptr());
let inst4 = Py::new(py, ClassWithFreelist {}).unwrap();
assert_ne!(ptr, inst4.as_ptr())
}
});
}
struct TestDropCall {
@ -60,9 +54,7 @@ fn data_is_dropped() {
let drop_called1 = Arc::new(AtomicBool::new(false));
let drop_called2 = Arc::new(AtomicBool::new(false));
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let data_is_dropped = DataIsDropped {
member1: TestDropCall {
drop_called: Arc::clone(&drop_called1),
@ -75,7 +67,7 @@ fn data_is_dropped() {
assert!(!drop_called1.load(Ordering::Relaxed));
assert!(!drop_called2.load(Ordering::Relaxed));
drop(inst);
}
});
assert!(drop_called1.load(Ordering::Relaxed));
assert!(drop_called2.load(Ordering::Relaxed));
@ -95,8 +87,9 @@ impl GcIntegration {
}
fn __clear__(&mut self) {
let gil = Python::acquire_gil();
self.self_ref = gil.python().None();
Python::with_gil(|py| {
self.self_ref = py.None();
});
}
}
@ -104,9 +97,7 @@ impl GcIntegration {
fn gc_integration() {
let drop_called = Arc::new(AtomicBool::new(false));
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(
py,
GcIntegration {
@ -122,12 +113,12 @@ fn gc_integration() {
borrow.self_ref = inst.to_object(py);
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
}
});
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
py.run("import gc; gc.collect()", None, None).unwrap();
assert!(drop_called.load(Ordering::Relaxed));
});
}
#[pyclass(subclass)]
@ -180,9 +171,7 @@ fn inheritance_with_new_methods_with_drop() {
let drop_called1 = Arc::new(AtomicBool::new(false));
let drop_called2 = Arc::new(AtomicBool::new(false));
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let _typebase = py.get_type::<BaseClassWithDrop>();
let typeobj = py.get_type::<SubClassWithDrop>();
let inst = typeobj.call((), None).unwrap();
@ -192,7 +181,7 @@ fn inheritance_with_new_methods_with_drop() {
obj_ref_mut.data = Some(Arc::clone(&drop_called1));
let base: &mut BaseClassWithDrop = obj_ref_mut.as_mut();
base.data = Some(Arc::clone(&drop_called2));
}
});
assert!(drop_called1.load(Ordering::Relaxed));
assert!(drop_called2.load(Ordering::Relaxed));
@ -228,9 +217,7 @@ unsafe fn get_type_traverse(tp: *mut pyo3::ffi::PyTypeObject) -> Option<pyo3::ff
#[test]
fn gc_during_borrow() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
unsafe {
// declare a dummy visitor function
extern "C" fn novisit(
@ -262,6 +249,7 @@ fn gc_during_borrow() {
assert!(!guard.traversed.load(Ordering::Relaxed));
drop(guard);
}
});
}
#[pyclass]

View File

@ -17,27 +17,21 @@ struct ClassWithFreelist {}
#[test]
fn class_with_freelist() {
let ptr;
{
let gil = Python::acquire_gil();
let py = gil.python();
let ptr = Python::with_gil(|py| {
let inst = Py::new(py, ClassWithFreelist {}).unwrap();
let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap();
ptr = inst.as_ptr();
let ptr = inst.as_ptr();
drop(inst);
}
{
let gil = Python::acquire_gil();
let py = gil.python();
ptr
});
Python::with_gil(|py| {
let inst3 = Py::new(py, ClassWithFreelist {}).unwrap();
assert_eq!(ptr, inst3.as_ptr());
let inst4 = Py::new(py, ClassWithFreelist {}).unwrap();
assert_ne!(ptr, inst4.as_ptr())
}
});
}
struct TestDropCall {
@ -62,9 +56,7 @@ fn data_is_dropped() {
let drop_called1 = Arc::new(AtomicBool::new(false));
let drop_called2 = Arc::new(AtomicBool::new(false));
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let data_is_dropped = DataIsDropped {
member1: TestDropCall {
drop_called: Arc::clone(&drop_called1),
@ -77,7 +69,7 @@ fn data_is_dropped() {
assert!(!drop_called1.load(Ordering::Relaxed));
assert!(!drop_called2.load(Ordering::Relaxed));
drop(inst);
}
});
assert!(drop_called1.load(Ordering::Relaxed));
assert!(drop_called2.load(Ordering::Relaxed));
@ -97,8 +89,9 @@ impl PyGCProtocol for GcIntegration {
}
fn __clear__(&mut self) {
let gil = Python::acquire_gil();
self.self_ref = gil.python().None();
Python::with_gil(|py| {
self.self_ref = py.None();
})
}
}
@ -106,9 +99,7 @@ impl PyGCProtocol for GcIntegration {
fn gc_integration() {
let drop_called = Arc::new(AtomicBool::new(false));
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(
py,
GcIntegration {
@ -122,12 +113,12 @@ fn gc_integration() {
let mut borrow = inst.borrow_mut();
borrow.self_ref = inst.to_object(py);
}
});
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
py.run("import gc; gc.collect()", None, None).unwrap();
assert!(drop_called.load(Ordering::Relaxed));
});
}
#[pyclass]
@ -143,10 +134,10 @@ impl PyGCProtocol for GcIntegration2 {
#[test]
fn gc_integration2() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(py, GcIntegration2 {}).unwrap();
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
});
}
#[pyclass(subclass)]
@ -199,9 +190,7 @@ fn inheritance_with_new_methods_with_drop() {
let drop_called1 = Arc::new(AtomicBool::new(false));
let drop_called2 = Arc::new(AtomicBool::new(false));
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let _typebase = py.get_type::<BaseClassWithDrop>();
let typeobj = py.get_type::<SubClassWithDrop>();
let inst = typeobj.call((), None).unwrap();
@ -211,7 +200,7 @@ fn inheritance_with_new_methods_with_drop() {
obj_ref_mut.data = Some(Arc::clone(&drop_called1));
let base: &mut BaseClassWithDrop = obj_ref_mut.as_mut();
base.data = Some(Arc::clone(&drop_called2));
}
});
assert!(drop_called1.load(Ordering::Relaxed));
assert!(drop_called2.load(Ordering::Relaxed));
@ -245,9 +234,7 @@ unsafe fn get_type_traverse(tp: *mut pyo3::ffi::PyTypeObject) -> Option<pyo3::ff
#[test]
fn gc_during_borrow() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
unsafe {
// declare a dummy visitor function
extern "C" fn novisit(
@ -279,4 +266,5 @@ fn gc_during_borrow() {
assert!(!guard.traversed.load(Ordering::Relaxed));
drop(guard);
}
});
}

View File

@ -46,9 +46,7 @@ impl ClassWithProperties {
#[test]
fn class_with_properties() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(py, ClassWithProperties { num: 10 }).unwrap();
py_run!(py, inst, "assert inst.get_num() == 10");
@ -65,6 +63,7 @@ fn class_with_properties() {
let d = [("C", py.get_type::<ClassWithProperties>())].into_py_dict(py);
py_assert!(py, *d, "C.DATA.__doc__ == 'a getter for data'");
});
}
#[pyclass]
@ -84,9 +83,7 @@ impl GetterSetter {
#[test]
fn getter_setter_autogen() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(
py,
GetterSetter {
@ -103,6 +100,7 @@ fn getter_setter_autogen() {
inst,
"assert inst.text == 'Hello'; inst.text = 'There'; assert inst.text == 'There'"
);
});
}
#[pyclass]
@ -126,13 +124,12 @@ impl RefGetterSetter {
#[test]
fn ref_getter_setter() {
// Regression test for #837
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(py, RefGetterSetter { num: 10 }).unwrap();
py_run!(py, inst, "assert inst.num == 10");
py_run!(py, inst, "inst.num = 20; assert inst.num == 20");
});
}
#[pyclass]
@ -153,12 +150,11 @@ impl TupleClassGetterSetter {
#[test]
fn tuple_struct_getter_setter() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(py, TupleClassGetterSetter(10)).unwrap();
py_assert!(py, inst, "inst.num == 10");
py_run!(py, inst, "inst.num = 20");
py_assert!(py, inst, "inst.num == 20");
});
}

View File

@ -18,8 +18,7 @@ struct SubclassAble {}
#[test]
fn subclass() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [("SubclassAble", py.get_type::<SubclassAble>())].into_py_dict(py);
py.run(
@ -29,6 +28,7 @@ fn subclass() {
)
.map_err(|e| e.print(py))
.unwrap();
});
}
#[pymethods]
@ -70,17 +70,16 @@ impl SubClass {
#[test]
fn inheritance_with_new_methods() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<SubClass>();
let inst = typeobj.call((), None).unwrap();
py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5");
});
}
#[test]
fn call_base_and_sub_methods() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let obj = PyCell::new(py, SubClass::new()).unwrap();
py_run!(
py,
@ -90,25 +89,24 @@ fn call_base_and_sub_methods() {
assert obj.sub_method(10) == 50
"#
);
});
}
#[test]
fn mutation_fails() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let obj = PyCell::new(py, SubClass::new()).unwrap();
let global = Some([("obj", obj)].into_py_dict(py));
let e = py
.run("obj.base_set(lambda: obj.sub_set_and_ret(1))", global, None)
.unwrap_err();
assert_eq!(&e.to_string(), "RuntimeError: Already borrowed")
assert_eq!(&e.to_string(), "RuntimeError: Already borrowed");
});
}
#[test]
fn is_subclass_and_is_instance() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let sub_ty = SubClass::type_object(py);
let base_ty = BaseClass::type_object(py);
assert!(sub_ty.is_subclass_of::<BaseClass>().unwrap());
@ -119,6 +117,7 @@ fn is_subclass_and_is_instance() {
assert!(obj.is_instance_of::<BaseClass>().unwrap());
assert!(obj.is_instance(sub_ty).unwrap());
assert!(obj.is_instance(base_ty).unwrap());
});
}
#[pyclass(subclass)]
@ -150,8 +149,7 @@ impl SubClass2 {
#[test]
fn handle_result_in_new() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let subclass = py.get_type::<SubClass2>();
py_run!(
py,
@ -166,6 +164,7 @@ except Exception as e:
raise e
"#
);
});
}
// Subclassing builtin types is not allowed in the LIMITED API.
@ -197,14 +196,14 @@ mod inheriting_native_type {
}
}
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let set_sub = pyo3::PyCell::new(py, SetWithName::new()).unwrap();
py_run!(
py,
set_sub,
r#"set_sub.add(10); assert list(set_sub) == [10]; assert set_sub.name == "Hello :)""#
);
});
}
#[pyclass(extends=PyDict)]
@ -224,14 +223,14 @@ mod inheriting_native_type {
#[test]
fn inherit_dict() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let dict_sub = pyo3::PyCell::new(py, DictWithName::new()).unwrap();
py_run!(
py,
dict_sub,
r#"dict_sub[0] = 1; assert dict_sub[0] == 1; assert dict_sub.name == "Hello :)""#
);
});
}
#[test]

View File

@ -75,20 +75,19 @@ fn map_dict(py: Python<'_>) -> &pyo3::types::PyDict {
#[test]
fn test_getitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = map_dict(py);
py_assert!(py, *d, "m['1'] == 0");
py_assert!(py, *d, "m['2'] == 1");
py_assert!(py, *d, "m['3'] == 2");
py_expect_exception!(py, *d, "print(m['4'])", PyKeyError);
});
}
#[test]
fn test_setitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = map_dict(py);
py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4");
@ -96,13 +95,12 @@ fn test_setitem() {
py_assert!(py, *d, "len(m) == 4");
py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError);
py_expect_exception!(py, *d, "m[0] = -1", PyTypeError);
});
}
#[test]
fn test_delitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = map_dict(py);
py_run!(
py,
@ -111,6 +109,7 @@ fn test_delitem() {
);
py_expect_exception!(py, *d, "del m[-1]", PyTypeError);
py_expect_exception!(py, *d, "del m['4']", PyKeyError);
});
}
#[test]

View File

@ -72,20 +72,19 @@ fn map_dict(py: Python<'_>) -> &pyo3::types::PyDict {
#[test]
fn test_getitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = map_dict(py);
py_assert!(py, *d, "m['1'] == 0");
py_assert!(py, *d, "m['2'] == 1");
py_assert!(py, *d, "m['3'] == 2");
py_expect_exception!(py, *d, "print(m['4'])", PyKeyError);
});
}
#[test]
fn test_setitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = map_dict(py);
py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4");
@ -93,13 +92,12 @@ fn test_setitem() {
py_assert!(py, *d, "len(m) == 4");
py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError);
py_expect_exception!(py, *d, "m[0] = -1", PyTypeError);
});
}
#[test]
fn test_delitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = map_dict(py);
py_run!(
py,
@ -108,4 +106,5 @@ fn test_delitem() {
);
py_expect_exception!(py, *d, "del m[-1]", PyTypeError);
py_expect_exception!(py, *d, "del m['4']", PyKeyError);
});
}

View File

@ -27,15 +27,14 @@ impl InstanceMethod {
#[test]
fn instance_method() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let obj = PyCell::new(py, InstanceMethod { member: 42 }).unwrap();
let obj_ref = obj.borrow();
assert_eq!(obj_ref.method(), 42);
py_assert!(py, obj, "obj.method() == 42");
py_assert!(py, obj, "obj.add_other(obj) == 84");
py_assert!(py, obj, "obj.method.__doc__ == 'Test method'");
});
}
#[pyclass]
@ -52,14 +51,13 @@ impl InstanceMethodWithArgs {
#[test]
fn instance_method_with_args() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let obj = PyCell::new(py, InstanceMethodWithArgs { member: 7 }).unwrap();
let obj_ref = obj.borrow();
assert_eq!(obj_ref.method(6), 42);
py_assert!(py, obj, "obj.method(3) == 21");
py_assert!(py, obj, "obj.method(multiplier=6) == 42");
});
}
#[pyclass]
@ -81,14 +79,13 @@ impl ClassMethod {
#[test]
fn class_method() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [("C", py.get_type::<ClassMethod>())].into_py_dict(py);
py_assert!(py, *d, "C.method() == 'ClassMethod.method()!'");
py_assert!(py, *d, "C().method() == 'ClassMethod.method()!'");
py_assert!(py, *d, "C.method.__doc__ == 'Test class method.'");
py_assert!(py, *d, "C().method.__doc__ == 'Test class method.'");
});
}
#[pyclass]
@ -104,15 +101,14 @@ impl ClassMethodWithArgs {
#[test]
fn class_method_with_args() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [("C", py.get_type::<ClassMethodWithArgs>())].into_py_dict(py);
py_assert!(
py,
*d,
"C.method('abc') == 'ClassMethodWithArgs.method(abc)'"
);
});
}
#[pyclass]
@ -134,9 +130,7 @@ impl StaticMethod {
#[test]
fn static_method() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
assert_eq!(StaticMethod::method(py), "StaticMethod.method()!");
let d = [("C", py.get_type::<StaticMethod>())].into_py_dict(py);
@ -144,6 +138,7 @@ fn static_method() {
py_assert!(py, *d, "C().method() == 'StaticMethod.method()!'");
py_assert!(py, *d, "C.method.__doc__ == 'Test static method.'");
py_assert!(py, *d, "C().method.__doc__ == 'Test static method.'");
});
}
#[pyclass]
@ -159,13 +154,12 @@ impl StaticMethodWithArgs {
#[test]
fn static_method_with_args() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
assert_eq!(StaticMethodWithArgs::method(py, 1234), "0x4d2");
let d = [("C", py.get_type::<StaticMethodWithArgs>())].into_py_dict(py);
py_assert!(py, *d, "C.method(1337) == '0x539'");
});
}
#[pyclass]
@ -305,8 +299,7 @@ impl MethArgs {
#[test]
fn meth_args() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(py, MethArgs {}).unwrap();
py_run!(py, inst, "assert inst.get_optional() == 10");
@ -614,6 +607,7 @@ fn meth_args() {
py_expect_exception!(py, inst, "inst.get_pos_kw(1,2)", PyTypeError);
py_run!(py, inst, "assert inst.args_as_vec(1,2,3) == 6");
});
}
#[pyclass]
@ -638,8 +632,7 @@ impl MethDocs {
#[test]
fn meth_doc() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [("C", py.get_type::<MethDocs>())].into_py_dict(py);
py_assert!(py, *d, "C.__doc__ == 'A class with \"documentation\".'");
py_assert!(
@ -652,6 +645,7 @@ fn meth_doc() {
*d,
"C.x.__doc__ == '`int`: a very \"important\" member of \\'this\\' instance.'"
);
});
}
#[pyclass]
@ -672,14 +666,14 @@ impl MethodWithLifeTime {
#[test]
fn method_with_lifetime() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let obj = PyCell::new(py, MethodWithLifeTime {}).unwrap();
py_run!(
py,
obj,
"assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]"
);
});
}
#[pyclass]
@ -720,8 +714,7 @@ impl MethodWithPyClassArg {
#[test]
fn method_with_pyclassarg() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let obj1 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap();
let obj2 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap();
let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py);
@ -749,6 +742,7 @@ fn method_with_pyclassarg() {
*d,
"obj1.optional_inplace_add(obj2); assert obj2.value == 40"
);
});
}
#[pyclass]
@ -783,8 +777,7 @@ impl CfgStruct {
#[test]
fn test_cfg_attrs() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(py, CfgStruct {}).unwrap();
#[cfg(unix)]
@ -800,6 +793,7 @@ fn test_cfg_attrs() {
}
py_assert!(py, inst, "not hasattr(inst, 'never_compiled_method')");
});
}
#[pyclass]
@ -825,10 +819,10 @@ impl FromSequence {
#[test]
fn test_from_sequence() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<FromSequence>();
py_assert!(py, typeobj, "typeobj(range(0, 4)).numbers == [0, 1, 2, 3]")
py_assert!(py, typeobj, "typeobj(range(0, 4)).numbers == [0, 1, 2, 3]");
});
}
#[pyclass]

View File

@ -67,9 +67,7 @@ fn module_with_functions(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
fn test_module_with_functions() {
use pyo3::wrap_pymodule;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [(
"module_with_functions",
wrap_pymodule!(module_with_functions)(py),
@ -112,6 +110,7 @@ fn test_module_with_functions() {
*d,
"module_with_functions.with_module() == 'module_with_functions'"
);
});
}
#[pymodule]
@ -125,19 +124,16 @@ fn some_name(_: Python<'_>, m: &PyModule) -> PyResult<()> {
fn test_module_renaming() {
use pyo3::wrap_pymodule;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [("different_name", wrap_pymodule!(some_name)(py))].into_py_dict(py);
py_run!(py, *d, "assert different_name.__name__ == 'other_name'");
});
}
#[test]
fn test_module_from_code() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let adder_mod = PyModule::from_code(
py,
"def add(a,b):\n\treturn a+b",
@ -158,6 +154,7 @@ fn test_module_from_code() {
.expect("The value should be able to be converted to an i32");
assert_eq!(ret_value, 3);
});
}
#[pyfunction]
@ -174,12 +171,11 @@ fn raw_ident_module(_py: Python<'_>, module: &PyModule) -> PyResult<()> {
fn test_raw_idents() {
use pyo3::wrap_pymodule;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let module = wrap_pymodule!(raw_ident_module)(py);
py_assert!(py, module, "module.move() == 42");
});
}
#[pyfunction]
@ -197,31 +193,30 @@ fn foobar_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
#[test]
fn test_custom_names() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let module = pyo3::wrap_pymodule!(foobar_module)(py);
py_assert!(py, module, "not hasattr(module, 'custom_named_fn')");
py_assert!(py, module, "module.foobar() == 42");
});
}
#[test]
fn test_module_dict() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let module = pyo3::wrap_pymodule!(foobar_module)(py);
py_assert!(py, module, "module.yay == 'me'");
});
}
#[test]
fn test_module_dunder_all() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let module = pyo3::wrap_pymodule!(foobar_module)(py);
py_assert!(py, module, "module.__all__ == ['foobar']");
});
}
#[pyfunction]
@ -261,8 +256,7 @@ fn supermodule(py: Python<'_>, module: &PyModule) -> PyResult<()> {
fn test_module_nesting() {
use pyo3::wrap_pymodule;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let supermodule = wrap_pymodule!(supermodule)(py);
py_assert!(
@ -280,6 +274,7 @@ fn test_module_nesting() {
supermodule,
"supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'"
);
});
}
// Test that argument parsing specification works for pyfunctions
@ -302,8 +297,7 @@ fn vararg_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
#[test]
fn test_vararg_module() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let m = pyo3::wrap_pymodule!(vararg_module)(py);
py_assert!(py, m, "m.ext_vararg_fn() == [5, ()]");
@ -311,6 +305,7 @@ fn test_vararg_module() {
py_assert!(py, m, "m.int_vararg_fn() == [5, ()]");
py_assert!(py, m, "m.int_vararg_fn(1, 2) == [1, (2,)]");
});
}
#[test]
@ -397,8 +392,7 @@ fn module_with_functions_with_module(_py: Python<'_>, m: &PyModule) -> PyResult<
#[test]
fn test_module_functions_with_module() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let m = pyo3::wrap_pymodule!(module_with_functions_with_module)(py);
py_assert!(
py,
@ -427,6 +421,7 @@ fn test_module_functions_with_module() {
m,
"m.pyfunction_with_pass_module_in_attribute() == 'module_with_functions_with_module'"
);
});
}
#[test]

View File

@ -377,9 +377,7 @@ impl Iterator {
#[test]
fn iterator() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(
py,
Iterator {
@ -389,6 +387,7 @@ fn iterator() {
.unwrap();
py_assert!(py, inst, "iter(inst) is inst");
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
});
}
#[pyclass]
@ -406,15 +405,14 @@ struct NotCallable;
#[test]
fn callable() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = Py::new(py, Callable).unwrap();
py_assert!(py, c, "callable(c)");
py_assert!(py, c, "c(7) == 42");
let nc = Py::new(py, NotCallable).unwrap();
py_assert!(py, nc, "not callable(nc)");
});
}
#[pyclass]
@ -434,9 +432,7 @@ impl SetItem {
#[test]
fn setitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, SetItem { key: 0, val: 0 }).unwrap();
py_run!(py, c, "c[1] = 2");
{
@ -445,6 +441,7 @@ fn setitem() {
assert_eq!(c.val, 2);
}
py_expect_exception!(py, c, "del c[1]", PyNotImplementedError);
});
}
#[pyclass]
@ -461,9 +458,7 @@ impl DelItem {
#[test]
fn delitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, DelItem { key: 0 }).unwrap();
py_run!(py, c, "del c[1]");
{
@ -471,6 +466,7 @@ fn delitem() {
assert_eq!(c.key, 1);
}
py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError);
});
}
#[pyclass]
@ -491,9 +487,7 @@ impl SetDelItem {
#[test]
fn setdelitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, SetDelItem { val: None }).unwrap();
py_run!(py, c, "c[1] = 2");
{
@ -503,6 +497,7 @@ fn setdelitem() {
py_run!(py, c, "del c[1]");
let c = c.borrow();
assert_eq!(c.val, None);
});
}
#[pyclass]
@ -517,13 +512,12 @@ impl Contains {
#[test]
fn contains() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = Py::new(py, Contains {}).unwrap();
py_run!(py, c, "assert 1 in c");
py_run!(py, c, "assert -1 not in c");
py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError);
});
}
#[pyclass]
@ -548,13 +542,12 @@ impl GetItem {
#[test]
fn test_getitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let ob = Py::new(py, GetItem {}).unwrap();
py_assert!(py, ob, "ob[1] == 'int'");
py_assert!(py, ob, "ob[100:200:1] == 'slice'");
});
}
#[pyclass]
@ -572,11 +565,11 @@ impl ClassWithGetAttr {
#[test]
fn getattr_doesnt_override_member() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(py, ClassWithGetAttr { data: 4 }).unwrap();
py_assert!(py, inst, "inst.data == 4");
py_assert!(py, inst, "inst.a == 8");
});
}
#[pyclass]
@ -594,11 +587,11 @@ impl ClassWithGetAttribute {
#[test]
fn getattribute_overrides_member() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(py, ClassWithGetAttribute { data: 4 }).unwrap();
py_assert!(py, inst, "inst.data == 8");
py_assert!(py, inst, "inst.y == 8");
});
}
#[pyclass]
@ -627,13 +620,13 @@ impl ClassWithGetAttrAndGetAttribute {
#[test]
fn getattr_and_getattribute() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(py, ClassWithGetAttrAndGetAttribute).unwrap();
py_assert!(py, inst, "inst.exists == 42");
py_assert!(py, inst, "inst.lucky == 57");
py_expect_exception!(py, inst, "inst.error", PyValueError);
py_expect_exception!(py, inst, "inst.unlucky", PyAttributeError);
});
}
/// Wraps a Python future and yield it once.
@ -674,8 +667,7 @@ impl OnceFuture {
#[test]
#[cfg(not(target_arch = "wasm32"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop)
fn test_await() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let once = py.get_type::<OnceFuture>();
let source = r#"
import asyncio
@ -696,6 +688,7 @@ asyncio.run(main())
py.run(source, Some(globals), None)
.map_err(|e| e.print(py))
.unwrap();
});
}
#[pyclass]
@ -724,8 +717,7 @@ impl AsyncIterator {
#[test]
#[cfg(not(target_arch = "wasm32"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop)
fn test_anext_aiter() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let once = py.get_type::<OnceFuture>();
let source = r#"
import asyncio
@ -753,6 +745,7 @@ asyncio.run(main())
py.run(source, Some(globals), None)
.map_err(|e| e.print(py))
.unwrap();
});
}
/// Increment the count when `__get__` is called.
@ -789,8 +782,7 @@ impl DescrCounter {
#[test]
fn descr_getset() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let counter = py.get_type::<DescrCounter>();
let source = pyo3::indoc::indoc!(
r#"
@ -822,6 +814,7 @@ assert c.counter.count == 1
py.run(source, Some(globals), None)
.map_err(|e| e.print(py))
.unwrap();
});
}
#[pyclass]

View File

@ -17,14 +17,14 @@ fn optional_bool(arg: Option<bool>) -> String {
#[test]
fn test_optional_bool() {
// Regression test for issue #932
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let f = wrap_pyfunction!(optional_bool)(py).unwrap();
py_assert!(py, f, "f() == 'Some(true)'");
py_assert!(py, f, "f(True) == 'Some(true)'");
py_assert!(py, f, "f(False) == 'Some(false)'");
py_assert!(py, f, "f(None) == 'None'");
});
}
#[cfg(not(Py_LIMITED_API))]
@ -41,8 +41,7 @@ fn buffer_inplace_add(py: Python<'_>, x: PyBuffer<i32>, y: PyBuffer<i32>) {
#[cfg(not(Py_LIMITED_API))]
#[test]
fn test_buffer_add() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let f = wrap_pyfunction!(buffer_inplace_add)(py).unwrap();
py_expect_exception!(
@ -68,6 +67,7 @@ f(a, b)
assert a, array.array("i", [2, 4, 6, 8])
"#
);
});
}
#[cfg(not(Py_LIMITED_API))]
@ -83,8 +83,7 @@ fn function_with_pycfunction_arg(fun: &PyCFunction) -> PyResult<&PyAny> {
#[test]
fn test_functions_with_function_args() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let py_cfunc_arg = wrap_pyfunction!(function_with_pycfunction_arg)(py).unwrap();
let bool_to_string = wrap_pyfunction!(optional_bool)(py).unwrap();
@ -110,6 +109,7 @@ fn test_functions_with_function_args() {
"#
);
}
});
}
#[cfg(not(Py_LIMITED_API))]
@ -131,9 +131,7 @@ fn function_with_custom_conversion(
#[cfg(not(Py_LIMITED_API))]
#[test]
fn test_function_with_custom_conversion() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();
pyo3::py_run!(
@ -146,14 +144,13 @@ fn test_function_with_custom_conversion() {
assert custom_conv_func(dt) == 1612040400
"#
)
});
}
#[cfg(not(Py_LIMITED_API))]
#[test]
fn test_function_with_custom_conversion_error() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();
py_expect_exception!(
@ -163,6 +160,7 @@ fn test_function_with_custom_conversion_error() {
PyTypeError,
"argument 'timestamp': 'list' object cannot be converted to 'PyDateTime'"
);
});
}
#[pyclass]
@ -188,9 +186,7 @@ fn conversion_error(
#[test]
fn test_conversion_error() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let conversion_error = wrap_pyfunction!(conversion_error)(py).unwrap();
py_expect_exception!(
py,
@ -258,6 +254,7 @@ conversion_error('string1', -100, ('string2', 10.), None, ValueClass(-5))",
"TypeError: argument 'struct_arg': failed to \
extract field ValueClass.value: OverflowError: can't convert negative int to unsigned"
);
});
}
/// Helper function that concatenates the error message from
@ -277,9 +274,7 @@ fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String {
fn test_pycfunction_new() {
use pyo3::ffi;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
unsafe extern "C" fn c_fn(
_self: *mut ffi::PyObject,
_args: *mut ffi::PyObject,
@ -301,6 +296,7 @@ fn test_pycfunction_new() {
py_fn,
"py_fn.__doc__ == 'py_fn for test (this is the docstring)'"
);
});
}
#[test]
@ -310,9 +306,7 @@ fn test_pycfunction_new_with_keywords() {
use std::os::raw::{c_char, c_long};
use std::ptr;
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
unsafe extern "C" fn c_fn(
_self: *mut ffi::PyObject,
args: *mut ffi::PyObject,
@ -333,7 +327,14 @@ fn test_pycfunction_new_with_keywords() {
let arg_pattern: *const c_char = CString::new("l|l").unwrap().into_raw();
ffi::PyArg_ParseTupleAndKeywords(args, kwds, arg_pattern, arglist_ptr, foo_ptr, bar_ptr);
ffi::PyArg_ParseTupleAndKeywords(
args,
kwds,
arg_pattern,
arglist_ptr,
foo_ptr,
bar_ptr,
);
ffi::PyLong_FromLong(foo * bar)
}
@ -353,16 +354,14 @@ fn test_pycfunction_new_with_keywords() {
py_fn,
"py_fn.__doc__ == 'py_fn for test (this is the docstring)'"
);
});
}
#[test]
fn test_closure() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let f = |args: &types::PyTuple, _kwargs: Option<&types::PyDict>| -> PyResult<_> {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let res: Vec<_> = args
.iter()
.map(|elem| {
@ -379,6 +378,7 @@ fn test_closure() {
})
.collect();
Ok(res)
})
};
let closure_py = PyCFunction::new_closure(f, py).unwrap();
@ -388,13 +388,12 @@ fn test_closure() {
closure_py,
"closure_py(42, 3.14, 'foo') == [43, 6.28, 'foo-py']"
);
});
}
#[test]
fn test_closure_counter() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let counter = std::cell::RefCell::new(0);
let counter_fn =
move |_args: &types::PyTuple, _kwargs: Option<&types::PyDict>| -> PyResult<i32> {
@ -407,6 +406,7 @@ fn test_closure_counter() {
py_assert!(py, counter_py, "counter_py() == 1");
py_assert!(py, counter_py, "counter_py() == 2");
py_assert!(py, counter_py, "counter_py() == 3");
});
}
#[test]

View File

@ -29,9 +29,7 @@ impl PyMappingProtocol for Len {
#[test]
fn len() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(py, Len { l: 10 }).unwrap();
py_assert!(py, inst, "len(inst) == 10");
unsafe {
@ -47,6 +45,7 @@ fn len() {
)
.unwrap();
py_expect_exception!(py, inst, "len(inst)", PyOverflowError);
});
}
#[pyclass]
@ -67,9 +66,7 @@ impl PyIterProtocol for Iterator {
#[test]
fn iterator() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(
py,
Iterator {
@ -79,6 +76,7 @@ fn iterator() {
.unwrap();
py_assert!(py, inst, "iter(inst) is inst");
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
});
}
#[pyclass]
@ -97,12 +95,11 @@ impl PyObjectProtocol for StringMethods {
#[test]
fn string_methods() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let obj = Py::new(py, StringMethods {}).unwrap();
py_assert!(py, obj, "str(obj) == 'str'");
py_assert!(py, obj, "repr(obj) == 'repr'");
});
}
#[pyclass]
@ -122,9 +119,7 @@ impl PyObjectProtocol for Comparisons {
#[test]
fn comparisons() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let zero = Py::new(py, Comparisons { val: 0 }).unwrap();
let one = Py::new(py, Comparisons { val: 1 }).unwrap();
let ten = Py::new(py, Comparisons { val: 10 }).unwrap();
@ -135,6 +130,7 @@ fn comparisons() {
py_assert!(py, one, "bool(one) is True");
py_assert!(py, zero, "not zero");
});
}
#[pyclass]
@ -181,9 +177,7 @@ impl PySequenceProtocol for Sequence {
#[test]
fn sequence() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = Py::new(py, Sequence::default()).unwrap();
py_assert!(py, c, "list(c) == ['A', 'B', 'C', 'D', 'E', 'F', 'G']");
py_assert!(py, c, "c[-1] == 'G'");
@ -196,6 +190,7 @@ fn sequence() {
"#
);
py_expect_exception!(py, c, "c['abc']", PyTypeError);
});
}
#[pyclass]
@ -215,9 +210,7 @@ impl PyMappingProtocol for SetItem {
#[test]
fn setitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, SetItem { key: 0, val: 0 }).unwrap();
py_run!(py, c, "c[1] = 2");
{
@ -226,6 +219,7 @@ fn setitem() {
assert_eq!(c.val, 2);
}
py_expect_exception!(py, c, "del c[1]", PyNotImplementedError);
});
}
#[pyclass]
@ -242,9 +236,7 @@ impl PyMappingProtocol<'a> for DelItem {
#[test]
fn delitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, DelItem { key: 0 }).unwrap();
py_run!(py, c, "del c[1]");
{
@ -252,6 +244,7 @@ fn delitem() {
assert_eq!(c.key, 1);
}
py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError);
});
}
#[pyclass]
@ -272,9 +265,7 @@ impl PyMappingProtocol for SetDelItem {
#[test]
fn setdelitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = PyCell::new(py, SetDelItem { val: None }).unwrap();
py_run!(py, c, "c[1] = 2");
{
@ -284,6 +275,7 @@ fn setdelitem() {
py_run!(py, c, "del c[1]");
let c = c.borrow();
assert_eq!(c.val, None);
});
}
#[pyclass]
@ -298,26 +290,24 @@ impl PySequenceProtocol for Contains {
#[test]
fn contains() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let c = Py::new(py, Contains {}).unwrap();
py_run!(py, c, "assert 1 in c");
py_run!(py, c, "assert -1 not in c");
py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError);
});
}
#[test]
fn test_basics() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let v = PySlice::new(py, 1, 10, 2);
let indices = v.indices(100).unwrap();
assert_eq!(1, indices.start);
assert_eq!(10, indices.stop);
assert_eq!(2, indices.step);
assert_eq!(5, indices.slicelength);
});
}
#[pyclass]
@ -342,13 +332,12 @@ impl<'p> PyMappingProtocol<'p> for Test {
#[test]
fn test_cls_impl() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let ob = Py::new(py, Test {}).unwrap();
py_assert!(py, ob, "ob[1] == 'int'");
py_assert!(py, ob, "ob[100:200:1] == 'slice'");
});
}
#[pyclass]
@ -366,11 +355,11 @@ impl PyObjectProtocol for ClassWithGetAttr {
#[test]
fn getattr_doesnt_override_member() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = PyCell::new(py, ClassWithGetAttr { data: 4 }).unwrap();
py_assert!(py, inst, "inst.data == 4");
py_assert!(py, inst, "inst.a == 8");
});
}
/// Wraps a Python future and yield it once.
@ -415,8 +404,7 @@ impl PyIterProtocol for OnceFuture {
#[test]
fn test_await() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let once = py.get_type::<OnceFuture>();
let source = pyo3::indoc::indoc!(
r#"
@ -441,6 +429,7 @@ loop.close()
py.run(source, Some(globals), None)
.map_err(|e| e.print(py))
.unwrap();
});
}
/// Increment the count when `__get__` is called.
@ -475,8 +464,7 @@ impl PyDescrProtocol for DescrCounter {
#[test]
fn descr_getset() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let counter = py.get_type::<DescrCounter>();
let source = pyo3::indoc::indoc!(
r#"
@ -494,4 +482,5 @@ assert c.counter.count == 3
py.run(source, Some(globals), None)
.map_err(|e| e.print(py))
.unwrap();
});
}

View File

@ -89,29 +89,28 @@ fn reader() -> Reader {
#[test]
fn test_nested_iter() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let reader: PyObject = reader().into_py(py);
py_assert!(
py,
reader,
"list(reader.get_iter(bytes([3, 5, 2]))) == ['c', 'e', 'b']"
);
});
}
#[test]
fn test_clone_ref() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let reader: PyObject = reader().into_py(py);
py_assert!(py, reader, "reader == reader.clone_ref()");
py_assert!(py, reader, "reader == reader.clone_ref_with_py()");
});
}
#[test]
fn test_nested_iter_reset() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let reader = PyCell::new(py, reader()).unwrap();
py_assert!(
py,
@ -120,4 +119,5 @@ fn test_nested_iter_reset() {
);
let reader_ref = reader.borrow();
assert!(reader_ref.inner.is_empty());
});
}

View File

@ -113,8 +113,7 @@ fn seq_dict(py: Python<'_>) -> &pyo3::types::PyDict {
#[test]
fn test_getitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_assert!(py, *d, "s[0] == 1");
@ -122,23 +121,22 @@ fn test_getitem() {
py_assert!(py, *d, "s[2] == 3");
py_expect_exception!(py, *d, "print(s[-4])", PyIndexError);
py_expect_exception!(py, *d, "print(s[4])", PyIndexError);
});
}
#[test]
fn test_setitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]");
py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError);
});
}
#[test]
fn test_delitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
py_run!(
@ -173,13 +171,12 @@ fn test_delitem() {
"s = ByteSequence([1, 2, 3]); del s[4]",
PyIndexError
);
});
}
#[test]
fn test_contains() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_assert!(py, *d, "1 in s");
@ -187,13 +184,12 @@ fn test_contains() {
py_assert!(py, *d, "3 in s");
py_assert!(py, *d, "4 not in s");
py_assert!(py, *d, "'hello' not in s");
});
}
#[test]
fn test_concat() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_run!(
@ -207,13 +203,12 @@ fn test_concat() {
"s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2",
PyTypeError
);
});
}
#[test]
fn test_inplace_concat() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_run!(
@ -222,24 +217,22 @@ fn test_inplace_concat() {
"s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]"
);
py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
});
}
#[test]
fn test_repeat() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_run!(py, *d, "s2 = s * 2; assert list(s2) == [1, 2, 3, 1, 2, 3]");
py_expect_exception!(py, *d, "s2 = s * -1", PyValueError);
});
}
#[test]
fn test_inplace_repeat() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
py_run!(
@ -248,6 +241,7 @@ fn test_inplace_repeat() {
"s = ByteSequence([1, 2]); s *= 3; assert list(s) == [1, 2, 1, 2, 1, 2]"
);
py_expect_exception!(py, *d, "s = ByteSequence([1, 2]); s *= -1", PyValueError);
});
}
// Check that #[pyo3(get, set)] works correctly for Vec<PyObject>
@ -260,22 +254,19 @@ struct GenericList {
#[test]
fn test_generic_list_get() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let list: PyObject = GenericList {
items: [1, 2, 3].iter().map(|i| i.to_object(py)).collect(),
}
.into_py(py);
py_assert!(py, list, "list.items == [1, 2, 3]");
});
}
#[test]
fn test_generic_list_set() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let list = PyCell::new(py, GenericList { items: vec![] }).unwrap();
py_run!(py, list, "list.items = [1, 2, 3]");
@ -285,6 +276,7 @@ fn test_generic_list_set() {
.iter()
.zip(&[1u32, 2, 3])
.all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
});
}
#[pyclass]
@ -306,9 +298,7 @@ impl OptionList {
#[test]
fn test_option_list_get() {
// Regression test for #798
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let list = PyCell::new(
py,
OptionList {
@ -320,4 +310,5 @@ fn test_option_list_get() {
py_assert!(py, list, "list[0] == 1");
py_assert!(py, list, "list[1] == None");
py_expect_exception!(py, list, "list[2]", PyIndexError);
});
}

View File

@ -97,8 +97,7 @@ fn seq_dict(py: Python<'_>) -> &pyo3::types::PyDict {
#[test]
fn test_getitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_assert!(py, *d, "s[0] == 1");
@ -106,23 +105,22 @@ fn test_getitem() {
py_assert!(py, *d, "s[2] == 3");
py_expect_exception!(py, *d, "print(s[-4])", PyIndexError);
py_expect_exception!(py, *d, "print(s[4])", PyIndexError);
});
}
#[test]
fn test_setitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]");
py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError);
});
}
#[test]
fn test_delitem() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
py_run!(
@ -157,13 +155,12 @@ fn test_delitem() {
"s = ByteSequence([1, 2, 3]); del s[4]",
PyIndexError
);
});
}
#[test]
fn test_contains() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_assert!(py, *d, "1 in s");
@ -171,13 +168,12 @@ fn test_contains() {
py_assert!(py, *d, "3 in s");
py_assert!(py, *d, "4 not in s");
py_assert!(py, *d, "'hello' not in s");
});
}
#[test]
fn test_concat() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_run!(
@ -191,13 +187,12 @@ fn test_concat() {
"s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2",
PyTypeError
);
});
}
#[test]
fn test_inplace_concat() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_run!(
@ -206,24 +201,22 @@ fn test_inplace_concat() {
"s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]"
);
py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
});
}
#[test]
fn test_repeat() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = seq_dict(py);
py_run!(py, *d, "s2 = s * 2; assert list(s2) == [1, 2, 3, 1, 2, 3]");
py_expect_exception!(py, *d, "s2 = s * -1", PyValueError);
});
}
#[test]
fn test_inplace_repeat() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
py_run!(
@ -232,6 +225,7 @@ fn test_inplace_repeat() {
"s = ByteSequence([1, 2]); s *= 3; assert list(s) == [1, 2, 1, 2, 1, 2]"
);
py_expect_exception!(py, *d, "s = ByteSequence([1, 2]); s *= -1", PyValueError);
});
}
// Check that #[pyo3(get, set)] works correctly for Vec<PyObject>
@ -244,22 +238,19 @@ struct GenericList {
#[test]
fn test_generic_list_get() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let list: PyObject = GenericList {
items: [1, 2, 3].iter().map(|i| i.to_object(py)).collect(),
}
.into_py(py);
py_assert!(py, list, "list.items == [1, 2, 3]");
});
}
#[test]
fn test_generic_list_set() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let list = PyCell::new(py, GenericList { items: vec![] }).unwrap();
py_run!(py, list, "list.items = [1, 2, 3]");
@ -269,6 +260,7 @@ fn test_generic_list_set() {
.iter()
.zip(&[1u32, 2, 3])
.all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
});
}
#[pyclass]
@ -290,9 +282,7 @@ impl PySequenceProtocol for OptionList {
#[test]
fn test_option_list_get() {
// Regression test for #798
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let list = PyCell::new(
py,
OptionList {
@ -304,4 +294,5 @@ fn test_option_list_get() {
py_assert!(py, list, "list[0] == 1");
py_assert!(py, list, "list[1] == None");
py_expect_exception!(py, list, "list[2]", PyIndexError);
});
}

View File

@ -9,9 +9,7 @@ fn take_str(_s: &str) {}
#[test]
fn test_unicode_encode_error() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let take_str = wrap_pyfunction!(take_str)(py).unwrap();
py_expect_exception!(
py,
@ -20,4 +18,5 @@ fn test_unicode_encode_error() {
PyUnicodeEncodeError,
"'utf-8' codec can't encode character '\\ud800' in position 0: surrogates not allowed"
);
});
}

View File

@ -10,12 +10,12 @@ fn class_without_docs_or_signature() {
#[pyclass]
struct MyClass {}
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<MyClass>();
py_assert!(py, typeobj, "typeobj.__doc__ is None");
py_assert!(py, typeobj, "typeobj.__text_signature__ is None");
});
}
#[test]
@ -25,12 +25,12 @@ fn class_with_docs() {
/// docs line2
struct MyClass {}
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<MyClass>();
py_assert!(py, typeobj, "typeobj.__doc__ == 'docs line1\\ndocs line2'");
py_assert!(py, typeobj, "typeobj.__text_signature__ is None");
});
}
#[test]
@ -53,8 +53,7 @@ fn class_with_docs_and_signature() {
}
}
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<MyClass>();
py_assert!(
@ -67,6 +66,7 @@ fn class_with_docs_and_signature() {
typeobj,
"typeobj.__text_signature__ == '(a, b=None, *, c=42)'"
);
});
}
#[test]
@ -86,8 +86,7 @@ fn class_with_signature() {
}
}
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<MyClass>();
py_assert!(
@ -100,6 +99,7 @@ fn class_with_signature() {
typeobj,
"typeobj.__text_signature__ == '(a, b=None, *, c=42)'"
);
});
}
#[test]
@ -110,11 +110,11 @@ fn test_function() {
let _ = (a, b, c);
}
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let f = wrap_pyfunction!(my_function)(py).unwrap();
py_assert!(py, f, "f.__text_signature__ == '(a, b=None, *, c=42)'");
});
}
#[test]
@ -129,8 +129,7 @@ fn test_pyfn() {
Ok(())
}
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let m = wrap_pymodule!(my_module)(py);
py_assert!(
@ -138,6 +137,7 @@ fn test_pyfn() {
m,
"m.my_function.__text_signature__ == '(a, b=None, *, c=42)'"
);
});
}
#[test]
@ -167,8 +167,7 @@ fn test_methods() {
}
}
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<MyClass>();
py_assert!(
@ -191,6 +190,7 @@ fn test_methods() {
typeobj,
"typeobj.static_method.__text_signature__ == '(d)'"
);
});
}
#[test]
@ -210,8 +210,7 @@ fn test_raw_identifiers() {
fn r#method(&self) {}
}
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let typeobj = py.get_type::<MyClass>();
py_assert!(py, typeobj, "typeobj.__text_signature__ == '($self)'");
@ -221,4 +220,5 @@ fn test_raw_identifiers() {
typeobj,
"typeobj.method.__text_signature__ == '($self)'"
);
});
}

View File

@ -17,10 +17,10 @@ impl UnsendableDictClass {
#[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]
fn test_unsendable_dict() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(py, UnsendableDictClass {}).unwrap();
py_run!(py, inst, "assert inst.__dict__ == {}");
});
}
#[pyclass(dict, unsendable, weakref)]
@ -37,8 +37,7 @@ impl UnsendableDictClassWithWeakRef {
#[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]
fn test_unsendable_dict_with_weakref() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst = Py::new(py, UnsendableDictClassWithWeakRef {}).unwrap();
py_run!(py, inst, "assert inst.__dict__ == {}");
py_run!(
@ -46,4 +45,5 @@ fn test_unsendable_dict_with_weakref() {
inst,
"import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1"
);
});
}

View File

@ -25,18 +25,17 @@ impl MyClass {
#[test]
fn variable_args() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let my_obj = py.get_type::<MyClass>();
py_assert!(py, my_obj, "my_obj.test_args() == ()");
py_assert!(py, my_obj, "my_obj.test_args(1) == (1,)");
py_assert!(py, my_obj, "my_obj.test_args(1, 2) == (1, 2)");
});
}
#[test]
fn variable_kwargs() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let my_obj = py.get_type::<MyClass>();
py_assert!(py, my_obj, "my_obj.test_kwargs() == None");
py_assert!(py, my_obj, "my_obj.test_kwargs(test=1) == {'test': 1}");
@ -45,4 +44,5 @@ fn variable_kwargs() {
my_obj,
"my_obj.test_kwargs(test1=1, test2=2) == {'test1':1, 'test2':2}"
);
});
}

View File

@ -25,14 +25,14 @@ impl MutRefArg {
#[test]
fn mut_ref_arg() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst1 = Py::new(py, MutRefArg { n: 0 }).unwrap();
let inst2 = Py::new(py, MutRefArg { n: 0 }).unwrap();
py_run!(py, inst1 inst2, "inst1.set_other(inst2)");
let inst2 = inst2.as_ref(py).borrow();
assert_eq!(inst2.n, 100);
});
}
#[pyclass]
@ -50,27 +50,25 @@ fn get_zero() -> PyUsize {
/// Checks that we can use return a custom class in arbitrary function and use those functions
/// both in rust and python
fn return_custom_class() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
// Using from rust
assert_eq!(get_zero().value, 0);
// Using from python
let get_zero = wrap_pyfunction!(get_zero)(py).unwrap();
py_assert!(py, get_zero, "get_zero().value == 0");
});
}
#[test]
fn intopytuple_primitive() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let tup = (1, 2, "foo");
py_assert!(py, tup, "tup == (1, 2, 'foo')");
py_assert!(py, tup, "tup[0] == 1");
py_assert!(py, tup, "tup[1] == 2");
py_assert!(py, tup, "tup[2] == 'foo'");
});
}
#[pyclass]
@ -78,9 +76,7 @@ struct SimplePyClass {}
#[test]
fn intopytuple_pyclass() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let tup = (
PyCell::new(py, SimplePyClass {}).unwrap(),
PyCell::new(py, SimplePyClass {}).unwrap(),
@ -88,22 +84,20 @@ fn intopytuple_pyclass() {
py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'");
py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[1]).__name__");
py_assert!(py, tup, "tup[0] != tup[1]");
});
}
#[test]
fn pytuple_primitive_iter() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let tup = PyTuple::new(py, [1u32, 2, 3].iter());
py_assert!(py, tup, "tup == (1, 2, 3)");
});
}
#[test]
fn pytuple_pyclass_iter() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let tup = PyTuple::new(
py,
[
@ -115,6 +109,7 @@ fn pytuple_pyclass_iter() {
py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'");
py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[0]).__name__");
py_assert!(py, tup, "tup[0] != tup[1]");
});
}
#[pyclass(dict, module = "test_module")]
@ -149,8 +144,7 @@ fn add_module(py: Python<'_>, module: &PyModule) -> PyResult<()> {
#[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]
fn test_pickle() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let module = PyModule::new(py, "test_module").unwrap();
module.add_class::<PickleSupport>().unwrap();
add_module(py, module).unwrap();
@ -168,6 +162,7 @@ fn test_pickle() {
assert inst2.__dict__ == {'a': 1}
"#
);
});
}
/// Testing https://github.com/PyO3/pyo3/issues/1106. A result type that
@ -203,7 +198,7 @@ fn result_conversion_function() -> Result<(), MyError> {
#[test]
fn test_result_conversion() {
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
wrap_pyfunction!(result_conversion_function)(py).unwrap();
});
}