Merge pull request #2518 from mejrs/acquire_gil_tests

Use Python::with_gil in tests
This commit is contained in:
David Hewitt 2022-07-20 06:54:35 +01:00 committed by GitHub
commit e40b25237d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 2622 additions and 2738 deletions

View file

@ -181,7 +181,7 @@ jobs:
run: | run: |
set -x set -x
cargo update -p indexmap --precise 1.6.2 cargo update -p indexmap --precise 1.6.2
cargo update -p hashbrown:0.12.2 --precise 0.9.1 cargo update -p hashbrown:0.12.3 --precise 0.9.1
PROJECTS=("." "examples/decorator" "examples/maturin-starter" "examples/setuptools-rust-starter" "examples/word-count") PROJECTS=("." "examples/decorator" "examples/maturin-starter" "examples/setuptools-rust-starter" "examples/word-count")
for PROJ in ${PROJECTS[@]}; do for PROJ in ${PROJECTS[@]}; do
cargo update --manifest-path "$PROJ/Cargo.toml" -p parking_lot --precise 0.11.0 cargo update --manifest-path "$PROJ/Cargo.toml" -p parking_lot --precise 0.11.0

View file

@ -5,62 +5,62 @@ use pyo3::types::IntoPyDict;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
fn iter_dict(b: &mut Bencher<'_>) { fn iter_dict(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 100_000;
const LEN: usize = 100_000; let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); let mut sum = 0;
let mut sum = 0; b.iter(|| {
b.iter(|| { for (k, _v) in dict.iter() {
for (k, _v) in dict.iter() { let i: u64 = k.extract().unwrap();
let i: u64 = k.extract().unwrap(); sum += i;
sum += i; }
} });
}); })
} }
fn dict_new(b: &mut Bencher<'_>) { fn dict_new(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 50_000;
const LEN: usize = 50_000; b.iter(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py));
b.iter(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py)); });
} }
fn dict_get_item(b: &mut Bencher<'_>) { fn dict_get_item(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 50_000;
const LEN: usize = 50_000; let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); let mut sum = 0;
let mut sum = 0; b.iter(|| {
b.iter(|| { for i in 0..LEN {
for i in 0..LEN { sum += dict.get_item(i).unwrap().extract::<usize>().unwrap();
sum += dict.get_item(i).unwrap().extract::<usize>().unwrap(); }
} });
}); });
} }
fn extract_hashmap(b: &mut Bencher<'_>) { fn extract_hashmap(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 100_000;
const LEN: usize = 100_000; let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); b.iter(|| HashMap::<u64, u64>::extract(dict));
b.iter(|| HashMap::<u64, u64>::extract(dict)); });
} }
fn extract_btreemap(b: &mut Bencher<'_>) { fn extract_btreemap(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 100_000;
const LEN: usize = 100_000; let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); b.iter(|| BTreeMap::<u64, u64>::extract(dict));
b.iter(|| BTreeMap::<u64, u64>::extract(dict)); });
} }
#[cfg(feature = "hashbrown")] #[cfg(feature = "hashbrown")]
fn extract_hashbrown_map(b: &mut Bencher<'_>) { fn extract_hashbrown_map(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 100_000;
const LEN: usize = 100_000; let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py); b.iter(|| hashbrown::HashMap::<u64, u64>::extract(dict));
b.iter(|| hashbrown::HashMap::<u64, u64>::extract(dict)); });
} }
fn criterion_benchmark(c: &mut Criterion) { 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<'_>) { fn bench_clean_acquire_gil(b: &mut Bencher<'_>) {
// Acquiring first GIL will also create a "clean" GILPool, so this measures the Python overhead. // Acquiring first GIL will also create a "clean" GILPool, so this measures the Python overhead.
b.iter(|| { 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 _ = obj.clone();
}, },
|_| { |_| {
let _ = Python::acquire_gil(); let _ = Python::with_gil(|_| {});
}, },
BatchSize::NumBatches(1), BatchSize::NumBatches(1),
); );

View file

@ -4,52 +4,52 @@ use pyo3::prelude::*;
use pyo3::types::PyList; use pyo3::types::PyList;
fn iter_list(b: &mut Bencher<'_>) { fn iter_list(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 100_000;
const LEN: usize = 100_000; let list = PyList::new(py, 0..LEN);
let list = PyList::new(py, 0..LEN); let mut sum = 0;
let mut sum = 0; b.iter(|| {
b.iter(|| { for x in list.iter() {
for x in list.iter() { let i: u64 = x.extract().unwrap();
let i: u64 = x.extract().unwrap(); sum += i;
sum += i; }
} });
}); });
} }
fn list_new(b: &mut Bencher<'_>) { fn list_new(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 50_000;
const LEN: usize = 50_000; b.iter(|| PyList::new(py, 0..LEN));
b.iter(|| PyList::new(py, 0..LEN)); });
} }
fn list_get_item(b: &mut Bencher<'_>) { fn list_get_item(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 50_000;
const LEN: usize = 50_000; let list = PyList::new(py, 0..LEN);
let list = PyList::new(py, 0..LEN); let mut sum = 0;
let mut sum = 0; b.iter(|| {
b.iter(|| { for i in 0..LEN {
for i in 0..LEN { sum += list.get_item(i).unwrap().extract::<usize>().unwrap();
sum += list.get_item(i).unwrap().extract::<usize>().unwrap(); }
} });
}); });
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
fn list_get_item_unchecked(b: &mut Bencher<'_>) { fn list_get_item_unchecked(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 50_000;
const LEN: usize = 50_000; let list = PyList::new(py, 0..LEN);
let list = PyList::new(py, 0..LEN); let mut sum = 0;
let mut sum = 0; b.iter(|| {
b.iter(|| { for i in 0..LEN {
for i in 0..LEN { unsafe {
unsafe { sum += list.get_item_unchecked(i).extract::<usize>().unwrap();
sum += list.get_item_unchecked(i).extract::<usize>().unwrap(); }
} }
} });
}); });
} }

View file

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

View file

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

View file

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

View file

@ -4,52 +4,52 @@ use pyo3::prelude::*;
use pyo3::types::PyTuple; use pyo3::types::PyTuple;
fn iter_tuple(b: &mut Bencher<'_>) { fn iter_tuple(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 100_000;
const LEN: usize = 100_000; let tuple = PyTuple::new(py, 0..LEN);
let tuple = PyTuple::new(py, 0..LEN); let mut sum = 0;
let mut sum = 0; b.iter(|| {
b.iter(|| { for x in tuple.iter() {
for x in tuple.iter() { let i: u64 = x.extract().unwrap();
let i: u64 = x.extract().unwrap(); sum += i;
sum += i; }
} });
}); });
} }
fn tuple_new(b: &mut Bencher<'_>) { fn tuple_new(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 50_000;
const LEN: usize = 50_000; b.iter(|| PyTuple::new(py, 0..LEN));
b.iter(|| PyTuple::new(py, 0..LEN)); });
} }
fn tuple_get_item(b: &mut Bencher<'_>) { fn tuple_get_item(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 50_000;
const LEN: usize = 50_000; let tuple = PyTuple::new(py, 0..LEN);
let tuple = PyTuple::new(py, 0..LEN); let mut sum = 0;
let mut sum = 0; b.iter(|| {
b.iter(|| { for i in 0..LEN {
for i in 0..LEN { sum += tuple.get_item(i).unwrap().extract::<usize>().unwrap();
sum += tuple.get_item(i).unwrap().extract::<usize>().unwrap(); }
} });
}); });
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
fn tuple_get_item_unchecked(b: &mut Bencher<'_>) { fn tuple_get_item_unchecked(b: &mut Bencher<'_>) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); const LEN: usize = 50_000;
const LEN: usize = 50_000; let tuple = PyTuple::new(py, 0..LEN);
let tuple = PyTuple::new(py, 0..LEN); let mut sum = 0;
let mut sum = 0; b.iter(|| {
b.iter(|| { for i in 0..LEN {
for i in 0..LEN { unsafe {
unsafe { sum += tuple.get_item_unchecked(i).extract::<usize>().unwrap();
sum += tuple.get_item_unchecked(i).extract::<usize>().unwrap(); }
} }
} });
}); });
} }

View file

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

View file

@ -41,15 +41,14 @@ impl UnaryArithmetic {
#[test] #[test]
fn unary_arithmetic() { fn unary_arithmetic() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
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(+c) == 'UA(2.7)'"); py_run!(py, c, "assert repr(round(c)) == 'UA(3)'");
py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'"); py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'");
py_run!(py, c, "assert repr(round(c)) == 'UA(3)'"); });
py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'");
} }
#[pyclass] #[pyclass]
@ -135,26 +134,26 @@ impl InPlaceOperations {
#[test] #[test]
fn inplace_operations() { fn inplace_operations() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let init = |value, code| {
let init = |value, code| { let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
let c = PyCell::new(py, InPlaceOperations { value }).unwrap(); py_run!(py, c, code);
py_run!(py, c, code); };
};
init(0, "d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'"); init(0, "d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'");
init(10, "d = c; c -= 1; assert repr(c) == repr(d) == 'IPO(9)'"); init(10, "d = c; c -= 1; assert repr(c) == repr(d) == 'IPO(9)'");
init(3, "d = c; c *= 3; assert repr(c) == repr(d) == 'IPO(9)'"); init(3, "d = c; c *= 3; assert repr(c) == repr(d) == 'IPO(9)'");
init(3, "d = c; c <<= 2; assert repr(c) == repr(d) == 'IPO(12)'"); init(3, "d = c; c <<= 2; assert repr(c) == repr(d) == 'IPO(12)'");
init(12, "d = c; c >>= 2; assert repr(c) == repr(d) == 'IPO(3)'"); init(12, "d = c; c >>= 2; assert repr(c) == repr(d) == 'IPO(3)'");
init(12, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'"); init(12, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'");
init(12, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'"); init(12, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'"); init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'");
init(3, "d = c; c **= 4; assert repr(c) == repr(d) == 'IPO(81)'"); init(3, "d = c; c **= 4; assert repr(c) == repr(d) == 'IPO(81)'");
init( init(
3, 3,
"d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'", "d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
); );
});
} }
#[pyclass] #[pyclass]
@ -205,36 +204,35 @@ impl BinaryArithmetic {
#[test] #[test]
fn binary_arithmetic() { fn binary_arithmetic() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); 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'");
py_run!(py, c, "assert c + 1 == 'BA + 1'");
py_run!(py, c, "assert c - 1 == 'BA - 1'");
py_run!(py, c, "assert c * 1 == 'BA * 1'");
py_run!(py, c, "assert c << 1 == 'BA << 1'");
py_run!(py, c, "assert c >> 1 == 'BA >> 1'");
py_run!(py, c, "assert c & 1 == 'BA & 1'");
py_run!(py, c, "assert c ^ 1 == 'BA ^ 1'");
py_run!(py, c, "assert c | 1 == 'BA | 1'");
py_run!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'");
let c = PyCell::new(py, BinaryArithmetic {}).unwrap(); // Class with __add__ only should not allow the reverse op;
py_run!(py, c, "assert c + c == 'BA + BA'"); // this is consistent with Python classes.
py_run!(py, c, "assert c.__add__(c) == 'BA + BA'");
py_run!(py, c, "assert c + 1 == 'BA + 1'");
py_run!(py, c, "assert c - 1 == 'BA - 1'");
py_run!(py, c, "assert c * 1 == 'BA * 1'");
py_run!(py, c, "assert c << 1 == 'BA << 1'");
py_run!(py, c, "assert c >> 1 == 'BA >> 1'");
py_run!(py, c, "assert c & 1 == 'BA & 1'");
py_run!(py, c, "assert c ^ 1 == 'BA ^ 1'");
py_run!(py, c, "assert c | 1 == 'BA | 1'");
py_run!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'");
// Class with __add__ only should not allow the reverse op; py_expect_exception!(py, c, "1 + c", PyTypeError);
// this is consistent with Python classes. py_expect_exception!(py, c, "1 - c", PyTypeError);
py_expect_exception!(py, c, "1 * c", PyTypeError);
py_expect_exception!(py, c, "1 << c", PyTypeError);
py_expect_exception!(py, c, "1 >> c", PyTypeError);
py_expect_exception!(py, c, "1 & c", PyTypeError);
py_expect_exception!(py, c, "1 ^ c", PyTypeError);
py_expect_exception!(py, c, "1 | c", PyTypeError);
py_expect_exception!(py, c, "1 ** c", PyTypeError);
py_expect_exception!(py, c, "1 + c", PyTypeError); py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'");
py_expect_exception!(py, c, "1 - c", PyTypeError); });
py_expect_exception!(py, c, "1 * c", PyTypeError);
py_expect_exception!(py, c, "1 << c", PyTypeError);
py_expect_exception!(py, c, "1 >> c", PyTypeError);
py_expect_exception!(py, c, "1 & c", PyTypeError);
py_expect_exception!(py, c, "1 ^ c", PyTypeError);
py_expect_exception!(py, c, "1 | c", PyTypeError);
py_expect_exception!(py, c, "1 ** c", PyTypeError);
py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'");
} }
#[pyclass] #[pyclass]
@ -281,28 +279,27 @@ impl RhsArithmetic {
#[test] #[test]
fn rhs_arithmetic() { fn rhs_arithmetic() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, RhsArithmetic {}).unwrap();
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
let c = PyCell::new(py, RhsArithmetic {}).unwrap(); py_run!(py, c, "assert 1 + c == '1 + RA'");
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'"); py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'");
py_run!(py, c, "assert 1 + c == '1 + RA'"); py_run!(py, c, "assert 1 - c == '1 - RA'");
py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'"); py_run!(py, c, "assert c.__rmul__(1) == '1 * RA'");
py_run!(py, c, "assert 1 - c == '1 - RA'"); py_run!(py, c, "assert 1 * c == '1 * RA'");
py_run!(py, c, "assert c.__rmul__(1) == '1 * RA'"); py_run!(py, c, "assert c.__rlshift__(1) == '1 << RA'");
py_run!(py, c, "assert 1 * c == '1 * RA'"); py_run!(py, c, "assert 1 << c == '1 << RA'");
py_run!(py, c, "assert c.__rlshift__(1) == '1 << RA'"); py_run!(py, c, "assert c.__rrshift__(1) == '1 >> RA'");
py_run!(py, c, "assert 1 << c == '1 << RA'"); py_run!(py, c, "assert 1 >> c == '1 >> RA'");
py_run!(py, c, "assert c.__rrshift__(1) == '1 >> RA'"); py_run!(py, c, "assert c.__rand__(1) == '1 & RA'");
py_run!(py, c, "assert 1 >> c == '1 >> RA'"); py_run!(py, c, "assert 1 & c == '1 & RA'");
py_run!(py, c, "assert c.__rand__(1) == '1 & RA'"); py_run!(py, c, "assert c.__rxor__(1) == '1 ^ RA'");
py_run!(py, c, "assert 1 & c == '1 & RA'"); py_run!(py, c, "assert 1 ^ c == '1 ^ RA'");
py_run!(py, c, "assert c.__rxor__(1) == '1 ^ RA'"); py_run!(py, c, "assert c.__ror__(1) == '1 | RA'");
py_run!(py, c, "assert 1 ^ c == '1 ^ RA'"); py_run!(py, c, "assert 1 | c == '1 | RA'");
py_run!(py, c, "assert c.__ror__(1) == '1 | RA'"); py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
py_run!(py, c, "assert 1 | c == '1 | RA'"); 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] #[pyclass]
@ -411,32 +408,31 @@ impl LhsAndRhs {
#[test] #[test]
fn lhs_fellback_to_rhs() { fn lhs_fellback_to_rhs() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, LhsAndRhs {}).unwrap();
// If the light hand value is `LhsAndRhs`, LHS is used.
let c = PyCell::new(py, LhsAndRhs {}).unwrap(); py_run!(py, c, "assert c + 1 == 'LR + 1'");
// If the light hand value is `LhsAndRhs`, LHS is used. py_run!(py, c, "assert c - 1 == 'LR - 1'");
py_run!(py, c, "assert c + 1 == 'LR + 1'"); py_run!(py, c, "assert c * 1 == 'LR * 1'");
py_run!(py, c, "assert c - 1 == 'LR - 1'"); py_run!(py, c, "assert c << 1 == 'LR << 1'");
py_run!(py, c, "assert c * 1 == 'LR * 1'"); py_run!(py, c, "assert c >> 1 == 'LR >> 1'");
py_run!(py, c, "assert c << 1 == 'LR << 1'"); py_run!(py, c, "assert c & 1 == 'LR & 1'");
py_run!(py, c, "assert c >> 1 == 'LR >> 1'"); py_run!(py, c, "assert c ^ 1 == 'LR ^ 1'");
py_run!(py, c, "assert c & 1 == 'LR & 1'"); py_run!(py, c, "assert c | 1 == 'LR | 1'");
py_run!(py, c, "assert c ^ 1 == 'LR ^ 1'"); py_run!(py, c, "assert c ** 1 == 'LR ** 1'");
py_run!(py, c, "assert c | 1 == 'LR | 1'"); py_run!(py, c, "assert c @ 1 == 'LR @ 1'");
py_run!(py, c, "assert c ** 1 == 'LR ** 1'"); // Fellback to RHS because of type mismatching
py_run!(py, c, "assert c @ 1 == 'LR @ 1'"); py_run!(py, c, "assert 1 + c == '1 + RA'");
// Fellback to RHS because of type mismatching 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'");
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'"); 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'");
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'"); 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'");
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'"); });
py_run!(py, c, "assert 1 @ c == '1 @ RA'");
} }
#[pyclass] #[pyclass]
@ -480,54 +476,52 @@ impl RichComparisons2 {
#[test] #[test]
fn rich_comparisons() { fn rich_comparisons() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, RichComparisons {}).unwrap();
py_run!(py, c, "assert (c < c) == 'RC < RC'");
let c = PyCell::new(py, RichComparisons {}).unwrap(); py_run!(py, c, "assert (c < 1) == 'RC < 1'");
py_run!(py, c, "assert (c < c) == 'RC < RC'"); py_run!(py, c, "assert (1 < c) == 'RC > 1'");
py_run!(py, c, "assert (c < 1) == 'RC < 1'"); py_run!(py, c, "assert (c <= c) == 'RC <= RC'");
py_run!(py, c, "assert (1 < c) == 'RC > 1'"); py_run!(py, c, "assert (c <= 1) == 'RC <= 1'");
py_run!(py, c, "assert (c <= c) == 'RC <= RC'"); py_run!(py, c, "assert (1 <= c) == 'RC >= 1'");
py_run!(py, c, "assert (c <= 1) == 'RC <= 1'"); py_run!(py, c, "assert (c == c) == 'RC == RC'");
py_run!(py, c, "assert (1 <= c) == 'RC >= 1'"); py_run!(py, c, "assert (c == 1) == 'RC == 1'");
py_run!(py, c, "assert (c == c) == 'RC == RC'"); py_run!(py, c, "assert (1 == c) == 'RC == 1'");
py_run!(py, c, "assert (c == 1) == 'RC == 1'"); py_run!(py, c, "assert (c != c) == 'RC != RC'");
py_run!(py, c, "assert (1 == c) == 'RC == 1'"); py_run!(py, c, "assert (c != 1) == 'RC != 1'");
py_run!(py, c, "assert (c != c) == 'RC != RC'"); py_run!(py, c, "assert (1 != c) == 'RC != 1'");
py_run!(py, c, "assert (c != 1) == 'RC != 1'"); py_run!(py, c, "assert (c > c) == 'RC > RC'");
py_run!(py, c, "assert (1 != c) == 'RC != 1'"); py_run!(py, c, "assert (c > 1) == 'RC > 1'");
py_run!(py, c, "assert (c > c) == 'RC > RC'"); py_run!(py, c, "assert (1 > c) == 'RC < 1'");
py_run!(py, c, "assert (c > 1) == 'RC > 1'"); py_run!(py, c, "assert (c >= c) == 'RC >= RC'");
py_run!(py, c, "assert (1 > c) == 'RC < 1'"); py_run!(py, c, "assert (c >= 1) == 'RC >= 1'");
py_run!(py, c, "assert (c >= c) == 'RC >= RC'"); py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
py_run!(py, c, "assert (c >= 1) == 'RC >= 1'"); });
py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
} }
#[test] #[test]
fn rich_comparisons_python_3_type_error() { fn rich_comparisons_python_3_type_error() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
py_expect_exception!(py, c2, "c2 < c2", PyTypeError);
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap(); py_expect_exception!(py, c2, "c2 < 1", PyTypeError);
py_expect_exception!(py, c2, "c2 < c2", PyTypeError); py_expect_exception!(py, c2, "1 < c2", PyTypeError);
py_expect_exception!(py, c2, "c2 < 1", PyTypeError); py_expect_exception!(py, c2, "c2 <= c2", PyTypeError);
py_expect_exception!(py, c2, "1 < c2", PyTypeError); py_expect_exception!(py, c2, "c2 <= 1", PyTypeError);
py_expect_exception!(py, c2, "c2 <= c2", PyTypeError); py_expect_exception!(py, c2, "1 <= c2", PyTypeError);
py_expect_exception!(py, c2, "c2 <= 1", PyTypeError); py_run!(py, c2, "assert (c2 == c2) == True");
py_expect_exception!(py, c2, "1 <= c2", PyTypeError); py_run!(py, c2, "assert (c2 == 1) == True");
py_run!(py, c2, "assert (c2 == c2) == True"); py_run!(py, c2, "assert (1 == c2) == True");
py_run!(py, c2, "assert (c2 == 1) == True"); py_run!(py, c2, "assert (c2 != c2) == False");
py_run!(py, c2, "assert (1 == c2) == True"); py_run!(py, c2, "assert (c2 != 1) == False");
py_run!(py, c2, "assert (c2 != c2) == False"); py_run!(py, c2, "assert (1 != c2) == False");
py_run!(py, c2, "assert (c2 != 1) == False"); py_expect_exception!(py, c2, "c2 > c2", PyTypeError);
py_run!(py, c2, "assert (1 != c2) == False"); py_expect_exception!(py, c2, "c2 > 1", PyTypeError);
py_expect_exception!(py, c2, "c2 > c2", PyTypeError); py_expect_exception!(py, c2, "1 > c2", PyTypeError);
py_expect_exception!(py, c2, "c2 > 1", PyTypeError); py_expect_exception!(py, c2, "c2 >= c2", PyTypeError);
py_expect_exception!(py, c2, "1 > c2", PyTypeError); py_expect_exception!(py, c2, "c2 >= 1", PyTypeError);
py_expect_exception!(py, c2, "c2 >= c2", PyTypeError); py_expect_exception!(py, c2, "1 >= 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 // Checks that binary operations for which the arguments don't match the
@ -608,31 +602,31 @@ mod return_not_implemented {
} }
fn _test_binary_dunder(dunder: &str) { fn _test_binary_dunder(dunder: &str) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap(); py_run!(
py_run!( py,
py, c2,
c2, &format!(
&format!( "class Other: pass\nassert c2.__{}__(Other()) is NotImplemented",
"class Other: pass\nassert c2.__{}__(Other()) is NotImplemented", dunder
dunder )
) );
); });
} }
fn _test_binary_operator(operator: &str, dunder: &str) { fn _test_binary_operator(operator: &str, dunder: &str) {
_test_binary_dunder(dunder); _test_binary_dunder(dunder);
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap(); py_expect_exception!(
py_expect_exception!( py,
py, c2,
c2, &format!("class Other: pass\nc2 {} Other()", operator),
&format!("class Other: pass\nc2 {} Other()", operator), PyTypeError
PyTypeError );
); });
} }
fn _test_inplace_binary_operator(operator: &str, dunder: &str) { fn _test_inplace_binary_operator(operator: &str, dunder: &str) {

View file

@ -44,13 +44,12 @@ impl PyNumberProtocol for UnaryArithmetic {
#[test] #[test]
fn unary_arithmetic() { fn unary_arithmetic() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
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(+c) == 'UA(2.7)'"); });
py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'");
} }
#[pyclass] #[pyclass]
@ -115,26 +114,26 @@ impl PyNumberProtocol for InPlaceOperations {
} }
#[test] #[test]
fn inplace_operations() { fn inplace_operations() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let init = |value, code| {
let init = |value, code| { let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
let c = PyCell::new(py, InPlaceOperations { value }).unwrap(); py_run!(py, c, code);
py_run!(py, c, code); };
};
init(0, "d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'"); init(0, "d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'");
init(10, "d = c; c -= 1; assert repr(c) == repr(d) == 'IPO(9)'"); init(10, "d = c; c -= 1; assert repr(c) == repr(d) == 'IPO(9)'");
init(3, "d = c; c *= 3; assert repr(c) == repr(d) == 'IPO(9)'"); init(3, "d = c; c *= 3; assert repr(c) == repr(d) == 'IPO(9)'");
init(3, "d = c; c <<= 2; assert repr(c) == repr(d) == 'IPO(12)'"); init(3, "d = c; c <<= 2; assert repr(c) == repr(d) == 'IPO(12)'");
init(12, "d = c; c >>= 2; assert repr(c) == repr(d) == 'IPO(3)'"); init(12, "d = c; c >>= 2; assert repr(c) == repr(d) == 'IPO(3)'");
init(12, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'"); init(12, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'");
init(12, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'"); init(12, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'"); init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'");
init(3, "d = c; c **= 4; assert repr(c) == repr(d) == 'IPO(81)'"); init(3, "d = c; c **= 4; assert repr(c) == repr(d) == 'IPO(81)'");
init( init(
3, 3,
"d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'", "d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
); );
});
} }
#[pyproto] #[pyproto]
@ -182,35 +181,34 @@ impl PyNumberProtocol for BinaryArithmetic {
#[test] #[test]
fn binary_arithmetic() { fn binary_arithmetic() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); 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'");
py_run!(py, c, "assert c + 1 == 'BA + 1'");
py_run!(py, c, "assert 1 + c == '1 + BA'");
py_run!(py, c, "assert c - 1 == 'BA - 1'");
py_run!(py, c, "assert 1 - c == '1 - BA'");
py_run!(py, c, "assert c * 1 == 'BA * 1'");
py_run!(py, c, "assert 1 * c == '1 * BA'");
py_run!(py, c, "assert c % 1 == 'BA % 1'");
py_run!(py, c, "assert 1 % c == '1 % BA'");
let c = PyCell::new(py, BinaryArithmetic {}).unwrap(); py_run!(py, c, "assert c << 1 == 'BA << 1'");
py_run!(py, c, "assert c + c == 'BA + BA'"); py_run!(py, c, "assert 1 << c == '1 << BA'");
py_run!(py, c, "assert c.__add__(c) == 'BA + BA'"); py_run!(py, c, "assert c >> 1 == 'BA >> 1'");
py_run!(py, c, "assert c + 1 == 'BA + 1'"); py_run!(py, c, "assert 1 >> c == '1 >> BA'");
py_run!(py, c, "assert 1 + c == '1 + BA'"); py_run!(py, c, "assert c & 1 == 'BA & 1'");
py_run!(py, c, "assert c - 1 == 'BA - 1'"); py_run!(py, c, "assert 1 & c == '1 & BA'");
py_run!(py, c, "assert 1 - c == '1 - BA'"); py_run!(py, c, "assert c ^ 1 == 'BA ^ 1'");
py_run!(py, c, "assert c * 1 == 'BA * 1'"); py_run!(py, c, "assert 1 ^ c == '1 ^ BA'");
py_run!(py, c, "assert 1 * c == '1 * BA'"); py_run!(py, c, "assert c | 1 == 'BA | 1'");
py_run!(py, c, "assert c % 1 == 'BA % 1'"); py_run!(py, c, "assert 1 | c == '1 | BA'");
py_run!(py, c, "assert 1 % c == '1 % BA'"); py_run!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'");
py_run!(py, c, "assert 1 ** c == '1 ** BA (mod: None)'");
py_run!(py, c, "assert c << 1 == 'BA << 1'"); py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'");
py_run!(py, c, "assert 1 << c == '1 << BA'"); });
py_run!(py, c, "assert c >> 1 == 'BA >> 1'");
py_run!(py, c, "assert 1 >> c == '1 >> BA'");
py_run!(py, c, "assert c & 1 == 'BA & 1'");
py_run!(py, c, "assert 1 & c == '1 & BA'");
py_run!(py, c, "assert c ^ 1 == 'BA ^ 1'");
py_run!(py, c, "assert 1 ^ c == '1 ^ BA'");
py_run!(py, c, "assert c | 1 == 'BA | 1'");
py_run!(py, c, "assert 1 | c == '1 | BA'");
py_run!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'");
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] #[pyclass]
@ -261,30 +259,29 @@ impl PyNumberProtocol for RhsArithmetic {
#[test] #[test]
fn rhs_arithmetic() { fn rhs_arithmetic() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, RhsArithmetic {}).unwrap();
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
let c = PyCell::new(py, RhsArithmetic {}).unwrap(); py_run!(py, c, "assert 1 + c == '1 + RA'");
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'"); py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'");
py_run!(py, c, "assert 1 + c == '1 + RA'"); py_run!(py, c, "assert 1 - c == '1 - RA'");
py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'"); py_run!(py, c, "assert c.__rmod__(1) == '1 % RA'");
py_run!(py, c, "assert 1 - c == '1 - RA'"); py_run!(py, c, "assert 1 % c == '1 % RA'");
py_run!(py, c, "assert c.__rmod__(1) == '1 % RA'"); py_run!(py, c, "assert c.__rmul__(1) == '1 * RA'");
py_run!(py, c, "assert 1 % c == '1 % RA'"); py_run!(py, c, "assert 1 * c == '1 * RA'");
py_run!(py, c, "assert c.__rmul__(1) == '1 * RA'"); py_run!(py, c, "assert c.__rlshift__(1) == '1 << RA'");
py_run!(py, c, "assert 1 * c == '1 * RA'"); py_run!(py, c, "assert 1 << c == '1 << RA'");
py_run!(py, c, "assert c.__rlshift__(1) == '1 << RA'"); py_run!(py, c, "assert c.__rrshift__(1) == '1 >> RA'");
py_run!(py, c, "assert 1 << c == '1 << RA'"); py_run!(py, c, "assert 1 >> c == '1 >> RA'");
py_run!(py, c, "assert c.__rrshift__(1) == '1 >> RA'"); py_run!(py, c, "assert c.__rand__(1) == '1 & RA'");
py_run!(py, c, "assert 1 >> c == '1 >> RA'"); py_run!(py, c, "assert 1 & c == '1 & RA'");
py_run!(py, c, "assert c.__rand__(1) == '1 & RA'"); py_run!(py, c, "assert c.__rxor__(1) == '1 ^ RA'");
py_run!(py, c, "assert 1 & c == '1 & RA'"); py_run!(py, c, "assert 1 ^ c == '1 ^ RA'");
py_run!(py, c, "assert c.__rxor__(1) == '1 ^ RA'"); py_run!(py, c, "assert c.__ror__(1) == '1 | RA'");
py_run!(py, c, "assert 1 ^ c == '1 ^ RA'"); py_run!(py, c, "assert 1 | c == '1 | RA'");
py_run!(py, c, "assert c.__ror__(1) == '1 | RA'"); py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
py_run!(py, c, "assert 1 | c == '1 | RA'"); 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] #[pyclass]
@ -396,34 +393,33 @@ impl PyObjectProtocol for LhsAndRhs {
#[test] #[test]
fn lhs_fellback_to_rhs() { fn lhs_fellback_to_rhs() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, LhsAndRhs {}).unwrap();
// If the light hand value is `LhsAndRhs`, LHS is used.
let c = PyCell::new(py, LhsAndRhs {}).unwrap(); py_run!(py, c, "assert c + 1 == 'LR + 1'");
// If the light hand value is `LhsAndRhs`, LHS is used. py_run!(py, c, "assert c - 1 == 'LR - 1'");
py_run!(py, c, "assert c + 1 == 'LR + 1'"); py_run!(py, c, "assert c % 1 == 'LR % 1'");
py_run!(py, c, "assert c - 1 == 'LR - 1'"); py_run!(py, c, "assert c * 1 == 'LR * 1'");
py_run!(py, c, "assert c % 1 == 'LR % 1'"); py_run!(py, c, "assert c << 1 == 'LR << 1'");
py_run!(py, c, "assert c * 1 == 'LR * 1'"); py_run!(py, c, "assert c >> 1 == 'LR >> 1'");
py_run!(py, c, "assert c << 1 == 'LR << 1'"); py_run!(py, c, "assert c & 1 == 'LR & 1'");
py_run!(py, c, "assert c >> 1 == 'LR >> 1'"); py_run!(py, c, "assert c ^ 1 == 'LR ^ 1'");
py_run!(py, c, "assert c & 1 == 'LR & 1'"); py_run!(py, c, "assert c | 1 == 'LR | 1'");
py_run!(py, c, "assert c ^ 1 == 'LR ^ 1'"); py_run!(py, c, "assert c ** 1 == 'LR ** 1'");
py_run!(py, c, "assert c | 1 == 'LR | 1'"); py_run!(py, c, "assert c @ 1 == 'LR @ 1'");
py_run!(py, c, "assert c ** 1 == 'LR ** 1'"); // Fellback to RHS because of type mismatching
py_run!(py, c, "assert c @ 1 == 'LR @ 1'"); py_run!(py, c, "assert 1 + c == '1 + RA'");
// Fellback to RHS because of type mismatching 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'");
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'"); 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'");
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'"); 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'");
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'"); 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] #[pyclass]
@ -467,54 +463,52 @@ impl PyObjectProtocol for RichComparisons2 {
#[test] #[test]
fn rich_comparisons() { fn rich_comparisons() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, RichComparisons {}).unwrap();
py_run!(py, c, "assert (c < c) == 'RC < RC'");
let c = PyCell::new(py, RichComparisons {}).unwrap(); py_run!(py, c, "assert (c < 1) == 'RC < 1'");
py_run!(py, c, "assert (c < c) == 'RC < RC'"); py_run!(py, c, "assert (1 < c) == 'RC > 1'");
py_run!(py, c, "assert (c < 1) == 'RC < 1'"); py_run!(py, c, "assert (c <= c) == 'RC <= RC'");
py_run!(py, c, "assert (1 < c) == 'RC > 1'"); py_run!(py, c, "assert (c <= 1) == 'RC <= 1'");
py_run!(py, c, "assert (c <= c) == 'RC <= RC'"); py_run!(py, c, "assert (1 <= c) == 'RC >= 1'");
py_run!(py, c, "assert (c <= 1) == 'RC <= 1'"); py_run!(py, c, "assert (c == c) == 'RC == RC'");
py_run!(py, c, "assert (1 <= c) == 'RC >= 1'"); py_run!(py, c, "assert (c == 1) == 'RC == 1'");
py_run!(py, c, "assert (c == c) == 'RC == RC'"); py_run!(py, c, "assert (1 == c) == 'RC == 1'");
py_run!(py, c, "assert (c == 1) == 'RC == 1'"); py_run!(py, c, "assert (c != c) == 'RC != RC'");
py_run!(py, c, "assert (1 == c) == 'RC == 1'"); py_run!(py, c, "assert (c != 1) == 'RC != 1'");
py_run!(py, c, "assert (c != c) == 'RC != RC'"); py_run!(py, c, "assert (1 != c) == 'RC != 1'");
py_run!(py, c, "assert (c != 1) == 'RC != 1'"); py_run!(py, c, "assert (c > c) == 'RC > RC'");
py_run!(py, c, "assert (1 != c) == 'RC != 1'"); py_run!(py, c, "assert (c > 1) == 'RC > 1'");
py_run!(py, c, "assert (c > c) == 'RC > RC'"); py_run!(py, c, "assert (1 > c) == 'RC < 1'");
py_run!(py, c, "assert (c > 1) == 'RC > 1'"); py_run!(py, c, "assert (c >= c) == 'RC >= RC'");
py_run!(py, c, "assert (1 > c) == 'RC < 1'"); py_run!(py, c, "assert (c >= 1) == 'RC >= 1'");
py_run!(py, c, "assert (c >= c) == 'RC >= RC'"); py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
py_run!(py, c, "assert (c >= 1) == 'RC >= 1'"); });
py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
} }
#[test] #[test]
fn rich_comparisons_python_3_type_error() { fn rich_comparisons_python_3_type_error() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
py_expect_exception!(py, c2, "c2 < c2", PyTypeError);
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap(); py_expect_exception!(py, c2, "c2 < 1", PyTypeError);
py_expect_exception!(py, c2, "c2 < c2", PyTypeError); py_expect_exception!(py, c2, "1 < c2", PyTypeError);
py_expect_exception!(py, c2, "c2 < 1", PyTypeError); py_expect_exception!(py, c2, "c2 <= c2", PyTypeError);
py_expect_exception!(py, c2, "1 < c2", PyTypeError); py_expect_exception!(py, c2, "c2 <= 1", PyTypeError);
py_expect_exception!(py, c2, "c2 <= c2", PyTypeError); py_expect_exception!(py, c2, "1 <= c2", PyTypeError);
py_expect_exception!(py, c2, "c2 <= 1", PyTypeError); py_run!(py, c2, "assert (c2 == c2) == True");
py_expect_exception!(py, c2, "1 <= c2", PyTypeError); py_run!(py, c2, "assert (c2 == 1) == True");
py_run!(py, c2, "assert (c2 == c2) == True"); py_run!(py, c2, "assert (1 == c2) == True");
py_run!(py, c2, "assert (c2 == 1) == True"); py_run!(py, c2, "assert (c2 != c2) == False");
py_run!(py, c2, "assert (1 == c2) == True"); py_run!(py, c2, "assert (c2 != 1) == False");
py_run!(py, c2, "assert (c2 != c2) == False"); py_run!(py, c2, "assert (1 != c2) == False");
py_run!(py, c2, "assert (c2 != 1) == False"); py_expect_exception!(py, c2, "c2 > c2", PyTypeError);
py_run!(py, c2, "assert (1 != c2) == False"); py_expect_exception!(py, c2, "c2 > 1", PyTypeError);
py_expect_exception!(py, c2, "c2 > c2", PyTypeError); py_expect_exception!(py, c2, "1 > c2", PyTypeError);
py_expect_exception!(py, c2, "c2 > 1", PyTypeError); py_expect_exception!(py, c2, "c2 >= c2", PyTypeError);
py_expect_exception!(py, c2, "1 > c2", PyTypeError); py_expect_exception!(py, c2, "c2 >= 1", PyTypeError);
py_expect_exception!(py, c2, "c2 >= c2", PyTypeError); py_expect_exception!(py, c2, "1 >= 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 // Checks that binary operations for which the arguments don't match the
@ -598,31 +592,31 @@ mod return_not_implemented {
} }
fn _test_binary_dunder(dunder: &str) { fn _test_binary_dunder(dunder: &str) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap(); py_run!(
py_run!( py,
py, c2,
c2, &format!(
&format!( "class Other: pass\nassert c2.__{}__(Other()) is NotImplemented",
"class Other: pass\nassert c2.__{}__(Other()) is NotImplemented", dunder
dunder )
) );
); });
} }
fn _test_binary_operator(operator: &str, dunder: &str) { fn _test_binary_operator(operator: &str, dunder: &str) {
_test_binary_dunder(dunder); _test_binary_dunder(dunder);
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap(); py_expect_exception!(
py_expect_exception!( py,
py, c2,
c2, &format!("class Other: pass\nc2 {} Other()", operator),
&format!("class Other: pass\nc2 {} Other()", operator), PyTypeError
PyTypeError );
); });
} }
fn _test_inplace_binary_operator(operator: &str, dunder: &str) { fn _test_inplace_binary_operator(operator: &str, dunder: &str) {

View file

@ -87,18 +87,18 @@ fn test_buffer() {
let drop_called = Arc::new(AtomicBool::new(false)); let drop_called = Arc::new(AtomicBool::new(false));
{ {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let instance = Py::new(
let instance = Py::new( py,
py, TestBufferClass {
TestBufferClass { vec: vec![b' ', b'2', b'3'],
vec: vec![b' ', b'2', b'3'], drop_called: drop_called.clone(),
drop_called: drop_called.clone(), },
}, )
) .unwrap();
.unwrap(); let env = [("ob", instance)].into_py_dict(py);
let env = [("ob", instance)].into_py_dict(py); py_assert!(py, *env, "bytes(ob) == b' 23'");
py_assert!(py, *env, "bytes(ob) == b' 23'"); });
} }
assert!(drop_called.load(Ordering::Relaxed)); assert!(drop_called.load(Ordering::Relaxed));
@ -110,26 +110,25 @@ fn test_buffer_referenced() {
let buf = { let buf = {
let input = vec![b' ', b'2', b'3']; let input = vec![b' ', b'2', b'3'];
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let instance: PyObject = TestBufferClass {
let instance: PyObject = TestBufferClass { vec: input.clone(),
vec: input.clone(), drop_called: drop_called.clone(),
drop_called: drop_called.clone(), }
} .into_py(py);
.into_py(py);
let buf = PyBuffer::<u8>::get(instance.as_ref(py)).unwrap(); let buf = PyBuffer::<u8>::get(instance.as_ref(py)).unwrap();
assert_eq!(buf.to_vec(py).unwrap(), input); assert_eq!(buf.to_vec(py).unwrap(), input);
drop(instance); drop(instance);
buf buf
})
}; };
assert!(!drop_called.load(Ordering::Relaxed)); assert!(!drop_called.load(Ordering::Relaxed));
{ Python::with_gil(|_| {
let _py = Python::acquire_gil().python();
drop(buf); drop(buf);
} });
assert!(drop_called.load(Ordering::Relaxed)); assert!(drop_called.load(Ordering::Relaxed));
} }

View file

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

View file

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

View file

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

View file

@ -11,13 +11,13 @@ struct EmptyClass {}
#[test] #[test]
fn empty_class() { fn empty_class() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<EmptyClass>();
let typeobj = py.get_type::<EmptyClass>(); // By default, don't allow creating instances from python.
// By default, don't allow creating instances from python. assert!(typeobj.call((), None).is_err());
assert!(typeobj.call((), None).is_err());
py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'"); py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
});
} }
#[pyclass] #[pyclass]
@ -56,9 +56,7 @@ struct ClassWithDocs {
#[test] #[test]
fn class_with_docstr() { fn class_with_docstr() {
{ Python::with_gil(|py| {
let gil = Python::acquire_gil();
let py = gil.python();
let typeobj = py.get_type::<ClassWithDocs>(); let typeobj = py.get_type::<ClassWithDocs>();
py_run!( py_run!(
py, py,
@ -80,7 +78,7 @@ fn class_with_docstr() {
typeobj, typeobj,
"assert typeobj.writeonly.__doc__ == 'Write-only property field'" "assert typeobj.writeonly.__doc__ == 'Write-only property field'"
); );
} });
} }
#[pyclass(name = "CustomName")] #[pyclass(name = "CustomName")]
@ -104,24 +102,24 @@ impl EmptyClass2 {
#[test] #[test]
fn custom_names() { fn custom_names() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<EmptyClass2>();
let typeobj = py.get_type::<EmptyClass2>(); py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'"); py_assert!(py, typeobj, "typeobj.custom_fn.__name__ == 'custom_fn'");
py_assert!(py, typeobj, "typeobj.custom_fn.__name__ == 'custom_fn'"); py_assert!(
py_assert!( py,
py, typeobj,
typeobj, "typeobj.custom_static.__name__ == 'custom_static'"
"typeobj.custom_static.__name__ == 'custom_static'" );
); py_assert!(
py_assert!( py,
py, typeobj,
typeobj, "typeobj.custom_getter.__name__ == 'custom_getter'"
"typeobj.custom_getter.__name__ == 'custom_getter'" );
); py_assert!(py, typeobj, "not hasattr(typeobj, 'bar')");
py_assert!(py, typeobj, "not hasattr(typeobj, 'bar')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'bar_static')");
py_assert!(py, typeobj, "not hasattr(typeobj, 'bar_static')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'foo')");
py_assert!(py, typeobj, "not hasattr(typeobj, 'foo')"); });
} }
#[pyclass] #[pyclass]
@ -137,12 +135,12 @@ impl RawIdents {
#[test] #[test]
fn test_raw_idents() { fn test_raw_idents() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<RawIdents>();
let typeobj = py.get_type::<RawIdents>(); py_assert!(py, typeobj, "not hasattr(typeobj, 'r#fn')");
py_assert!(py, typeobj, "not hasattr(typeobj, 'r#fn')"); py_assert!(py, typeobj, "hasattr(typeobj, 'fn')");
py_assert!(py, typeobj, "hasattr(typeobj, 'fn')"); py_assert!(py, typeobj, "hasattr(typeobj, 'type')");
py_assert!(py, typeobj, "hasattr(typeobj, 'type')"); });
} }
#[pyclass] #[pyclass]
@ -154,23 +152,23 @@ struct EmptyClassInModule {}
#[test] #[test]
#[ignore] #[ignore]
fn empty_class_in_module() { fn empty_class_in_module() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let module = PyModule::new(py, "test_module.nested").unwrap();
let module = PyModule::new(py, "test_module.nested").unwrap(); module.add_class::<EmptyClassInModule>().unwrap();
module.add_class::<EmptyClassInModule>().unwrap();
let ty = module.getattr("EmptyClassInModule").unwrap(); let ty = module.getattr("EmptyClassInModule").unwrap();
assert_eq!( assert_eq!(
ty.getattr("__name__").unwrap().extract::<String>().unwrap(), ty.getattr("__name__").unwrap().extract::<String>().unwrap(),
"EmptyClassInModule" "EmptyClassInModule"
); );
let module: String = ty.getattr("__module__").unwrap().extract().unwrap(); let module: String = ty.getattr("__module__").unwrap().extract().unwrap();
// Rationale: The class can be added to many modules, but will only be initialized once. // Rationale: The class can be added to many modules, but will only be initialized once.
// We currently have no way of determining a canonical module, so builtins is better // We currently have no way of determining a canonical module, so builtins is better
// than using whatever calls init first. // than using whatever calls init first.
assert_eq!(module, "builtins"); assert_eq!(module, "builtins");
});
} }
#[pyclass] #[pyclass]
@ -191,11 +189,11 @@ impl ClassWithObjectField {
#[test] #[test]
fn class_with_object_field() { fn class_with_object_field() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let ty = py.get_type::<ClassWithObjectField>();
let ty = py.get_type::<ClassWithObjectField>(); py_assert!(py, ty, "ty(5).value == 5");
py_assert!(py, ty, "ty(5).value == 5"); py_assert!(py, ty, "ty(None).value == None");
py_assert!(py, ty, "ty(None).value == None"); });
} }
#[pyclass(unsendable, subclass)] #[pyclass(unsendable, subclass)]
@ -355,46 +353,46 @@ struct DunderDictSupport {
#[test] #[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn dunder_dict_support() { fn dunder_dict_support() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = PyCell::new(
let inst = PyCell::new( py,
py, DunderDictSupport {
DunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", },
}, )
) .unwrap();
.unwrap(); py_run!(
py_run!( py,
py, inst,
inst, r#"
r#"
inst.a = 1 inst.a = 1
assert inst.a == 1 assert inst.a == 1
"# "#
); );
});
} }
// Accessing inst.__dict__ only supported in limited API from Python 3.10 // Accessing inst.__dict__ only supported in limited API from Python 3.10
#[test] #[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]
fn access_dunder_dict() { fn access_dunder_dict() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = PyCell::new(
let inst = PyCell::new( py,
py, DunderDictSupport {
DunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", },
}, )
) .unwrap();
.unwrap(); py_run!(
py_run!( py,
py, inst,
inst, r#"
r#"
inst.a = 1 inst.a = 1
assert inst.__dict__ == {'a': 1} assert inst.__dict__ == {'a': 1}
"# "#
); );
});
} }
// If the base class has dict support, child class also has dict // If the base class has dict support, child class also has dict
@ -406,26 +404,26 @@ struct InheritDict {
#[test] #[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn inherited_dict() { fn inherited_dict() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = PyCell::new(
let inst = PyCell::new( py,
py, (
( InheritDict { _value: 0 },
InheritDict { _value: 0 }, DunderDictSupport {
DunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", },
}, ),
), )
) .unwrap();
.unwrap(); py_run!(
py_run!( py,
py, inst,
inst, r#"
r#"
inst.a = 1 inst.a = 1
assert inst.a == 1 assert inst.a == 1
"# "#
); );
});
} }
#[pyclass(weakref, dict)] #[pyclass(weakref, dict)]
@ -437,20 +435,20 @@ struct WeakRefDunderDictSupport {
#[test] #[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn weakref_dunder_dict_support() { fn weakref_dunder_dict_support() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = PyCell::new(
let inst = PyCell::new( py,
py, WeakRefDunderDictSupport {
WeakRefDunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", },
}, )
) .unwrap();
.unwrap(); py_run!(
py_run!( py,
py, inst,
inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1"
"import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1" );
); });
} }
#[pyclass(weakref, subclass)] #[pyclass(weakref, subclass)]
@ -461,20 +459,20 @@ struct WeakRefSupport {
#[test] #[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn weakref_support() { fn weakref_support() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = PyCell::new(
let inst = PyCell::new( py,
py, WeakRefSupport {
WeakRefSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", },
}, )
) .unwrap();
.unwrap(); py_run!(
py_run!( py,
py, inst,
inst, "import weakref; assert weakref.ref(inst)() is inst"
"import weakref; assert weakref.ref(inst)() is inst" );
); });
} }
// If the base class has weakref support, child class also has weakref. // If the base class has weakref support, child class also has weakref.
@ -486,21 +484,21 @@ struct InheritWeakRef {
#[test] #[test]
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
fn inherited_weakref() { fn inherited_weakref() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = PyCell::new(
let inst = PyCell::new( py,
py, (
( InheritWeakRef { _value: 0 },
InheritWeakRef { _value: 0 }, WeakRefSupport {
WeakRefSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", },
}, ),
), )
) .unwrap();
.unwrap(); py_run!(
py_run!( py,
py, inst,
inst, "import weakref; assert weakref.ref(inst)() is inst"
"import weakref; assert weakref.ref(inst)() is inst" );
); });
} }

View file

@ -16,20 +16,19 @@ struct Cloneable {
fn test_cloneable_pyclass() { fn test_cloneable_pyclass() {
let c = Cloneable { x: 10 }; let c = Cloneable { x: 10 };
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let py_c = Py::new(py, c.clone()).unwrap().to_object(py);
let py_c = Py::new(py, c.clone()).unwrap().to_object(py); let c2: Cloneable = py_c.extract(py).unwrap();
assert_eq!(c, c2);
let c2: Cloneable = py_c.extract(py).unwrap(); {
assert_eq!(c, c2); let rc: PyRef<'_, Cloneable> = py_c.extract(py).unwrap();
{ assert_eq!(&c, &*rc);
let rc: PyRef<'_, Cloneable> = py_c.extract(py).unwrap(); // Drops PyRef before taking PyRefMut
assert_eq!(&c, &*rc); }
// Drops PyRef before taking PyRefMut let mrc: PyRefMut<'_, Cloneable> = py_c.extract(py).unwrap();
} assert_eq!(&c, &*mrc);
let mrc: PyRefMut<'_, Cloneable> = py_c.extract(py).unwrap(); });
assert_eq!(&c, &*mrc);
} }
#[pyclass(subclass)] #[pyclass(subclass)]
@ -63,103 +62,98 @@ struct PolymorphicContainer {
#[test] #[test]
fn test_polymorphic_container_stores_base_class() { fn test_polymorphic_container_stores_base_class() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let p = PyCell::new(
py,
PolymorphicContainer {
inner: Py::new(py, BaseClass::default()).unwrap(),
},
)
.unwrap()
.to_object(py);
let p = PyCell::new( py_assert!(py, p, "p.inner.foo() == 'BaseClass'");
py, });
PolymorphicContainer {
inner: Py::new(py, BaseClass::default()).unwrap(),
},
)
.unwrap()
.to_object(py);
py_assert!(py, p, "p.inner.foo() == 'BaseClass'");
} }
#[test] #[test]
fn test_polymorphic_container_stores_sub_class() { fn test_polymorphic_container_stores_sub_class() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let p = PyCell::new(
py,
let p = PyCell::new( PolymorphicContainer {
py, inner: Py::new(py, BaseClass::default()).unwrap(),
PolymorphicContainer { },
inner: Py::new(py, BaseClass::default()).unwrap(),
},
)
.unwrap()
.to_object(py);
p.as_ref(py)
.setattr(
"inner",
PyCell::new(
py,
PyClassInitializer::from(BaseClass::default()).add_subclass(SubClass {}),
)
.unwrap(),
) )
.unwrap(); .unwrap()
.to_object(py);
py_assert!(py, p, "p.inner.foo() == 'SubClass'"); p.as_ref(py)
.setattr(
"inner",
PyCell::new(
py,
PyClassInitializer::from(BaseClass::default()).add_subclass(SubClass {}),
)
.unwrap(),
)
.unwrap();
py_assert!(py, p, "p.inner.foo() == 'SubClass'");
});
} }
#[test] #[test]
fn test_polymorphic_container_does_not_accept_other_types() { fn test_polymorphic_container_does_not_accept_other_types() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let p = PyCell::new(
py,
PolymorphicContainer {
inner: Py::new(py, BaseClass::default()).unwrap(),
},
)
.unwrap()
.to_object(py);
let p = PyCell::new( let setattr = |value: PyObject| p.as_ref(py).setattr("inner", value);
py,
PolymorphicContainer {
inner: Py::new(py, BaseClass::default()).unwrap(),
},
)
.unwrap()
.to_object(py);
let setattr = |value: PyObject| p.as_ref(py).setattr("inner", value); assert!(setattr(1i32.into_py(py)).is_err());
assert!(setattr(py.None()).is_err());
assert!(setattr(1i32.into_py(py)).is_err()); assert!(setattr((1i32, 2i32).into_py(py)).is_err());
assert!(setattr(py.None()).is_err()); });
assert!(setattr((1i32, 2i32).into_py(py)).is_err());
} }
#[test] #[test]
fn test_pyref_as_base() { fn test_pyref_as_base() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let cell = PyCell::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap();
let cell = PyCell::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap(); // First try PyRefMut
let sub: PyRefMut<'_, SubClass> = cell.borrow_mut();
let mut base: PyRefMut<'_, BaseClass> = sub.into_super();
assert_eq!(120, base.value);
base.value = 999;
assert_eq!(999, base.value);
drop(base);
// First try PyRefMut // Repeat for PyRef
let sub: PyRefMut<'_, SubClass> = cell.borrow_mut(); let sub: PyRef<'_, SubClass> = cell.borrow();
let mut base: PyRefMut<'_, BaseClass> = sub.into_super(); let base: PyRef<'_, BaseClass> = sub.into_super();
assert_eq!(120, base.value); assert_eq!(999, base.value);
base.value = 999; });
assert_eq!(999, base.value);
drop(base);
// Repeat for PyRef
let sub: PyRef<'_, SubClass> = cell.borrow();
let base: PyRef<'_, BaseClass> = sub.into_super();
assert_eq!(999, base.value);
} }
#[test] #[test]
fn test_pycell_deref() { fn test_pycell_deref() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let cell = PyCell::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap();
let cell = PyCell::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap(); // Should be able to deref as PyAny
assert_eq!(
// Should be able to deref as PyAny cell.call_method0("foo")
assert_eq!( .and_then(PyAny::extract::<&str>)
cell.call_method0("foo") .unwrap(),
.and_then(PyAny::extract::<&str>) "SubClass"
.unwrap(), );
"SubClass" });
);
} }

View file

@ -16,14 +16,14 @@ impl EmptyClassWithNew {
#[test] #[test]
fn empty_class_with_new() { fn empty_class_with_new() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<EmptyClassWithNew>();
let typeobj = py.get_type::<EmptyClassWithNew>(); assert!(typeobj
assert!(typeobj .call((), None)
.call((), None) .unwrap()
.unwrap() .cast_as::<PyCell<EmptyClassWithNew>>()
.cast_as::<PyCell<EmptyClassWithNew>>() .is_ok());
.is_ok()); });
} }
#[pyclass] #[pyclass]
@ -87,13 +87,13 @@ impl NewWithOneArg {
#[test] #[test]
fn new_with_one_arg() { fn new_with_one_arg() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<NewWithOneArg>();
let typeobj = py.get_type::<NewWithOneArg>(); let wrp = typeobj.call((42,), None).unwrap();
let wrp = typeobj.call((42,), None).unwrap(); let obj = wrp.cast_as::<PyCell<NewWithOneArg>>().unwrap();
let obj = wrp.cast_as::<PyCell<NewWithOneArg>>().unwrap(); let obj_ref = obj.borrow();
let obj_ref = obj.borrow(); assert_eq!(obj_ref._data, 42);
assert_eq!(obj_ref._data, 42); });
} }
#[pyclass] #[pyclass]
@ -115,17 +115,17 @@ impl NewWithTwoArgs {
#[test] #[test]
fn new_with_two_args() { fn new_with_two_args() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<NewWithTwoArgs>();
let typeobj = py.get_type::<NewWithTwoArgs>(); let wrp = typeobj
let wrp = typeobj .call((10, 20), None)
.call((10, 20), None) .map_err(|e| e.print(py))
.map_err(|e| e.print(py)) .unwrap();
.unwrap(); let obj = wrp.cast_as::<PyCell<NewWithTwoArgs>>().unwrap();
let obj = wrp.cast_as::<PyCell<NewWithTwoArgs>>().unwrap(); let obj_ref = obj.borrow();
let obj_ref = obj.borrow(); assert_eq!(obj_ref._data1, 10);
assert_eq!(obj_ref._data1, 10); assert_eq!(obj_ref._data2, 20);
assert_eq!(obj_ref._data2, 20); });
} }
#[pyclass(subclass)] #[pyclass(subclass)]
@ -146,11 +146,10 @@ impl SuperClass {
/// See https://github.com/PyO3/pyo3/issues/947 for the corresponding bug. /// See https://github.com/PyO3/pyo3/issues/947 for the corresponding bug.
#[test] #[test]
fn subclass_new() { fn subclass_new() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let super_cls = py.get_type::<SuperClass>();
let super_cls = py.get_type::<SuperClass>(); let source = pyo3::indoc::indoc!(
let source = pyo3::indoc::indoc!( r#"
r#"
class Class(SuperClass): class Class(SuperClass):
def __new__(cls): def __new__(cls):
return super().__new__(cls) # This should return an instance of Class return super().__new__(cls) # This should return an instance of Class
@ -161,12 +160,13 @@ class Class(SuperClass):
c = Class() c = Class()
assert c.from_rust is False assert c.from_rust is False
"# "#
); );
let globals = PyModule::import(py, "__main__").unwrap().dict(); let globals = PyModule::import(py, "__main__").unwrap().dict();
globals.set_item("SuperClass", super_cls).unwrap(); globals.set_item("SuperClass", super_cls).unwrap();
py.run(source, Some(globals), None) py.run(source, Some(globals), None)
.map_err(|e| e.print(py)) .map_err(|e| e.print(py))
.unwrap(); .unwrap();
});
} }
#[pyclass] #[pyclass]
@ -191,9 +191,9 @@ impl NewWithCustomError {
#[test] #[test]
fn new_with_custom_error() { fn new_with_custom_error() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<NewWithCustomError>();
let typeobj = py.get_type::<NewWithCustomError>(); let err = typeobj.call0().unwrap_err();
let err = typeobj.call0().unwrap_err(); assert_eq!(err.to_string(), "ValueError: custom error");
assert_eq!(err.to_string(), "ValueError: custom error"); });
} }

View file

@ -55,52 +55,52 @@ macro_rules! assert_check_only {
#[test] #[test]
fn test_date_check() { fn test_date_check() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "date", "2018, 1, 1").unwrap();
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "date", "2018, 1, 1").unwrap(); unsafe { PyDateTime_IMPORT() }
unsafe { PyDateTime_IMPORT() } assert_check_exact!(PyDate_Check, PyDate_CheckExact, obj);
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_obj); assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_sub_obj);
assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_sub_obj); });
} }
#[test] #[test]
fn test_time_check() { fn test_time_check() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "time", "12, 30, 15").unwrap();
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "time", "12, 30, 15").unwrap(); unsafe { PyDateTime_IMPORT() }
unsafe { PyDateTime_IMPORT() }
assert_check_exact!(PyTime_Check, PyTime_CheckExact, obj); 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_obj);
assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_sub_obj); assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_sub_obj);
});
} }
#[test] #[test]
fn test_datetime_check() { fn test_datetime_check() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "datetime", "2018, 1, 1, 13, 30, 15")
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "datetime", "2018, 1, 1, 13, 30, 15") .map_err(|e| e.print(py))
.map_err(|e| e.print(py)) .unwrap();
.unwrap(); unsafe { PyDateTime_IMPORT() }
unsafe { PyDateTime_IMPORT() }
assert_check_only!(PyDate_Check, PyDate_CheckExact, obj); assert_check_only!(PyDate_Check, PyDate_CheckExact, obj);
assert_check_exact!(PyDateTime_Check, PyDateTime_CheckExact, obj); 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_obj);
assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_sub_obj); assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_sub_obj);
});
} }
#[test] #[test]
fn test_delta_check() { fn test_delta_check() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "timedelta", "1, -3").unwrap();
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "timedelta", "1, -3").unwrap(); unsafe { PyDateTime_IMPORT() }
unsafe { PyDateTime_IMPORT() }
assert_check_exact!(PyDelta_Check, PyDelta_CheckExact, obj); 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_obj);
assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_sub_obj); assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_sub_obj);
});
} }
#[test] #[test]
@ -108,20 +108,20 @@ fn test_datetime_utc() {
use assert_approx_eq::assert_approx_eq; use assert_approx_eq::assert_approx_eq;
use pyo3::types::PyDateTime; use pyo3::types::PyDateTime;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let utc = timezone_utc(py);
let utc = timezone_utc(py);
let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(utc)).unwrap(); let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(utc)).unwrap();
let locals = [("dt", dt)].into_py_dict(py); let locals = [("dt", dt)].into_py_dict(py);
let offset: f32 = py let offset: f32 = py
.eval("dt.utcoffset().total_seconds()", None, Some(locals)) .eval("dt.utcoffset().total_seconds()", None, Some(locals))
.unwrap() .unwrap()
.extract() .extract()
.unwrap(); .unwrap();
assert_approx_eq!(offset, 0f32); assert_approx_eq!(offset, 0f32);
});
} }
static INVALID_DATES: &[(i32, u8, u8)] = &[ static INVALID_DATES: &[(i32, u8, u8)] = &[
@ -143,26 +143,26 @@ static INVALID_TIMES: &[(u8, u8, u8, u32)] =
fn test_pydate_out_of_bounds() { fn test_pydate_out_of_bounds() {
use pyo3::types::PyDate; use pyo3::types::PyDate;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); for val in INVALID_DATES {
for val in INVALID_DATES { let (year, month, day) = val;
let (year, month, day) = val; let dt = PyDate::new(py, *year, *month, *day);
let dt = PyDate::new(py, *year, *month, *day); dt.unwrap_err();
dt.unwrap_err(); }
} });
} }
#[test] #[test]
fn test_pytime_out_of_bounds() { fn test_pytime_out_of_bounds() {
use pyo3::types::PyTime; use pyo3::types::PyTime;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); for val in INVALID_TIMES {
for val in INVALID_TIMES { let (hour, minute, second, microsecond) = val;
let (hour, minute, second, microsecond) = val; let dt = PyTime::new(py, *hour, *minute, *second, *microsecond, None);
let dt = PyTime::new(py, *hour, *minute, *second, *microsecond, None); dt.unwrap_err();
dt.unwrap_err(); }
} });
} }
#[test] #[test]
@ -170,31 +170,31 @@ fn test_pydatetime_out_of_bounds() {
use pyo3::types::PyDateTime; use pyo3::types::PyDateTime;
use std::iter; use std::iter;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let valid_time = (0, 0, 0, 0);
let valid_time = (0, 0, 0, 0); let valid_date = (2018, 1, 1);
let valid_date = (2018, 1, 1);
let invalid_dates = INVALID_DATES.iter().zip(iter::repeat(&valid_time)); let invalid_dates = INVALID_DATES.iter().zip(iter::repeat(&valid_time));
let invalid_times = iter::repeat(&valid_date).zip(INVALID_TIMES.iter()); let invalid_times = iter::repeat(&valid_date).zip(INVALID_TIMES.iter());
let vals = invalid_dates.chain(invalid_times); let vals = invalid_dates.chain(invalid_times);
for val in vals { for val in vals {
let (date, time) = val; let (date, time) = val;
let (year, month, day) = date; let (year, month, day) = date;
let (hour, minute, second, microsecond) = time; let (hour, minute, second, microsecond) = time;
let dt = PyDateTime::new( let dt = PyDateTime::new(
py, py,
*year, *year,
*month, *month,
*day, *day,
*hour, *hour,
*minute, *minute,
*second, *second,
*microsecond, *microsecond,
None, None,
); );
dt.unwrap_err(); dt.unwrap_err();
} }
});
} }

View file

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

View file

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

View file

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

View file

@ -15,27 +15,21 @@ struct ClassWithFreelist {}
#[test] #[test]
fn class_with_freelist() { fn class_with_freelist() {
let ptr; let ptr = Python::with_gil(|py| {
{
let gil = Python::acquire_gil();
let py = gil.python();
let inst = Py::new(py, ClassWithFreelist {}).unwrap(); let inst = Py::new(py, ClassWithFreelist {}).unwrap();
let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap(); let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap();
ptr = inst.as_ptr(); let ptr = inst.as_ptr();
drop(inst); drop(inst);
} ptr
});
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst3 = Py::new(py, ClassWithFreelist {}).unwrap(); let inst3 = Py::new(py, ClassWithFreelist {}).unwrap();
assert_eq!(ptr, inst3.as_ptr()); assert_eq!(ptr, inst3.as_ptr());
let inst4 = Py::new(py, ClassWithFreelist {}).unwrap(); let inst4 = Py::new(py, ClassWithFreelist {}).unwrap();
assert_ne!(ptr, inst4.as_ptr()) assert_ne!(ptr, inst4.as_ptr())
} });
} }
struct TestDropCall { struct TestDropCall {
@ -60,9 +54,7 @@ fn data_is_dropped() {
let drop_called1 = Arc::new(AtomicBool::new(false)); let drop_called1 = Arc::new(AtomicBool::new(false));
let drop_called2 = Arc::new(AtomicBool::new(false)); let drop_called2 = Arc::new(AtomicBool::new(false));
{ Python::with_gil(|py| {
let gil = Python::acquire_gil();
let py = gil.python();
let data_is_dropped = DataIsDropped { let data_is_dropped = DataIsDropped {
member1: TestDropCall { member1: TestDropCall {
drop_called: Arc::clone(&drop_called1), drop_called: Arc::clone(&drop_called1),
@ -75,7 +67,7 @@ fn data_is_dropped() {
assert!(!drop_called1.load(Ordering::Relaxed)); assert!(!drop_called1.load(Ordering::Relaxed));
assert!(!drop_called2.load(Ordering::Relaxed)); assert!(!drop_called2.load(Ordering::Relaxed));
drop(inst); drop(inst);
} });
assert!(drop_called1.load(Ordering::Relaxed)); assert!(drop_called1.load(Ordering::Relaxed));
assert!(drop_called2.load(Ordering::Relaxed)); assert!(drop_called2.load(Ordering::Relaxed));
@ -95,8 +87,9 @@ impl GcIntegration {
} }
fn __clear__(&mut self) { fn __clear__(&mut self) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
self.self_ref = gil.python().None(); self.self_ref = py.None();
});
} }
} }
@ -104,9 +97,7 @@ impl GcIntegration {
fn gc_integration() { fn gc_integration() {
let drop_called = Arc::new(AtomicBool::new(false)); let drop_called = Arc::new(AtomicBool::new(false));
{ Python::with_gil(|py| {
let gil = Python::acquire_gil();
let py = gil.python();
let inst = PyCell::new( let inst = PyCell::new(
py, py,
GcIntegration { GcIntegration {
@ -122,12 +113,12 @@ fn gc_integration() {
borrow.self_ref = inst.to_object(py); borrow.self_ref = inst.to_object(py);
py_run!(py, inst, "import gc; assert inst in gc.get_objects()"); py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
} });
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); py.run("import gc; gc.collect()", None, None).unwrap();
py.run("import gc; gc.collect()", None, None).unwrap(); assert!(drop_called.load(Ordering::Relaxed));
assert!(drop_called.load(Ordering::Relaxed)); });
} }
#[pyclass(subclass)] #[pyclass(subclass)]
@ -180,9 +171,7 @@ fn inheritance_with_new_methods_with_drop() {
let drop_called1 = Arc::new(AtomicBool::new(false)); let drop_called1 = Arc::new(AtomicBool::new(false));
let drop_called2 = Arc::new(AtomicBool::new(false)); let drop_called2 = Arc::new(AtomicBool::new(false));
{ Python::with_gil(|py| {
let gil = Python::acquire_gil();
let py = gil.python();
let _typebase = py.get_type::<BaseClassWithDrop>(); let _typebase = py.get_type::<BaseClassWithDrop>();
let typeobj = py.get_type::<SubClassWithDrop>(); let typeobj = py.get_type::<SubClassWithDrop>();
let inst = typeobj.call((), None).unwrap(); 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)); obj_ref_mut.data = Some(Arc::clone(&drop_called1));
let base: &mut BaseClassWithDrop = obj_ref_mut.as_mut(); let base: &mut BaseClassWithDrop = obj_ref_mut.as_mut();
base.data = Some(Arc::clone(&drop_called2)); base.data = Some(Arc::clone(&drop_called2));
} });
assert!(drop_called1.load(Ordering::Relaxed)); assert!(drop_called1.load(Ordering::Relaxed));
assert!(drop_called2.load(Ordering::Relaxed)); assert!(drop_called2.load(Ordering::Relaxed));
@ -228,40 +217,39 @@ unsafe fn get_type_traverse(tp: *mut pyo3::ffi::PyTypeObject) -> Option<pyo3::ff
#[test] #[test]
fn gc_during_borrow() { fn gc_during_borrow() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); unsafe {
// declare a dummy visitor function
extern "C" fn novisit(
_object: *mut pyo3::ffi::PyObject,
_arg: *mut core::ffi::c_void,
) -> std::os::raw::c_int {
0
}
unsafe { // get the traverse function
// declare a dummy visitor function let ty = TraversableClass::type_object(py).as_type_ptr();
extern "C" fn novisit( let traverse = get_type_traverse(ty).unwrap();
_object: *mut pyo3::ffi::PyObject,
_arg: *mut core::ffi::c_void, // create an object and check that traversing it works normally
) -> std::os::raw::c_int { // when it's not borrowed
0 let cell = PyCell::new(py, TraversableClass::new()).unwrap();
let obj = cell.to_object(py);
assert!(!cell.borrow().traversed.load(Ordering::Relaxed));
traverse(obj.as_ptr(), novisit, std::ptr::null_mut());
assert!(cell.borrow().traversed.load(Ordering::Relaxed));
// create an object and check that it is not traversed if the GC
// is invoked while it is already borrowed mutably
let cell2 = PyCell::new(py, TraversableClass::new()).unwrap();
let obj2 = cell2.to_object(py);
let guard = cell2.borrow_mut();
assert!(!guard.traversed.load(Ordering::Relaxed));
traverse(obj2.as_ptr(), novisit, std::ptr::null_mut());
assert!(!guard.traversed.load(Ordering::Relaxed));
drop(guard);
} }
});
// get the traverse function
let ty = TraversableClass::type_object(py).as_type_ptr();
let traverse = get_type_traverse(ty).unwrap();
// create an object and check that traversing it works normally
// when it's not borrowed
let cell = PyCell::new(py, TraversableClass::new()).unwrap();
let obj = cell.to_object(py);
assert!(!cell.borrow().traversed.load(Ordering::Relaxed));
traverse(obj.as_ptr(), novisit, std::ptr::null_mut());
assert!(cell.borrow().traversed.load(Ordering::Relaxed));
// create an object and check that it is not traversed if the GC
// is invoked while it is already borrowed mutably
let cell2 = PyCell::new(py, TraversableClass::new()).unwrap();
let obj2 = cell2.to_object(py);
let guard = cell2.borrow_mut();
assert!(!guard.traversed.load(Ordering::Relaxed));
traverse(obj2.as_ptr(), novisit, std::ptr::null_mut());
assert!(!guard.traversed.load(Ordering::Relaxed));
drop(guard);
}
} }
#[pyclass] #[pyclass]

View file

@ -17,27 +17,21 @@ struct ClassWithFreelist {}
#[test] #[test]
fn class_with_freelist() { fn class_with_freelist() {
let ptr; let ptr = Python::with_gil(|py| {
{
let gil = Python::acquire_gil();
let py = gil.python();
let inst = Py::new(py, ClassWithFreelist {}).unwrap(); let inst = Py::new(py, ClassWithFreelist {}).unwrap();
let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap(); let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap();
ptr = inst.as_ptr(); let ptr = inst.as_ptr();
drop(inst); drop(inst);
} ptr
});
{
let gil = Python::acquire_gil();
let py = gil.python();
Python::with_gil(|py| {
let inst3 = Py::new(py, ClassWithFreelist {}).unwrap(); let inst3 = Py::new(py, ClassWithFreelist {}).unwrap();
assert_eq!(ptr, inst3.as_ptr()); assert_eq!(ptr, inst3.as_ptr());
let inst4 = Py::new(py, ClassWithFreelist {}).unwrap(); let inst4 = Py::new(py, ClassWithFreelist {}).unwrap();
assert_ne!(ptr, inst4.as_ptr()) assert_ne!(ptr, inst4.as_ptr())
} });
} }
struct TestDropCall { struct TestDropCall {
@ -62,9 +56,7 @@ fn data_is_dropped() {
let drop_called1 = Arc::new(AtomicBool::new(false)); let drop_called1 = Arc::new(AtomicBool::new(false));
let drop_called2 = Arc::new(AtomicBool::new(false)); let drop_called2 = Arc::new(AtomicBool::new(false));
{ Python::with_gil(|py| {
let gil = Python::acquire_gil();
let py = gil.python();
let data_is_dropped = DataIsDropped { let data_is_dropped = DataIsDropped {
member1: TestDropCall { member1: TestDropCall {
drop_called: Arc::clone(&drop_called1), drop_called: Arc::clone(&drop_called1),
@ -77,7 +69,7 @@ fn data_is_dropped() {
assert!(!drop_called1.load(Ordering::Relaxed)); assert!(!drop_called1.load(Ordering::Relaxed));
assert!(!drop_called2.load(Ordering::Relaxed)); assert!(!drop_called2.load(Ordering::Relaxed));
drop(inst); drop(inst);
} });
assert!(drop_called1.load(Ordering::Relaxed)); assert!(drop_called1.load(Ordering::Relaxed));
assert!(drop_called2.load(Ordering::Relaxed)); assert!(drop_called2.load(Ordering::Relaxed));
@ -97,8 +89,9 @@ impl PyGCProtocol for GcIntegration {
} }
fn __clear__(&mut self) { fn __clear__(&mut self) {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
self.self_ref = gil.python().None(); self.self_ref = py.None();
})
} }
} }
@ -106,9 +99,7 @@ impl PyGCProtocol for GcIntegration {
fn gc_integration() { fn gc_integration() {
let drop_called = Arc::new(AtomicBool::new(false)); let drop_called = Arc::new(AtomicBool::new(false));
{ Python::with_gil(|py| {
let gil = Python::acquire_gil();
let py = gil.python();
let inst = PyCell::new( let inst = PyCell::new(
py, py,
GcIntegration { GcIntegration {
@ -122,12 +113,12 @@ fn gc_integration() {
let mut borrow = inst.borrow_mut(); let mut borrow = inst.borrow_mut();
borrow.self_ref = inst.to_object(py); borrow.self_ref = inst.to_object(py);
} });
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); py.run("import gc; gc.collect()", None, None).unwrap();
py.run("import gc; gc.collect()", None, None).unwrap(); assert!(drop_called.load(Ordering::Relaxed));
assert!(drop_called.load(Ordering::Relaxed)); });
} }
#[pyclass] #[pyclass]
@ -143,10 +134,10 @@ impl PyGCProtocol for GcIntegration2 {
#[test] #[test]
fn gc_integration2() { fn gc_integration2() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = PyCell::new(py, GcIntegration2 {}).unwrap();
let inst = PyCell::new(py, GcIntegration2 {}).unwrap(); py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
py_run!(py, inst, "import gc; assert inst in gc.get_objects()"); });
} }
#[pyclass(subclass)] #[pyclass(subclass)]
@ -199,9 +190,7 @@ fn inheritance_with_new_methods_with_drop() {
let drop_called1 = Arc::new(AtomicBool::new(false)); let drop_called1 = Arc::new(AtomicBool::new(false));
let drop_called2 = Arc::new(AtomicBool::new(false)); let drop_called2 = Arc::new(AtomicBool::new(false));
{ Python::with_gil(|py| {
let gil = Python::acquire_gil();
let py = gil.python();
let _typebase = py.get_type::<BaseClassWithDrop>(); let _typebase = py.get_type::<BaseClassWithDrop>();
let typeobj = py.get_type::<SubClassWithDrop>(); let typeobj = py.get_type::<SubClassWithDrop>();
let inst = typeobj.call((), None).unwrap(); 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)); obj_ref_mut.data = Some(Arc::clone(&drop_called1));
let base: &mut BaseClassWithDrop = obj_ref_mut.as_mut(); let base: &mut BaseClassWithDrop = obj_ref_mut.as_mut();
base.data = Some(Arc::clone(&drop_called2)); base.data = Some(Arc::clone(&drop_called2));
} });
assert!(drop_called1.load(Ordering::Relaxed)); assert!(drop_called1.load(Ordering::Relaxed));
assert!(drop_called2.load(Ordering::Relaxed)); assert!(drop_called2.load(Ordering::Relaxed));
@ -245,38 +234,37 @@ unsafe fn get_type_traverse(tp: *mut pyo3::ffi::PyTypeObject) -> Option<pyo3::ff
#[test] #[test]
fn gc_during_borrow() { fn gc_during_borrow() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); unsafe {
// declare a dummy visitor function
extern "C" fn novisit(
_object: *mut pyo3::ffi::PyObject,
_arg: *mut core::ffi::c_void,
) -> std::os::raw::c_int {
0
}
unsafe { // get the traverse function
// declare a dummy visitor function let ty = TraversableClass::type_object(py).as_type_ptr();
extern "C" fn novisit( let traverse = get_type_traverse(ty).unwrap();
_object: *mut pyo3::ffi::PyObject,
_arg: *mut core::ffi::c_void, // create an object and check that traversing it works normally
) -> std::os::raw::c_int { // when it's not borrowed
0 let cell = PyCell::new(py, TraversableClass::new()).unwrap();
let obj = cell.to_object(py);
assert!(!cell.borrow().traversed.load(Ordering::Relaxed));
traverse(obj.as_ptr(), novisit, std::ptr::null_mut());
assert!(cell.borrow().traversed.load(Ordering::Relaxed));
// create an object and check that it is not traversed if the GC
// is invoked while it is already borrowed mutably
let cell2 = PyCell::new(py, TraversableClass::new()).unwrap();
let obj2 = cell2.to_object(py);
let guard = cell2.borrow_mut();
assert!(!guard.traversed.load(Ordering::Relaxed));
traverse(obj2.as_ptr(), novisit, std::ptr::null_mut());
assert!(!guard.traversed.load(Ordering::Relaxed));
drop(guard);
} }
});
// get the traverse function
let ty = TraversableClass::type_object(py).as_type_ptr();
let traverse = get_type_traverse(ty).unwrap();
// create an object and check that traversing it works normally
// when it's not borrowed
let cell = PyCell::new(py, TraversableClass::new()).unwrap();
let obj = cell.to_object(py);
assert!(!cell.borrow().traversed.load(Ordering::Relaxed));
traverse(obj.as_ptr(), novisit, std::ptr::null_mut());
assert!(cell.borrow().traversed.load(Ordering::Relaxed));
// create an object and check that it is not traversed if the GC
// is invoked while it is already borrowed mutably
let cell2 = PyCell::new(py, TraversableClass::new()).unwrap();
let obj2 = cell2.to_object(py);
let guard = cell2.borrow_mut();
assert!(!guard.traversed.load(Ordering::Relaxed));
traverse(obj2.as_ptr(), novisit, std::ptr::null_mut());
assert!(!guard.traversed.load(Ordering::Relaxed));
drop(guard);
}
} }

View file

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

View file

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

View file

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

View file

@ -72,40 +72,39 @@ fn map_dict(py: Python<'_>) -> &pyo3::types::PyDict {
#[test] #[test]
fn test_getitem() { fn test_getitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = map_dict(py);
let d = map_dict(py);
py_assert!(py, *d, "m['1'] == 0"); py_assert!(py, *d, "m['1'] == 0");
py_assert!(py, *d, "m['2'] == 1"); py_assert!(py, *d, "m['2'] == 1");
py_assert!(py, *d, "m['3'] == 2"); py_assert!(py, *d, "m['3'] == 2");
py_expect_exception!(py, *d, "print(m['4'])", PyKeyError); py_expect_exception!(py, *d, "print(m['4'])", PyKeyError);
});
} }
#[test] #[test]
fn test_setitem() { fn test_setitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = map_dict(py);
let d = map_dict(py);
py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4"); py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4");
py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0"); py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0");
py_assert!(py, *d, "len(m) == 4"); py_assert!(py, *d, "len(m) == 4");
py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError); py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError);
py_expect_exception!(py, *d, "m[0] = -1", PyTypeError); py_expect_exception!(py, *d, "m[0] = -1", PyTypeError);
});
} }
#[test] #[test]
fn test_delitem() { fn test_delitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = map_dict(py);
py_run!(
let d = map_dict(py); py,
py_run!( *d,
py, "del m['1']; assert len(m) == 2 and m['2'] == 1 and m['3'] == 2"
*d, );
"del m['1']; assert len(m) == 2 and m['2'] == 1 and m['3'] == 2" py_expect_exception!(py, *d, "del m[-1]", PyTypeError);
); py_expect_exception!(py, *d, "del m['4']", PyKeyError);
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] #[test]
fn instance_method() { fn instance_method() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let obj = PyCell::new(py, InstanceMethod { member: 42 }).unwrap();
let obj_ref = obj.borrow();
let obj = PyCell::new(py, InstanceMethod { member: 42 }).unwrap(); assert_eq!(obj_ref.method(), 42);
let obj_ref = obj.borrow(); py_assert!(py, obj, "obj.method() == 42");
assert_eq!(obj_ref.method(), 42); py_assert!(py, obj, "obj.add_other(obj) == 84");
py_assert!(py, obj, "obj.method() == 42"); py_assert!(py, obj, "obj.method.__doc__ == 'Test method'");
py_assert!(py, obj, "obj.add_other(obj) == 84"); });
py_assert!(py, obj, "obj.method.__doc__ == 'Test method'");
} }
#[pyclass] #[pyclass]
@ -52,14 +51,13 @@ impl InstanceMethodWithArgs {
#[test] #[test]
fn instance_method_with_args() { fn instance_method_with_args() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let obj = PyCell::new(py, InstanceMethodWithArgs { member: 7 }).unwrap();
let obj_ref = obj.borrow();
let obj = PyCell::new(py, InstanceMethodWithArgs { member: 7 }).unwrap(); assert_eq!(obj_ref.method(6), 42);
let obj_ref = obj.borrow(); py_assert!(py, obj, "obj.method(3) == 21");
assert_eq!(obj_ref.method(6), 42); py_assert!(py, obj, "obj.method(multiplier=6) == 42");
py_assert!(py, obj, "obj.method(3) == 21"); });
py_assert!(py, obj, "obj.method(multiplier=6) == 42");
} }
#[pyclass] #[pyclass]
@ -81,14 +79,13 @@ impl ClassMethod {
#[test] #[test]
fn class_method() { fn class_method() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = [("C", py.get_type::<ClassMethod>())].into_py_dict(py);
py_assert!(py, *d, "C.method() == 'ClassMethod.method()!'");
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() == 'ClassMethod.method()!'"); py_assert!(py, *d, "C().method.__doc__ == 'Test class method.'");
py_assert!(py, *d, "C.method.__doc__ == 'Test class method.'"); });
py_assert!(py, *d, "C().method.__doc__ == 'Test class method.'");
} }
#[pyclass] #[pyclass]
@ -104,15 +101,14 @@ impl ClassMethodWithArgs {
#[test] #[test]
fn class_method_with_args() { fn class_method_with_args() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = [("C", py.get_type::<ClassMethodWithArgs>())].into_py_dict(py);
py_assert!(
let d = [("C", py.get_type::<ClassMethodWithArgs>())].into_py_dict(py); py,
py_assert!( *d,
py, "C.method('abc') == 'ClassMethodWithArgs.method(abc)'"
*d, );
"C.method('abc') == 'ClassMethodWithArgs.method(abc)'" });
);
} }
#[pyclass] #[pyclass]
@ -134,16 +130,15 @@ impl StaticMethod {
#[test] #[test]
fn static_method() { fn static_method() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); assert_eq!(StaticMethod::method(py), "StaticMethod.method()!");
assert_eq!(StaticMethod::method(py), "StaticMethod.method()!"); let d = [("C", py.get_type::<StaticMethod>())].into_py_dict(py);
py_assert!(py, *d, "C.method() == 'StaticMethod.method()!'");
let d = [("C", py.get_type::<StaticMethod>())].into_py_dict(py); py_assert!(py, *d, "C().method() == 'StaticMethod.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() == 'StaticMethod.method()!'"); py_assert!(py, *d, "C().method.__doc__ == 'Test static method.'");
py_assert!(py, *d, "C.method.__doc__ == 'Test static method.'"); });
py_assert!(py, *d, "C().method.__doc__ == 'Test static method.'");
} }
#[pyclass] #[pyclass]
@ -159,13 +154,12 @@ impl StaticMethodWithArgs {
#[test] #[test]
fn static_method_with_args() { fn static_method_with_args() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); assert_eq!(StaticMethodWithArgs::method(py, 1234), "0x4d2");
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'");
let d = [("C", py.get_type::<StaticMethodWithArgs>())].into_py_dict(py); });
py_assert!(py, *d, "C.method(1337) == '0x539'");
} }
#[pyclass] #[pyclass]
@ -305,315 +299,315 @@ impl MethArgs {
#[test] #[test]
fn meth_args() { fn meth_args() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = Py::new(py, MethArgs {}).unwrap();
let inst = Py::new(py, MethArgs {}).unwrap();
py_run!(py, inst, "assert inst.get_optional() == 10"); py_run!(py, inst, "assert inst.get_optional() == 10");
py_run!(py, inst, "assert inst.get_optional(100) == 100"); py_run!(py, inst, "assert inst.get_optional(100) == 100");
py_run!(py, inst, "assert inst.get_optional2() == None"); py_run!(py, inst, "assert inst.get_optional2() == None");
py_run!(py, inst, "assert inst.get_optional2(100) == 100"); py_run!(py, inst, "assert inst.get_optional2(100) == 100");
py_run!(py, inst, "assert inst.get_optional3() == None"); py_run!(py, inst, "assert inst.get_optional3() == None");
py_run!(py, inst, "assert inst.get_optional3(100) == 100"); py_run!(py, inst, "assert inst.get_optional3(100) == 100");
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_optional_positional(1, 2, 3) == 2" "assert inst.get_optional_positional(1, 2, 3) == 2"
); );
py_run!(py, inst, "assert inst.get_optional_positional(1) == None"); py_run!(py, inst, "assert inst.get_optional_positional(1) == None");
py_run!(py, inst, "assert inst.get_default() == 10"); py_run!(py, inst, "assert inst.get_default() == 10");
py_run!(py, inst, "assert inst.get_default(100) == 100"); py_run!(py, inst, "assert inst.get_default(100) == 100");
py_run!(py, inst, "assert inst.get_kwarg() == 10"); py_run!(py, inst, "assert inst.get_kwarg() == 10");
py_expect_exception!(py, inst, "inst.get_kwarg(100)", PyTypeError); py_expect_exception!(py, inst, "inst.get_kwarg(100)", PyTypeError);
py_run!(py, inst, "assert inst.get_kwarg(test=100) == 100"); py_run!(py, inst, "assert inst.get_kwarg(test=100) == 100");
py_run!(py, inst, "assert inst.get_kwargs() == [(), None]"); py_run!(py, inst, "assert inst.get_kwargs() == [(), None]");
py_run!(py, inst, "assert inst.get_kwargs(1,2,3) == [(1,2,3), None]"); py_run!(py, inst, "assert inst.get_kwargs(1,2,3) == [(1,2,3), None]");
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_kwargs(t=1,n=2) == [(), {'t': 1, 'n': 2}]" "assert inst.get_kwargs(t=1,n=2) == [(), {'t': 1, 'n': 2}]"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]" "assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]"
); );
py_run!(py, inst, "assert inst.get_pos_arg_kw(1) == [1, (), None]"); py_run!(py, inst, "assert inst.get_pos_arg_kw(1) == [1, (), None]");
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_arg_kw(1, 2, 3) == [1, (2, 3), None]" "assert inst.get_pos_arg_kw(1, 2, 3) == [1, (2, 3), None]"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_arg_kw(1, b=2) == [1, (), {'b': 2}]" "assert inst.get_pos_arg_kw(1, b=2) == [1, (), {'b': 2}]"
); );
py_run!(py, inst, "assert inst.get_pos_arg_kw(a=1) == [1, (), None]"); py_run!(py, inst, "assert inst.get_pos_arg_kw(a=1) == [1, (), None]");
py_expect_exception!(py, inst, "inst.get_pos_arg_kw()", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw()", PyTypeError);
py_expect_exception!(py, inst, "inst.get_pos_arg_kw(1, a=1)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw(1, a=1)", PyTypeError);
py_expect_exception!(py, inst, "inst.get_pos_arg_kw(b=2)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw(b=2)", PyTypeError);
py_run!(py, inst, "assert inst.get_pos_only(10, 11) == 21"); py_run!(py, inst, "assert inst.get_pos_only(10, 11) == 21");
py_expect_exception!(py, inst, "inst.get_pos_only(10, b = 11)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_only(10, b = 11)", PyTypeError);
py_expect_exception!(py, inst, "inst.get_pos_only(a = 10, b = 11)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_only(a = 10, b = 11)", PyTypeError);
py_run!(py, inst, "assert inst.get_pos_only_and_pos(10, 11) == 21"); py_run!(py, inst, "assert inst.get_pos_only_and_pos(10, 11) == 21");
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_and_pos(10, b = 11) == 21" "assert inst.get_pos_only_and_pos(10, b = 11) == 21"
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_pos_only_and_pos(a = 10, b = 11)", "inst.get_pos_only_and_pos(a = 10, b = 11)",
PyTypeError PyTypeError
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_and_pos_and_kw(10, 11) == 26" "assert inst.get_pos_only_and_pos_and_kw(10, 11) == 26"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_and_pos_and_kw(10, b = 11) == 26" "assert inst.get_pos_only_and_pos_and_kw(10, b = 11) == 26"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_and_pos_and_kw(10, 11, c = 0) == 21" "assert inst.get_pos_only_and_pos_and_kw(10, 11, c = 0) == 21"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_and_pos_and_kw(10, b = 11, c = 0) == 21" "assert inst.get_pos_only_and_pos_and_kw(10, b = 11, c = 0) == 21"
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_pos_only_and_pos_and_kw(a = 10, b = 11)", "inst.get_pos_only_and_pos_and_kw(a = 10, b = 11)",
PyTypeError PyTypeError
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_and_kw_only(10, b = 11) == 21" "assert inst.get_pos_only_and_kw_only(10, b = 11) == 21"
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_pos_only_and_kw_only(10, 11)", "inst.get_pos_only_and_kw_only(10, 11)",
PyTypeError PyTypeError
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_pos_only_and_kw_only(a = 10, b = 11)", "inst.get_pos_only_and_kw_only(a = 10, b = 11)",
PyTypeError PyTypeError
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_and_kw_only_with_default(10) == 13" "assert inst.get_pos_only_and_kw_only_with_default(10) == 13"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_and_kw_only_with_default(10, b = 11) == 21" "assert inst.get_pos_only_and_kw_only_with_default(10, b = 11) == 21"
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_pos_only_and_kw_only_with_default(10, 11)", "inst.get_pos_only_and_kw_only_with_default(10, 11)",
PyTypeError PyTypeError
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_pos_only_and_kw_only_with_default(a = 10, b = 11)", "inst.get_pos_only_and_kw_only_with_default(a = 10, b = 11)",
PyTypeError PyTypeError
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_all_arg_types_together(10, 10, c = 10) == 35" "assert inst.get_all_arg_types_together(10, 10, c = 10) == 35"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_all_arg_types_together(10, 10, c = 10, d = 10) == 40" "assert inst.get_all_arg_types_together(10, 10, c = 10, d = 10) == 40"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_all_arg_types_together(10, b = 10, c = 10, d = 10) == 40" "assert inst.get_all_arg_types_together(10, b = 10, c = 10, d = 10) == 40"
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_all_arg_types_together(10, 10, 10)", "inst.get_all_arg_types_together(10, 10, 10)",
PyTypeError PyTypeError
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_all_arg_types_together(a = 10, b = 10, c = 10)", "inst.get_all_arg_types_together(a = 10, b = 10, c = 10)",
PyTypeError PyTypeError
); );
py_run!(py, inst, "assert inst.get_pos_only_with_varargs(10) == 10"); py_run!(py, inst, "assert inst.get_pos_only_with_varargs(10) == 10");
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_with_varargs(10, 10) == 20" "assert inst.get_pos_only_with_varargs(10, 10) == 20"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_with_varargs(10, 10, 10, 10, 10) == 50" "assert inst.get_pos_only_with_varargs(10, 10, 10, 10, 10) == 50"
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_pos_only_with_varargs(a = 10)", "inst.get_pos_only_with_varargs(a = 10)",
PyTypeError PyTypeError
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_with_kwargs(10) == [10, None]" "assert inst.get_pos_only_with_kwargs(10) == [10, None]"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_with_kwargs(10, b = 10) == [10, {'b': 10}]" "assert inst.get_pos_only_with_kwargs(10, b = 10) == [10, {'b': 10}]"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_only_with_kwargs(10, b = 10, c = 10, d = 10, e = 10) == [10, {'b': 10, 'c': 10, 'd': 10, 'e': 10}]" "assert inst.get_pos_only_with_kwargs(10, b = 10, c = 10, d = 10, e = 10) == [10, {'b': 10, 'c': 10, 'd': 10, 'e': 10}]"
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_pos_only_with_kwargs(a = 10)", "inst.get_pos_only_with_kwargs(a = 10)",
PyTypeError PyTypeError
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_pos_only_with_kwargs(a = 10, b = 10)", "inst.get_pos_only_with_kwargs(a = 10, b = 10)",
PyTypeError PyTypeError
); );
py_run!(py, inst, "assert inst.get_kwargs_only_with_defaults() == 5"); py_run!(py, inst, "assert inst.get_kwargs_only_with_defaults() == 5");
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_kwargs_only_with_defaults(a = 8) == 11" "assert inst.get_kwargs_only_with_defaults(a = 8) == 11"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_kwargs_only_with_defaults(b = 8) == 10" "assert inst.get_kwargs_only_with_defaults(b = 8) == 10"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_kwargs_only_with_defaults(a = 1, b = 1) == 2" "assert inst.get_kwargs_only_with_defaults(a = 1, b = 1) == 2"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_kwargs_only_with_defaults(b = 1, a = 1) == 2" "assert inst.get_kwargs_only_with_defaults(b = 1, a = 1) == 2"
); );
py_run!(py, inst, "assert inst.get_kwargs_only(a = 1, b = 1) == 2"); py_run!(py, inst, "assert inst.get_kwargs_only(a = 1, b = 1) == 2");
py_run!(py, inst, "assert inst.get_kwargs_only(b = 1, a = 1) == 2"); py_run!(py, inst, "assert inst.get_kwargs_only(b = 1, a = 1) == 2");
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_kwargs_only_with_some_default(a = 2, b = 1) == 3" "assert inst.get_kwargs_only_with_some_default(a = 2, b = 1) == 3"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_kwargs_only_with_some_default(b = 1) == 2" "assert inst.get_kwargs_only_with_some_default(b = 1) == 2"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_kwargs_only_with_some_default(b = 1, a = 2) == 3" "assert inst.get_kwargs_only_with_some_default(b = 1, a = 2) == 3"
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_kwargs_only_with_some_default()", "inst.get_kwargs_only_with_some_default()",
PyTypeError PyTypeError
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_args_and_required_keyword(1, 2, a=3) == ((1, 2), 3)" "assert inst.get_args_and_required_keyword(1, 2, a=3) == ((1, 2), 3)"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_args_and_required_keyword(a=1) == ((), 1)" "assert inst.get_args_and_required_keyword(a=1) == ((), 1)"
); );
py_expect_exception!( py_expect_exception!(
py, py,
inst, inst,
"inst.get_args_and_required_keyword()", "inst.get_args_and_required_keyword()",
PyTypeError PyTypeError
); );
py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1) == 6"); py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1) == 6");
py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1, 2) == 6"); py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1, 2) == 6");
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_arg_kw_sep1(1, 2, c=13) == 16" "assert inst.get_pos_arg_kw_sep1(1, 2, c=13) == 16"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_arg_kw_sep1(a=1, b=2, c=13) == 16" "assert inst.get_pos_arg_kw_sep1(a=1, b=2, c=13) == 16"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_arg_kw_sep1(b=2, c=13, a=1) == 16" "assert inst.get_pos_arg_kw_sep1(b=2, c=13, a=1) == 16"
); );
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_arg_kw_sep1(c=13, b=2, a=1) == 16" "assert inst.get_pos_arg_kw_sep1(c=13, b=2, a=1) == 16"
); );
py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep1(1, 2, 3)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep1(1, 2, 3)", PyTypeError);
py_run!(py, inst, "assert inst.get_pos_arg_kw_sep2(1) == 6"); py_run!(py, inst, "assert inst.get_pos_arg_kw_sep2(1) == 6");
py_run!( py_run!(
py, py,
inst, inst,
"assert inst.get_pos_arg_kw_sep2(1, b=12, c=13) == 26" "assert inst.get_pos_arg_kw_sep2(1, b=12, c=13) == 26"
); );
py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep2(1, 2)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep2(1, 2)", PyTypeError);
py_run!(py, inst, "assert inst.get_pos_kw(1, b=2) == [1, {'b': 2}]"); py_run!(py, inst, "assert inst.get_pos_kw(1, b=2) == [1, {'b': 2}]");
py_expect_exception!(py, inst, "inst.get_pos_kw(1,2)", PyTypeError); 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"); py_run!(py, inst, "assert inst.args_as_vec(1,2,3) == 6");
});
} }
#[pyclass] #[pyclass]
@ -638,20 +632,20 @@ impl MethDocs {
#[test] #[test]
fn meth_doc() { fn meth_doc() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = [("C", py.get_type::<MethDocs>())].into_py_dict(py);
let d = [("C", py.get_type::<MethDocs>())].into_py_dict(py); py_assert!(py, *d, "C.__doc__ == 'A class with \"documentation\".'");
py_assert!(py, *d, "C.__doc__ == 'A class with \"documentation\".'"); py_assert!(
py_assert!( py,
py, *d,
*d, "C.method.__doc__ == 'A method with \"documentation\" as well.'"
"C.method.__doc__ == 'A method with \"documentation\" as well.'" );
); py_assert!(
py_assert!( py,
py, *d,
*d, "C.x.__doc__ == '`int`: a very \"important\" member of \\'this\\' instance.'"
"C.x.__doc__ == '`int`: a very \"important\" member of \\'this\\' instance.'" );
); });
} }
#[pyclass] #[pyclass]
@ -672,14 +666,14 @@ impl MethodWithLifeTime {
#[test] #[test]
fn method_with_lifetime() { fn method_with_lifetime() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let obj = PyCell::new(py, MethodWithLifeTime {}).unwrap();
let obj = PyCell::new(py, MethodWithLifeTime {}).unwrap(); py_run!(
py_run!( py,
py, obj,
obj, "assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]"
"assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]" );
); });
} }
#[pyclass] #[pyclass]
@ -720,35 +714,35 @@ impl MethodWithPyClassArg {
#[test] #[test]
fn method_with_pyclassarg() { fn method_with_pyclassarg() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let obj1 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap();
let obj1 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap(); let obj2 = 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);
let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py); py_run!(py, *d, "obj = obj1.add(obj2); assert obj.value == 20");
py_run!(py, *d, "obj = obj1.add(obj2); assert obj.value == 20"); py_run!(py, *d, "obj = obj1.add_pyref(obj2); assert obj.value == 20");
py_run!(py, *d, "obj = obj1.add_pyref(obj2); assert obj.value == 20"); py_run!(py, *d, "obj = obj1.optional_add(); assert obj.value == 20");
py_run!(py, *d, "obj = obj1.optional_add(); assert obj.value == 20"); py_run!(
py_run!( py,
py, *d,
*d, "obj = obj1.optional_add(obj2); assert obj.value == 20"
"obj = obj1.optional_add(obj2); assert obj.value == 20" );
); py_run!(py, *d, "obj1.inplace_add(obj2); assert obj.value == 20");
py_run!(py, *d, "obj1.inplace_add(obj2); assert obj.value == 20"); py_run!(
py_run!( py,
py, *d,
*d, "obj1.inplace_add_pyref(obj2); assert obj2.value == 30"
"obj1.inplace_add_pyref(obj2); assert obj2.value == 30" );
); py_run!(
py_run!( py,
py, *d,
*d, "obj1.optional_inplace_add(); assert obj2.value == 30"
"obj1.optional_inplace_add(); assert obj2.value == 30" );
); py_run!(
py_run!( py,
py, *d,
*d, "obj1.optional_inplace_add(obj2); assert obj2.value == 40"
"obj1.optional_inplace_add(obj2); assert obj2.value == 40" );
); });
} }
#[pyclass] #[pyclass]
@ -783,23 +777,23 @@ impl CfgStruct {
#[test] #[test]
fn test_cfg_attrs() { fn test_cfg_attrs() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = Py::new(py, CfgStruct {}).unwrap();
let inst = Py::new(py, CfgStruct {}).unwrap();
#[cfg(unix)] #[cfg(unix)]
{ {
py_assert!(py, inst, "inst.unix_method() == 'unix'"); py_assert!(py, inst, "inst.unix_method() == 'unix'");
py_assert!(py, inst, "not hasattr(inst, 'not_unix_method')"); py_assert!(py, inst, "not hasattr(inst, 'not_unix_method')");
} }
#[cfg(not(unix))] #[cfg(not(unix))]
{ {
py_assert!(py, inst, "not hasattr(inst, 'unix_method')"); py_assert!(py, inst, "not hasattr(inst, 'unix_method')");
py_assert!(py, inst, "inst.not_unix_method() == 'not unix'"); py_assert!(py, inst, "inst.not_unix_method() == 'not unix'");
} }
py_assert!(py, inst, "not hasattr(inst, 'never_compiled_method')"); py_assert!(py, inst, "not hasattr(inst, 'never_compiled_method')");
});
} }
#[pyclass] #[pyclass]
@ -825,10 +819,10 @@ impl FromSequence {
#[test] #[test]
fn test_from_sequence() { fn test_from_sequence() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<FromSequence>();
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] #[pyclass]

View file

@ -67,51 +67,50 @@ fn module_with_functions(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
fn test_module_with_functions() { fn test_module_with_functions() {
use pyo3::wrap_pymodule; use pyo3::wrap_pymodule;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = [(
"module_with_functions",
wrap_pymodule!(module_with_functions)(py),
)]
.into_py_dict(py);
let d = [( py_assert!(
"module_with_functions", py,
wrap_pymodule!(module_with_functions)(py), *d,
)] "module_with_functions.__doc__ == 'This module is implemented in Rust.'"
.into_py_dict(py); );
py_assert!(py, *d, "module_with_functions.no_parameters() == 42");
py_assert!( py_assert!(py, *d, "module_with_functions.foo == 'bar'");
py, py_assert!(py, *d, "module_with_functions.AnonClass != None");
*d, py_assert!(py, *d, "module_with_functions.LocatedClass != None");
"module_with_functions.__doc__ == 'This module is implemented in Rust.'" py_assert!(
); py,
py_assert!(py, *d, "module_with_functions.no_parameters() == 42"); *d,
py_assert!(py, *d, "module_with_functions.foo == 'bar'"); "module_with_functions.LocatedClass.__module__ == 'module'"
py_assert!(py, *d, "module_with_functions.AnonClass != None"); );
py_assert!(py, *d, "module_with_functions.LocatedClass != None"); py_assert!(py, *d, "module_with_functions.double(3) == 6");
py_assert!( py_assert!(
py, py,
*d, *d,
"module_with_functions.LocatedClass.__module__ == 'module'" "module_with_functions.double.__doc__ == 'Doubles the given value'"
); );
py_assert!(py, *d, "module_with_functions.double(3) == 6"); py_assert!(py, *d, "module_with_functions.also_double(3) == 6");
py_assert!( py_assert!(
py, py,
*d, *d,
"module_with_functions.double.__doc__ == 'Doubles the given value'" "module_with_functions.also_double.__doc__ == 'Doubles the given value'"
); );
py_assert!(py, *d, "module_with_functions.also_double(3) == 6"); py_assert!(
py_assert!( py,
py, *d,
*d, "module_with_functions.double_value(module_with_functions.ValueClass(1)) == 2"
"module_with_functions.also_double.__doc__ == 'Doubles the given value'" );
); py_assert!(
py_assert!( py,
py, *d,
*d, "module_with_functions.with_module() == 'module_with_functions'"
"module_with_functions.double_value(module_with_functions.ValueClass(1)) == 2" );
); });
py_assert!(
py,
*d,
"module_with_functions.with_module() == 'module_with_functions'"
);
} }
#[pymodule] #[pymodule]
@ -125,39 +124,37 @@ fn some_name(_: Python<'_>, m: &PyModule) -> PyResult<()> {
fn test_module_renaming() { fn test_module_renaming() {
use pyo3::wrap_pymodule; use pyo3::wrap_pymodule;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = [("different_name", wrap_pymodule!(some_name)(py))].into_py_dict(py);
let d = [("different_name", wrap_pymodule!(some_name)(py))].into_py_dict(py); py_run!(py, *d, "assert different_name.__name__ == 'other_name'");
});
py_run!(py, *d, "assert different_name.__name__ == 'other_name'");
} }
#[test] #[test]
fn test_module_from_code() { fn test_module_from_code() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let adder_mod = PyModule::from_code(
py,
"def add(a,b):\n\treturn a+b",
"adder_mod.py",
"adder_mod",
)
.expect("Module code should be loaded");
let adder_mod = PyModule::from_code( let add_func = adder_mod
py, .getattr("add")
"def add(a,b):\n\treturn a+b", .expect("Add function should be in the module")
"adder_mod.py", .to_object(py);
"adder_mod",
)
.expect("Module code should be loaded");
let add_func = adder_mod let ret_value: i32 = add_func
.getattr("add") .call1(py, (1, 2))
.expect("Add function should be in the module") .expect("A value should be returned")
.to_object(py); .extract(py)
.expect("The value should be able to be converted to an i32");
let ret_value: i32 = add_func assert_eq!(ret_value, 3);
.call1(py, (1, 2)) });
.expect("A value should be returned")
.extract(py)
.expect("The value should be able to be converted to an i32");
assert_eq!(ret_value, 3);
} }
#[pyfunction] #[pyfunction]
@ -174,12 +171,11 @@ fn raw_ident_module(_py: Python<'_>, module: &PyModule) -> PyResult<()> {
fn test_raw_idents() { fn test_raw_idents() {
use pyo3::wrap_pymodule; use pyo3::wrap_pymodule;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let module = wrap_pymodule!(raw_ident_module)(py);
let module = wrap_pymodule!(raw_ident_module)(py); py_assert!(py, module, "module.move() == 42");
});
py_assert!(py, module, "module.move() == 42");
} }
#[pyfunction] #[pyfunction]
@ -197,31 +193,30 @@ fn foobar_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
#[test] #[test]
fn test_custom_names() { fn test_custom_names() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let module = pyo3::wrap_pymodule!(foobar_module)(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");
py_assert!(py, module, "not hasattr(module, 'custom_named_fn')"); });
py_assert!(py, module, "module.foobar() == 42");
} }
#[test] #[test]
fn test_module_dict() { fn test_module_dict() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let module = pyo3::wrap_pymodule!(foobar_module)(py);
let module = pyo3::wrap_pymodule!(foobar_module)(py);
py_assert!(py, module, "module.yay == 'me'"); py_assert!(py, module, "module.yay == 'me'");
});
} }
#[test] #[test]
fn test_module_dunder_all() { fn test_module_dunder_all() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let module = pyo3::wrap_pymodule!(foobar_module)(py);
let module = pyo3::wrap_pymodule!(foobar_module)(py);
py_assert!(py, module, "module.__all__ == ['foobar']"); py_assert!(py, module, "module.__all__ == ['foobar']");
});
} }
#[pyfunction] #[pyfunction]
@ -261,25 +256,25 @@ fn supermodule(py: Python<'_>, module: &PyModule) -> PyResult<()> {
fn test_module_nesting() { fn test_module_nesting() {
use pyo3::wrap_pymodule; use pyo3::wrap_pymodule;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let supermodule = wrap_pymodule!(supermodule)(py);
let supermodule = wrap_pymodule!(supermodule)(py);
py_assert!( py_assert!(
py, py,
supermodule, supermodule,
"supermodule.superfunction() == 'Superfunction'" "supermodule.superfunction() == 'Superfunction'"
); );
py_assert!( py_assert!(
py, py,
supermodule, supermodule,
"supermodule.submodule.subfunction() == 'Subfunction'" "supermodule.submodule.subfunction() == 'Subfunction'"
); );
py_assert!( py_assert!(
py, py,
supermodule, supermodule,
"supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'" "supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'"
); );
});
} }
// Test that argument parsing specification works for pyfunctions // Test that argument parsing specification works for pyfunctions
@ -302,15 +297,15 @@ fn vararg_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
#[test] #[test]
fn test_vararg_module() { fn test_vararg_module() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let m = pyo3::wrap_pymodule!(vararg_module)(py);
let m = pyo3::wrap_pymodule!(vararg_module)(py);
py_assert!(py, m, "m.ext_vararg_fn() == [5, ()]"); py_assert!(py, m, "m.ext_vararg_fn() == [5, ()]");
py_assert!(py, m, "m.ext_vararg_fn(1, 2) == [1, (2,)]"); py_assert!(py, m, "m.ext_vararg_fn(1, 2) == [1, (2,)]");
py_assert!(py, m, "m.int_vararg_fn() == [5, ()]"); py_assert!(py, m, "m.int_vararg_fn() == [5, ()]");
py_assert!(py, m, "m.int_vararg_fn(1, 2) == [1, (2,)]"); py_assert!(py, m, "m.int_vararg_fn(1, 2) == [1, (2,)]");
});
} }
#[test] #[test]
@ -397,36 +392,36 @@ fn module_with_functions_with_module(_py: Python<'_>, m: &PyModule) -> PyResult<
#[test] #[test]
fn test_module_functions_with_module() { fn test_module_functions_with_module() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let m = pyo3::wrap_pymodule!(module_with_functions_with_module)(py);
let m = pyo3::wrap_pymodule!(module_with_functions_with_module)(py); py_assert!(
py_assert!( py,
py, m,
m, "m.pyfunction_with_module() == 'module_with_functions_with_module'"
"m.pyfunction_with_module() == 'module_with_functions_with_module'" );
); py_assert!(
py_assert!( py,
py, m,
m, "m.pyfunction_with_module_and_py() == 'module_with_functions_with_module'"
"m.pyfunction_with_module_and_py() == 'module_with_functions_with_module'" );
); py_assert!(
py_assert!( py,
py, m,
m, "m.pyfunction_with_module_and_default_arg() \
"m.pyfunction_with_module_and_default_arg() \
== ('module_with_functions_with_module', 'foo')" == ('module_with_functions_with_module', 'foo')"
); );
py_assert!( py_assert!(
py, py,
m, m,
"m.pyfunction_with_module_and_args_kwargs(1, x=1, y=2) \ "m.pyfunction_with_module_and_args_kwargs(1, x=1, y=2) \
== ('module_with_functions_with_module', 1, 2)" == ('module_with_functions_with_module', 1, 2)"
); );
py_assert!( py_assert!(
py, py,
m, m,
"m.pyfunction_with_pass_module_in_attribute() == 'module_with_functions_with_module'" "m.pyfunction_with_pass_module_in_attribute() == 'module_with_functions_with_module'"
); );
});
} }
#[test] #[test]

View file

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

View file

@ -17,14 +17,14 @@ fn optional_bool(arg: Option<bool>) -> String {
#[test] #[test]
fn test_optional_bool() { fn test_optional_bool() {
// Regression test for issue #932 // Regression test for issue #932
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let f = wrap_pyfunction!(optional_bool)(py).unwrap();
let f = wrap_pyfunction!(optional_bool)(py).unwrap();
py_assert!(py, f, "f() == 'Some(true)'"); py_assert!(py, f, "f() == 'Some(true)'");
py_assert!(py, f, "f(True) == 'Some(true)'"); py_assert!(py, f, "f(True) == 'Some(true)'");
py_assert!(py, f, "f(False) == 'Some(false)'"); py_assert!(py, f, "f(False) == 'Some(false)'");
py_assert!(py, f, "f(None) == 'None'"); py_assert!(py, f, "f(None) == 'None'");
});
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
@ -41,33 +41,33 @@ fn buffer_inplace_add(py: Python<'_>, x: PyBuffer<i32>, y: PyBuffer<i32>) {
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
#[test] #[test]
fn test_buffer_add() { fn test_buffer_add() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let f = wrap_pyfunction!(buffer_inplace_add)(py).unwrap();
let f = wrap_pyfunction!(buffer_inplace_add)(py).unwrap();
py_expect_exception!( py_expect_exception!(
py, py,
f, f,
r#" r#"
import array import array
a = array.array("i", [0, 1, 2, 3]) a = array.array("i", [0, 1, 2, 3])
b = array.array("I", [0, 1, 2, 3]) b = array.array("I", [0, 1, 2, 3])
f(a, b) f(a, b)
"#, "#,
PyBufferError PyBufferError
); );
pyo3::py_run!( pyo3::py_run!(
py, py,
f, f,
r#" r#"
import array import array
a = array.array("i", [0, 1, 2, 3]) a = array.array("i", [0, 1, 2, 3])
b = array.array("i", [2, 3, 4, 5]) b = array.array("i", [2, 3, 4, 5])
f(a, b) f(a, b)
assert a, array.array("i", [2, 4, 6, 8]) assert a, array.array("i", [2, 4, 6, 8])
"# "#
); );
});
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
@ -83,33 +83,33 @@ fn function_with_pycfunction_arg(fun: &PyCFunction) -> PyResult<&PyAny> {
#[test] #[test]
fn test_functions_with_function_args() { fn test_functions_with_function_args() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let py_cfunc_arg = wrap_pyfunction!(function_with_pycfunction_arg)(py).unwrap();
let py_cfunc_arg = wrap_pyfunction!(function_with_pycfunction_arg)(py).unwrap(); let bool_to_string = wrap_pyfunction!(optional_bool)(py).unwrap();
let bool_to_string = wrap_pyfunction!(optional_bool)(py).unwrap();
pyo3::py_run!(
py,
py_cfunc_arg
bool_to_string,
r#"
assert py_cfunc_arg(bool_to_string) == "Some(true)"
"#
);
#[cfg(not(Py_LIMITED_API))]
{
let py_func_arg = wrap_pyfunction!(function_with_pyfunction_arg)(py).unwrap();
pyo3::py_run!( pyo3::py_run!(
py, py,
py_func_arg, py_cfunc_arg
bool_to_string,
r#" r#"
assert py_cfunc_arg(bool_to_string) == "Some(true)"
"#
);
#[cfg(not(Py_LIMITED_API))]
{
let py_func_arg = wrap_pyfunction!(function_with_pyfunction_arg)(py).unwrap();
pyo3::py_run!(
py,
py_func_arg,
r#"
def foo(): return "bar" def foo(): return "bar"
assert py_func_arg(foo) == "bar" assert py_func_arg(foo) == "bar"
"# "#
); );
} }
});
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
@ -131,38 +131,36 @@ fn function_with_custom_conversion(
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
#[test] #[test]
fn test_function_with_custom_conversion() { fn test_function_with_custom_conversion() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();
let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap(); pyo3::py_run!(
py,
pyo3::py_run!( custom_conv_func,
py, r#"
custom_conv_func,
r#"
import datetime import datetime
dt = datetime.datetime.fromtimestamp(1612040400) dt = datetime.datetime.fromtimestamp(1612040400)
assert custom_conv_func(dt) == 1612040400 assert custom_conv_func(dt) == 1612040400
"# "#
) )
});
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
#[test] #[test]
fn test_function_with_custom_conversion_error() { fn test_function_with_custom_conversion_error() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();
let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap(); py_expect_exception!(
py,
py_expect_exception!( custom_conv_func,
py, "custom_conv_func(['a'])",
custom_conv_func, PyTypeError,
"custom_conv_func(['a'])", "argument 'timestamp': 'list' object cannot be converted to 'PyDateTime'"
PyTypeError, );
"argument 'timestamp': 'list' object cannot be converted to 'PyDateTime'" });
);
} }
#[pyclass] #[pyclass]
@ -188,76 +186,75 @@ fn conversion_error(
#[test] #[test]
fn test_conversion_error() { fn test_conversion_error() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let conversion_error = wrap_pyfunction!(conversion_error)(py).unwrap();
py_expect_exception!(
let conversion_error = wrap_pyfunction!(conversion_error)(py).unwrap(); py,
py_expect_exception!( conversion_error,
py, "conversion_error(None, None, None, None, None)",
conversion_error, PyTypeError,
"conversion_error(None, None, None, None, None)", "argument 'str_arg': 'NoneType' object cannot be converted to 'PyString'"
PyTypeError, );
"argument 'str_arg': 'NoneType' object cannot be converted to 'PyString'" py_expect_exception!(
); py,
py_expect_exception!( conversion_error,
py, "conversion_error(100, None, None, None, None)",
conversion_error, PyTypeError,
"conversion_error(100, None, None, None, None)", "argument 'str_arg': 'int' object cannot be converted to 'PyString'"
PyTypeError, );
"argument 'str_arg': 'int' object cannot be converted to 'PyString'" py_expect_exception!(
); py,
py_expect_exception!( conversion_error,
py, "conversion_error('string1', 'string2', None, None, None)",
conversion_error, PyTypeError,
"conversion_error('string1', 'string2', None, None, None)", "argument 'int_arg': 'str' object cannot be interpreted as an integer"
PyTypeError, );
"argument 'int_arg': 'str' object cannot be interpreted as an integer" py_expect_exception!(
); py,
py_expect_exception!( conversion_error,
py, "conversion_error('string1', -100, 'string2', None, None)",
conversion_error, PyTypeError,
"conversion_error('string1', -100, 'string2', None, None)", "argument 'tuple_arg': 'str' object cannot be converted to 'PyTuple'"
PyTypeError, );
"argument 'tuple_arg': 'str' object cannot be converted to 'PyTuple'" py_expect_exception!(
); py,
py_expect_exception!( conversion_error,
py, "conversion_error('string1', -100, ('string2', 10.), 'string3', None)",
conversion_error, PyTypeError,
"conversion_error('string1', -100, ('string2', 10.), 'string3', None)", "argument 'option_arg': 'str' object cannot be interpreted as an integer"
PyTypeError, );
"argument 'option_arg': 'str' object cannot be interpreted as an integer" let exception = py_expect_exception!(
); py,
let exception = py_expect_exception!( conversion_error,
py, "
conversion_error,
"
class ValueClass: class ValueClass:
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
conversion_error('string1', -100, ('string2', 10.), None, ValueClass(\"no_expected_type\"))", conversion_error('string1', -100, ('string2', 10.), None, ValueClass(\"no_expected_type\"))",
PyTypeError PyTypeError
); );
assert_eq!( assert_eq!(
extract_traceback(py, exception), extract_traceback(py, exception),
"TypeError: argument 'struct_arg': failed to \ "TypeError: argument 'struct_arg': failed to \
extract field ValueClass.value: TypeError: 'str' object cannot be interpreted as an integer" extract field ValueClass.value: TypeError: 'str' object cannot be interpreted as an integer"
); );
let exception = py_expect_exception!( let exception = py_expect_exception!(
py, py,
conversion_error, conversion_error,
" "
class ValueClass: class ValueClass:
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
conversion_error('string1', -100, ('string2', 10.), None, ValueClass(-5))", conversion_error('string1', -100, ('string2', 10.), None, ValueClass(-5))",
PyTypeError PyTypeError
); );
assert_eq!( assert_eq!(
extract_traceback(py, exception), extract_traceback(py, exception),
"TypeError: argument 'struct_arg': failed to \ "TypeError: argument 'struct_arg': failed to \
extract field ValueClass.value: OverflowError: can't convert negative int to unsigned" extract field ValueClass.value: OverflowError: can't convert negative int to unsigned"
); );
});
} }
/// Helper function that concatenates the error message from /// Helper function that concatenates the error message from
@ -277,30 +274,29 @@ fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String {
fn test_pycfunction_new() { fn test_pycfunction_new() {
use pyo3::ffi; use pyo3::ffi;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); unsafe extern "C" fn c_fn(
_self: *mut ffi::PyObject,
_args: *mut ffi::PyObject,
) -> *mut ffi::PyObject {
ffi::PyLong_FromLong(4200)
}
unsafe extern "C" fn c_fn( let py_fn = PyCFunction::new(
_self: *mut ffi::PyObject, c_fn,
_args: *mut ffi::PyObject, "py_fn",
) -> *mut ffi::PyObject { "py_fn for test (this is the docstring)",
ffi::PyLong_FromLong(4200) py.into(),
} )
.unwrap();
let py_fn = PyCFunction::new( py_assert!(py, py_fn, "py_fn() == 4200");
c_fn, py_assert!(
"py_fn", py,
"py_fn for test (this is the docstring)", py_fn,
py.into(), "py_fn.__doc__ == 'py_fn for test (this is the docstring)'"
) );
.unwrap(); });
py_assert!(py, py_fn, "py_fn() == 4200");
py_assert!(
py,
py_fn,
"py_fn.__doc__ == 'py_fn for test (this is the docstring)'"
);
} }
#[test] #[test]
@ -310,103 +306,107 @@ fn test_pycfunction_new_with_keywords() {
use std::os::raw::{c_char, c_long}; use std::os::raw::{c_char, c_long};
use std::ptr; use std::ptr;
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); unsafe extern "C" fn c_fn(
_self: *mut ffi::PyObject,
args: *mut ffi::PyObject,
kwds: *mut ffi::PyObject,
) -> *mut ffi::PyObject {
let mut foo: c_long = 0;
let mut bar: c_long = 0;
let foo_ptr: *mut c_long = &mut foo;
let bar_ptr: *mut c_long = &mut bar;
unsafe extern "C" fn c_fn( let foo_name = CString::new("foo").unwrap();
_self: *mut ffi::PyObject, let foo_name_raw: *mut c_char = foo_name.into_raw();
args: *mut ffi::PyObject, let kw_bar_name = CString::new("kw_bar").unwrap();
kwds: *mut ffi::PyObject, let kw_bar_name_raw: *mut c_char = kw_bar_name.into_raw();
) -> *mut ffi::PyObject {
let mut foo: c_long = 0;
let mut bar: c_long = 0;
let foo_ptr: *mut c_long = &mut foo;
let bar_ptr: *mut c_long = &mut bar;
let foo_name = CString::new("foo").unwrap(); let mut arglist = vec![foo_name_raw, kw_bar_name_raw, ptr::null_mut()];
let foo_name_raw: *mut c_char = foo_name.into_raw(); let arglist_ptr: *mut *mut c_char = arglist.as_mut_ptr();
let kw_bar_name = CString::new("kw_bar").unwrap();
let kw_bar_name_raw: *mut c_char = kw_bar_name.into_raw();
let mut arglist = vec![foo_name_raw, kw_bar_name_raw, ptr::null_mut()]; let arg_pattern: *const c_char = CString::new("l|l").unwrap().into_raw();
let arglist_ptr: *mut *mut c_char = arglist.as_mut_ptr();
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)
}
ffi::PyLong_FromLong(foo * bar) let py_fn = PyCFunction::new_with_keywords(
} c_fn,
"py_fn",
"py_fn for test (this is the docstring)",
py.into(),
)
.unwrap();
let py_fn = PyCFunction::new_with_keywords( py_assert!(py, py_fn, "py_fn(42, kw_bar=100) == 4200");
c_fn, py_assert!(py, py_fn, "py_fn(foo=42, kw_bar=100) == 4200");
"py_fn", py_assert!(
"py_fn for test (this is the docstring)", py,
py.into(), py_fn,
) "py_fn.__doc__ == 'py_fn for test (this is the docstring)'"
.unwrap(); );
});
py_assert!(py, py_fn, "py_fn(42, kw_bar=100) == 4200");
py_assert!(py, py_fn, "py_fn(foo=42, kw_bar=100) == 4200");
py_assert!(
py,
py_fn,
"py_fn.__doc__ == 'py_fn for test (this is the docstring)'"
);
} }
#[test] #[test]
fn test_closure() { fn test_closure() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let f = |args: &types::PyTuple, _kwargs: Option<&types::PyDict>| -> PyResult<_> {
Python::with_gil(|py| {
let f = |args: &types::PyTuple, _kwargs: Option<&types::PyDict>| -> PyResult<_> { let res: Vec<_> = args
let gil = Python::acquire_gil(); .iter()
let py = gil.python(); .map(|elem| {
let res: Vec<_> = args if let Ok(i) = elem.extract::<i64>() {
.iter() (i + 1).into_py(py)
.map(|elem| { } else if let Ok(f) = elem.extract::<f64>() {
if let Ok(i) = elem.extract::<i64>() { (2. * f).into_py(py)
(i + 1).into_py(py) } else if let Ok(mut s) = elem.extract::<String>() {
} else if let Ok(f) = elem.extract::<f64>() { s.push_str("-py");
(2. * f).into_py(py) s.into_py(py)
} else if let Ok(mut s) = elem.extract::<String>() { } else {
s.push_str("-py"); panic!("unexpected argument type for {:?}", elem)
s.into_py(py) }
} else { })
panic!("unexpected argument type for {:?}", elem) .collect();
} Ok(res)
}) })
.collect(); };
Ok(res) let closure_py = PyCFunction::new_closure(f, py).unwrap();
};
let closure_py = PyCFunction::new_closure(f, py).unwrap();
py_assert!(py, closure_py, "closure_py(42) == [43]"); py_assert!(py, closure_py, "closure_py(42) == [43]");
py_assert!( py_assert!(
py, py,
closure_py, closure_py,
"closure_py(42, 3.14, 'foo') == [43, 6.28, 'foo-py']" "closure_py(42, 3.14, 'foo') == [43, 6.28, 'foo-py']"
); );
});
} }
#[test] #[test]
fn test_closure_counter() { fn test_closure_counter() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let counter = std::cell::RefCell::new(0);
let counter_fn =
move |_args: &types::PyTuple, _kwargs: Option<&types::PyDict>| -> PyResult<i32> {
let mut counter = counter.borrow_mut();
*counter += 1;
Ok(*counter)
};
let counter_py = PyCFunction::new_closure(counter_fn, py).unwrap();
let counter = std::cell::RefCell::new(0); py_assert!(py, counter_py, "counter_py() == 1");
let counter_fn = py_assert!(py, counter_py, "counter_py() == 2");
move |_args: &types::PyTuple, _kwargs: Option<&types::PyDict>| -> PyResult<i32> { py_assert!(py, counter_py, "counter_py() == 3");
let mut counter = counter.borrow_mut(); });
*counter += 1;
Ok(*counter)
};
let counter_py = PyCFunction::new_closure(counter_fn, py).unwrap();
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] #[test]

View file

@ -29,24 +29,23 @@ impl PyMappingProtocol for Len {
#[test] #[test]
fn len() { fn len() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = Py::new(py, Len { l: 10 }).unwrap();
py_assert!(py, inst, "len(inst) == 10");
unsafe {
assert_eq!(ffi::PyObject_Size(inst.as_ptr()), 10);
assert_eq!(ffi::PyMapping_Size(inst.as_ptr()), 10);
}
let inst = Py::new(py, Len { l: 10 }).unwrap(); let inst = Py::new(
py_assert!(py, inst, "len(inst) == 10"); py,
unsafe { Len {
assert_eq!(ffi::PyObject_Size(inst.as_ptr()), 10); l: (isize::MAX as usize) + 1,
assert_eq!(ffi::PyMapping_Size(inst.as_ptr()), 10); },
} )
.unwrap();
let inst = Py::new( py_expect_exception!(py, inst, "len(inst)", PyOverflowError);
py, });
Len {
l: (isize::MAX as usize) + 1,
},
)
.unwrap();
py_expect_exception!(py, inst, "len(inst)", PyOverflowError);
} }
#[pyclass] #[pyclass]
@ -67,18 +66,17 @@ impl PyIterProtocol for Iterator {
#[test] #[test]
fn iterator() { fn iterator() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = Py::new(
py,
let inst = Py::new( Iterator {
py, iter: Box::new(5..8),
Iterator { },
iter: Box::new(5..8), )
}, .unwrap();
) py_assert!(py, inst, "iter(inst) is inst");
.unwrap(); py_assert!(py, inst, "list(inst) == [5, 6, 7]");
py_assert!(py, inst, "iter(inst) is inst"); });
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
} }
#[pyclass] #[pyclass]
@ -97,12 +95,11 @@ impl PyObjectProtocol for StringMethods {
#[test] #[test]
fn string_methods() { fn string_methods() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let obj = Py::new(py, StringMethods {}).unwrap();
py_assert!(py, obj, "str(obj) == 'str'");
let obj = Py::new(py, StringMethods {}).unwrap(); py_assert!(py, obj, "repr(obj) == 'repr'");
py_assert!(py, obj, "str(obj) == 'str'"); });
py_assert!(py, obj, "repr(obj) == 'repr'");
} }
#[pyclass] #[pyclass]
@ -122,19 +119,18 @@ impl PyObjectProtocol for Comparisons {
#[test] #[test]
fn comparisons() { fn comparisons() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); 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();
let minus_one = Py::new(py, Comparisons { val: -1 }).unwrap();
py_assert!(py, one, "hash(one) == 1");
py_assert!(py, ten, "hash(ten) == 10");
py_assert!(py, minus_one, "hash(minus_one) == -2");
let zero = Py::new(py, Comparisons { val: 0 }).unwrap(); py_assert!(py, one, "bool(one) is True");
let one = Py::new(py, Comparisons { val: 1 }).unwrap(); py_assert!(py, zero, "not zero");
let ten = Py::new(py, Comparisons { val: 10 }).unwrap(); });
let minus_one = Py::new(py, Comparisons { val: -1 }).unwrap();
py_assert!(py, one, "hash(one) == 1");
py_assert!(py, ten, "hash(ten) == 10");
py_assert!(py, minus_one, "hash(minus_one) == -2");
py_assert!(py, one, "bool(one) is True");
py_assert!(py, zero, "not zero");
} }
#[pyclass] #[pyclass]
@ -181,21 +177,20 @@ impl PySequenceProtocol for Sequence {
#[test] #[test]
fn sequence() { fn sequence() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = Py::new(py, Sequence::default()).unwrap();
py_assert!(py, c, "list(c) == ['A', 'B', 'C', 'D', 'E', 'F', 'G']");
let c = Py::new(py, Sequence::default()).unwrap(); py_assert!(py, c, "c[-1] == 'G'");
py_assert!(py, c, "list(c) == ['A', 'B', 'C', 'D', 'E', 'F', 'G']"); py_run!(
py_assert!(py, c, "c[-1] == 'G'"); py,
py_run!( c,
py, r#"
c,
r#"
c[0] = 'H' c[0] = 'H'
assert c[0] == 'H' assert c[0] == 'H'
"# "#
); );
py_expect_exception!(py, c, "c['abc']", PyTypeError); py_expect_exception!(py, c, "c['abc']", PyTypeError);
});
} }
#[pyclass] #[pyclass]
@ -215,17 +210,16 @@ impl PyMappingProtocol for SetItem {
#[test] #[test]
fn setitem() { fn setitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, SetItem { key: 0, val: 0 }).unwrap();
py_run!(py, c, "c[1] = 2");
let c = PyCell::new(py, SetItem { key: 0, val: 0 }).unwrap(); {
py_run!(py, c, "c[1] = 2"); let c = c.borrow();
{ assert_eq!(c.key, 1);
let c = c.borrow(); assert_eq!(c.val, 2);
assert_eq!(c.key, 1); }
assert_eq!(c.val, 2); py_expect_exception!(py, c, "del c[1]", PyNotImplementedError);
} });
py_expect_exception!(py, c, "del c[1]", PyNotImplementedError);
} }
#[pyclass] #[pyclass]
@ -242,16 +236,15 @@ impl PyMappingProtocol<'a> for DelItem {
#[test] #[test]
fn delitem() { fn delitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, DelItem { key: 0 }).unwrap();
py_run!(py, c, "del c[1]");
let c = PyCell::new(py, DelItem { key: 0 }).unwrap(); {
py_run!(py, c, "del c[1]"); let c = c.borrow();
{ assert_eq!(c.key, 1);
let c = c.borrow(); }
assert_eq!(c.key, 1); py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError);
} });
py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError);
} }
#[pyclass] #[pyclass]
@ -272,18 +265,17 @@ impl PyMappingProtocol for SetDelItem {
#[test] #[test]
fn setdelitem() { fn setdelitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = PyCell::new(py, SetDelItem { val: None }).unwrap();
py_run!(py, c, "c[1] = 2");
let c = PyCell::new(py, SetDelItem { val: None }).unwrap(); {
py_run!(py, c, "c[1] = 2"); let c = c.borrow();
{ assert_eq!(c.val, Some(2));
}
py_run!(py, c, "del c[1]");
let c = c.borrow(); let c = c.borrow();
assert_eq!(c.val, Some(2)); assert_eq!(c.val, None);
} });
py_run!(py, c, "del c[1]");
let c = c.borrow();
assert_eq!(c.val, None);
} }
#[pyclass] #[pyclass]
@ -298,26 +290,24 @@ impl PySequenceProtocol for Contains {
#[test] #[test]
fn contains() { fn contains() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let c = Py::new(py, Contains {}).unwrap();
py_run!(py, c, "assert 1 in c");
let c = Py::new(py, Contains {}).unwrap(); py_run!(py, c, "assert -1 not in c");
py_run!(py, c, "assert 1 in c"); py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError);
py_run!(py, c, "assert -1 not in c"); });
py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError);
} }
#[test] #[test]
fn test_basics() { fn test_basics() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let v = PySlice::new(py, 1, 10, 2);
let indices = v.indices(100).unwrap();
let v = PySlice::new(py, 1, 10, 2); assert_eq!(1, indices.start);
let indices = v.indices(100).unwrap(); assert_eq!(10, indices.stop);
assert_eq!(1, indices.start); assert_eq!(2, indices.step);
assert_eq!(10, indices.stop); assert_eq!(5, indices.slicelength);
assert_eq!(2, indices.step); });
assert_eq!(5, indices.slicelength);
} }
#[pyclass] #[pyclass]
@ -342,13 +332,12 @@ impl<'p> PyMappingProtocol<'p> for Test {
#[test] #[test]
fn test_cls_impl() { fn test_cls_impl() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let ob = Py::new(py, Test {}).unwrap();
let ob = Py::new(py, Test {}).unwrap(); py_assert!(py, ob, "ob[1] == 'int'");
py_assert!(py, ob, "ob[100:200:1] == 'slice'");
py_assert!(py, ob, "ob[1] == 'int'"); });
py_assert!(py, ob, "ob[100:200:1] == 'slice'");
} }
#[pyclass] #[pyclass]
@ -366,11 +355,11 @@ impl PyObjectProtocol for ClassWithGetAttr {
#[test] #[test]
fn getattr_doesnt_override_member() { fn getattr_doesnt_override_member() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let inst = PyCell::new(py, ClassWithGetAttr { data: 4 }).unwrap();
let inst = PyCell::new(py, ClassWithGetAttr { data: 4 }).unwrap(); py_assert!(py, inst, "inst.data == 4");
py_assert!(py, inst, "inst.data == 4"); py_assert!(py, inst, "inst.a == 8");
py_assert!(py, inst, "inst.a == 8"); });
} }
/// Wraps a Python future and yield it once. /// Wraps a Python future and yield it once.
@ -415,11 +404,10 @@ impl PyIterProtocol for OnceFuture {
#[test] #[test]
fn test_await() { fn test_await() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let once = py.get_type::<OnceFuture>();
let once = py.get_type::<OnceFuture>(); let source = pyo3::indoc::indoc!(
let source = pyo3::indoc::indoc!( r#"
r#"
import asyncio import asyncio
import sys import sys
@ -435,12 +423,13 @@ asyncio.set_event_loop(loop)
assert loop.run_until_complete(main()) is None assert loop.run_until_complete(main()) is None
loop.close() loop.close()
"# "#
); );
let globals = PyModule::import(py, "__main__").unwrap().dict(); let globals = PyModule::import(py, "__main__").unwrap().dict();
globals.set_item("Once", once).unwrap(); globals.set_item("Once", once).unwrap();
py.run(source, Some(globals), None) py.run(source, Some(globals), None)
.map_err(|e| e.print(py)) .map_err(|e| e.print(py))
.unwrap(); .unwrap();
});
} }
/// Increment the count when `__get__` is called. /// Increment the count when `__get__` is called.
@ -475,11 +464,10 @@ impl PyDescrProtocol for DescrCounter {
#[test] #[test]
fn descr_getset() { fn descr_getset() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let counter = py.get_type::<DescrCounter>();
let counter = py.get_type::<DescrCounter>(); let source = pyo3::indoc::indoc!(
let source = pyo3::indoc::indoc!( r#"
r#"
class Class: class Class:
counter = Counter() counter = Counter()
c = Class() c = Class()
@ -488,10 +476,11 @@ assert c.counter.count == 2
c.counter = Counter() c.counter = Counter()
assert c.counter.count == 3 assert c.counter.count == 3
"# "#
); );
let globals = PyModule::import(py, "__main__").unwrap().dict(); let globals = PyModule::import(py, "__main__").unwrap().dict();
globals.set_item("Counter", counter).unwrap(); globals.set_item("Counter", counter).unwrap();
py.run(source, Some(globals), None) py.run(source, Some(globals), None)
.map_err(|e| e.print(py)) .map_err(|e| e.print(py))
.unwrap(); .unwrap();
});
} }

View file

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

View file

@ -113,141 +113,135 @@ fn seq_dict(py: Python<'_>) -> &pyo3::types::PyDict {
#[test] #[test]
fn test_getitem() { fn test_getitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py);
py_assert!(py, *d, "s[0] == 1"); py_assert!(py, *d, "s[0] == 1");
py_assert!(py, *d, "s[1] == 2"); py_assert!(py, *d, "s[1] == 2");
py_assert!(py, *d, "s[2] == 3"); 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);
py_expect_exception!(py, *d, "print(s[4])", PyIndexError); py_expect_exception!(py, *d, "print(s[4])", PyIndexError);
});
} }
#[test] #[test]
fn test_setitem() { fn test_setitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py);
py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]"); py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]");
py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError); py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError);
});
} }
#[test] #[test]
fn test_delitem() { fn test_delitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py); py_run!(
py,
py_run!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]"
*d, );
"s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]" py_run!(
); py,
py_run!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]"
*d, );
"s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]" py_run!(
); py,
py_run!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]"
*d, );
"s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]" py_run!(
); py,
py_run!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]"
*d, );
"s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]" py_expect_exception!(
); py,
py_expect_exception!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))",
*d, PyIndexError
"s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))", );
PyIndexError py_expect_exception!(
); py,
py_expect_exception!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[4]",
*d, PyIndexError
"s = ByteSequence([1, 2, 3]); del s[4]", );
PyIndexError });
);
} }
#[test] #[test]
fn test_contains() { fn test_contains() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py); py_assert!(py, *d, "1 in s");
py_assert!(py, *d, "2 in s");
py_assert!(py, *d, "1 in s"); py_assert!(py, *d, "3 in s");
py_assert!(py, *d, "2 in s"); py_assert!(py, *d, "4 not in s");
py_assert!(py, *d, "3 in s"); py_assert!(py, *d, "'hello' not in s");
py_assert!(py, *d, "4 not in s"); });
py_assert!(py, *d, "'hello' not in s");
} }
#[test] #[test]
fn test_concat() { fn test_concat() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py); py_run!(
py_run!(
py, py,
*d, *d,
"s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]" "s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]"
); );
py_expect_exception!( py_expect_exception!(
py, py,
*d, *d,
"s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2", "s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2",
PyTypeError PyTypeError
); );
});
} }
#[test] #[test]
fn test_inplace_concat() { fn test_inplace_concat() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py); py_run!(
py,
py_run!( *d,
py, "s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]"
*d, );
"s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]" py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
); });
py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
} }
#[test] #[test]
fn test_repeat() { fn test_repeat() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(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);
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] #[test]
fn test_inplace_repeat() { fn test_inplace_repeat() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py); py_run!(
py,
py_run!( *d,
py, "s = ByteSequence([1, 2]); s *= 3; assert list(s) == [1, 2, 1, 2, 1, 2]"
*d, );
"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);
); });
py_expect_exception!(py, *d, "s = ByteSequence([1, 2]); s *= -1", PyValueError);
} }
// Check that #[pyo3(get, set)] works correctly for Vec<PyObject> // Check that #[pyo3(get, set)] works correctly for Vec<PyObject>
@ -260,31 +254,29 @@ struct GenericList {
#[test] #[test]
fn test_generic_list_get() { fn test_generic_list_get() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let list: PyObject = GenericList {
items: [1, 2, 3].iter().map(|i| i.to_object(py)).collect(),
}
.into_py(py);
let list: PyObject = GenericList { py_assert!(py, list, "list.items == [1, 2, 3]");
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] #[test]
fn test_generic_list_set() { fn test_generic_list_set() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let list = PyCell::new(py, GenericList { items: vec![] }).unwrap();
let list = PyCell::new(py, GenericList { items: vec![] }).unwrap(); py_run!(py, list, "list.items = [1, 2, 3]");
assert!(list
py_run!(py, list, "list.items = [1, 2, 3]"); .borrow()
assert!(list .items
.borrow() .iter()
.items .zip(&[1u32, 2, 3])
.iter() .all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
.zip(&[1u32, 2, 3]) });
.all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
} }
#[pyclass] #[pyclass]
@ -306,18 +298,17 @@ impl OptionList {
#[test] #[test]
fn test_option_list_get() { fn test_option_list_get() {
// Regression test for #798 // Regression test for #798
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let list = PyCell::new(
py,
OptionList {
items: vec![Some(1), None],
},
)
.unwrap();
let list = PyCell::new( py_assert!(py, list, "list[0] == 1");
py, py_assert!(py, list, "list[1] == None");
OptionList { py_expect_exception!(py, list, "list[2]", PyIndexError);
items: vec![Some(1), None], });
},
)
.unwrap();
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,141 +97,135 @@ fn seq_dict(py: Python<'_>) -> &pyo3::types::PyDict {
#[test] #[test]
fn test_getitem() { fn test_getitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py);
py_assert!(py, *d, "s[0] == 1"); py_assert!(py, *d, "s[0] == 1");
py_assert!(py, *d, "s[1] == 2"); py_assert!(py, *d, "s[1] == 2");
py_assert!(py, *d, "s[2] == 3"); 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);
py_expect_exception!(py, *d, "print(s[4])", PyIndexError); py_expect_exception!(py, *d, "print(s[4])", PyIndexError);
});
} }
#[test] #[test]
fn test_setitem() { fn test_setitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py);
py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]"); py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]");
py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError); py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError);
});
} }
#[test] #[test]
fn test_delitem() { fn test_delitem() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py); py_run!(
py,
py_run!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]"
*d, );
"s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]" py_run!(
); py,
py_run!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]"
*d, );
"s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]" py_run!(
); py,
py_run!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]"
*d, );
"s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]" py_run!(
); py,
py_run!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]"
*d, );
"s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]" py_expect_exception!(
); py,
py_expect_exception!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))",
*d, PyIndexError
"s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))", );
PyIndexError py_expect_exception!(
); py,
py_expect_exception!( *d,
py, "s = ByteSequence([1, 2, 3]); del s[4]",
*d, PyIndexError
"s = ByteSequence([1, 2, 3]); del s[4]", );
PyIndexError });
);
} }
#[test] #[test]
fn test_contains() { fn test_contains() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py); py_assert!(py, *d, "1 in s");
py_assert!(py, *d, "2 in s");
py_assert!(py, *d, "1 in s"); py_assert!(py, *d, "3 in s");
py_assert!(py, *d, "2 in s"); py_assert!(py, *d, "4 not in s");
py_assert!(py, *d, "3 in s"); py_assert!(py, *d, "'hello' not in s");
py_assert!(py, *d, "4 not in s"); });
py_assert!(py, *d, "'hello' not in s");
} }
#[test] #[test]
fn test_concat() { fn test_concat() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py); py_run!(
py_run!(
py, py,
*d, *d,
"s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]" "s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]"
); );
py_expect_exception!( py_expect_exception!(
py, py,
*d, *d,
"s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2", "s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2",
PyTypeError PyTypeError
); );
});
} }
#[test] #[test]
fn test_inplace_concat() { fn test_inplace_concat() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(py);
let d = seq_dict(py); py_run!(
py,
py_run!( *d,
py, "s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]"
*d, );
"s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]" py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
); });
py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
} }
#[test] #[test]
fn test_repeat() { fn test_repeat() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = seq_dict(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);
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] #[test]
fn test_inplace_repeat() { fn test_inplace_repeat() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py); py_run!(
py,
py_run!( *d,
py, "s = ByteSequence([1, 2]); s *= 3; assert list(s) == [1, 2, 1, 2, 1, 2]"
*d, );
"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);
); });
py_expect_exception!(py, *d, "s = ByteSequence([1, 2]); s *= -1", PyValueError);
} }
// Check that #[pyo3(get, set)] works correctly for Vec<PyObject> // Check that #[pyo3(get, set)] works correctly for Vec<PyObject>
@ -244,31 +238,29 @@ struct GenericList {
#[test] #[test]
fn test_generic_list_get() { fn test_generic_list_get() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let list: PyObject = GenericList {
items: [1, 2, 3].iter().map(|i| i.to_object(py)).collect(),
}
.into_py(py);
let list: PyObject = GenericList { py_assert!(py, list, "list.items == [1, 2, 3]");
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] #[test]
fn test_generic_list_set() { fn test_generic_list_set() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let list = PyCell::new(py, GenericList { items: vec![] }).unwrap();
let list = PyCell::new(py, GenericList { items: vec![] }).unwrap(); py_run!(py, list, "list.items = [1, 2, 3]");
assert!(list
py_run!(py, list, "list.items = [1, 2, 3]"); .borrow()
assert!(list .items
.borrow() .iter()
.items .zip(&[1u32, 2, 3])
.iter() .all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
.zip(&[1u32, 2, 3]) });
.all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
} }
#[pyclass] #[pyclass]
@ -290,18 +282,17 @@ impl PySequenceProtocol for OptionList {
#[test] #[test]
fn test_option_list_get() { fn test_option_list_get() {
// Regression test for #798 // Regression test for #798
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let list = PyCell::new(
py,
OptionList {
items: vec![Some(1), None],
},
)
.unwrap();
let list = PyCell::new( py_assert!(py, list, "list[0] == 1");
py, py_assert!(py, list, "list[1] == None");
OptionList { py_expect_exception!(py, list, "list[2]", PyIndexError);
items: vec![Some(1), None], });
},
)
.unwrap();
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,15 +9,14 @@ fn take_str(_s: &str) {}
#[test] #[test]
fn test_unicode_encode_error() { fn test_unicode_encode_error() {
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let take_str = wrap_pyfunction!(take_str)(py).unwrap();
py_expect_exception!(
let take_str = wrap_pyfunction!(take_str)(py).unwrap(); py,
py_expect_exception!( take_str,
py, "take_str('\\ud800')",
take_str, PyUnicodeEncodeError,
"take_str('\\ud800')", "'utf-8' codec can't encode character '\\ud800' in position 0: surrogates not allowed"
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] #[pyclass]
struct MyClass {} struct MyClass {}
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<MyClass>();
let typeobj = py.get_type::<MyClass>();
py_assert!(py, typeobj, "typeobj.__doc__ is None"); py_assert!(py, typeobj, "typeobj.__doc__ is None");
py_assert!(py, typeobj, "typeobj.__text_signature__ is None"); py_assert!(py, typeobj, "typeobj.__text_signature__ is None");
});
} }
#[test] #[test]
@ -25,12 +25,12 @@ fn class_with_docs() {
/// docs line2 /// docs line2
struct MyClass {} struct MyClass {}
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<MyClass>();
let typeobj = py.get_type::<MyClass>();
py_assert!(py, typeobj, "typeobj.__doc__ == 'docs line1\\ndocs line2'"); py_assert!(py, typeobj, "typeobj.__doc__ == 'docs line1\\ndocs line2'");
py_assert!(py, typeobj, "typeobj.__text_signature__ is None"); py_assert!(py, typeobj, "typeobj.__text_signature__ is None");
});
} }
#[test] #[test]
@ -53,20 +53,20 @@ fn class_with_docs_and_signature() {
} }
} }
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<MyClass>();
let typeobj = py.get_type::<MyClass>();
py_assert!( py_assert!(
py, py,
typeobj, typeobj,
"typeobj.__doc__ == 'docs line1\\ndocs line2\\ndocs line3'" "typeobj.__doc__ == 'docs line1\\ndocs line2\\ndocs line3'"
); );
py_assert!( py_assert!(
py, py,
typeobj, typeobj,
"typeobj.__text_signature__ == '(a, b=None, *, c=42)'" "typeobj.__text_signature__ == '(a, b=None, *, c=42)'"
); );
});
} }
#[test] #[test]
@ -86,20 +86,20 @@ fn class_with_signature() {
} }
} }
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<MyClass>();
let typeobj = py.get_type::<MyClass>();
py_assert!( py_assert!(
py, py,
typeobj, typeobj,
"typeobj.__doc__ is None or typeobj.__doc__ == ''" "typeobj.__doc__ is None or typeobj.__doc__ == ''"
); );
py_assert!( py_assert!(
py, py,
typeobj, typeobj,
"typeobj.__text_signature__ == '(a, b=None, *, c=42)'" "typeobj.__text_signature__ == '(a, b=None, *, c=42)'"
); );
});
} }
#[test] #[test]
@ -110,11 +110,11 @@ fn test_function() {
let _ = (a, b, c); let _ = (a, b, c);
} }
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let f = wrap_pyfunction!(my_function)(py).unwrap();
let f = wrap_pyfunction!(my_function)(py).unwrap();
py_assert!(py, f, "f.__text_signature__ == '(a, b=None, *, c=42)'"); py_assert!(py, f, "f.__text_signature__ == '(a, b=None, *, c=42)'");
});
} }
#[test] #[test]
@ -129,15 +129,15 @@ fn test_pyfn() {
Ok(()) Ok(())
} }
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let m = wrap_pymodule!(my_module)(py);
let m = wrap_pymodule!(my_module)(py);
py_assert!( py_assert!(
py, py,
m, m,
"m.my_function.__text_signature__ == '(a, b=None, *, c=42)'" "m.my_function.__text_signature__ == '(a, b=None, *, c=42)'"
); );
});
} }
#[test] #[test]
@ -167,30 +167,30 @@ fn test_methods() {
} }
} }
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<MyClass>();
let typeobj = py.get_type::<MyClass>();
py_assert!( py_assert!(
py, py,
typeobj, typeobj,
"typeobj.method.__text_signature__ == '($self, a)'" "typeobj.method.__text_signature__ == '($self, a)'"
); );
py_assert!( py_assert!(
py, py,
typeobj, typeobj,
"typeobj.pyself_method.__text_signature__ == '($self, b)'" "typeobj.pyself_method.__text_signature__ == '($self, b)'"
); );
py_assert!( py_assert!(
py, py,
typeobj, typeobj,
"typeobj.class_method.__text_signature__ == '($cls, c)'" "typeobj.class_method.__text_signature__ == '($cls, c)'"
); );
py_assert!( py_assert!(
py, py,
typeobj, typeobj,
"typeobj.static_method.__text_signature__ == '(d)'" "typeobj.static_method.__text_signature__ == '(d)'"
); );
});
} }
#[test] #[test]
@ -210,15 +210,15 @@ fn test_raw_identifiers() {
fn r#method(&self) {} fn r#method(&self) {}
} }
let gil = Python::acquire_gil(); Python::with_gil(|py| {
let py = gil.python(); let typeobj = py.get_type::<MyClass>();
let typeobj = py.get_type::<MyClass>();
py_assert!(py, typeobj, "typeobj.__text_signature__ == '($self)'"); py_assert!(py, typeobj, "typeobj.__text_signature__ == '($self)'");
py_assert!( py_assert!(
py, py,
typeobj, typeobj,
"typeobj.method.__text_signature__ == '($self)'" "typeobj.method.__text_signature__ == '($self)'"
); );
});
} }

View file

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

View file

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

View file

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