Use Python:;with_gil in tests
This commit is contained in:
parent
2b6d59f889
commit
984fdf57c7
|
@ -5,62 +5,62 @@ use pyo3::types::IntoPyDict;
|
|||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
fn iter_dict(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for (k, _v) in dict.iter() {
|
||||
let i: u64 = k.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
});
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for (k, _v) in dict.iter() {
|
||||
let i: u64 = k.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
fn dict_new(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 50_000;
|
||||
b.iter(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py));
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
b.iter(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py));
|
||||
});
|
||||
}
|
||||
|
||||
fn dict_get_item(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 50_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
sum += dict.get_item(i).unwrap().extract::<usize>().unwrap();
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
sum += dict.get_item(i).unwrap().extract::<usize>().unwrap();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn extract_hashmap(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
b.iter(|| HashMap::<u64, u64>::extract(dict));
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
b.iter(|| HashMap::<u64, u64>::extract(dict));
|
||||
});
|
||||
}
|
||||
|
||||
fn extract_btreemap(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
b.iter(|| BTreeMap::<u64, u64>::extract(dict));
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
b.iter(|| BTreeMap::<u64, u64>::extract(dict));
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "hashbrown")]
|
||||
fn extract_hashbrown_map(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
b.iter(|| hashbrown::HashMap::<u64, u64>::extract(dict));
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
b.iter(|| hashbrown::HashMap::<u64, u64>::extract(dict));
|
||||
});
|
||||
}
|
||||
|
||||
fn criterion_benchmark(c: &mut Criterion) {
|
||||
|
|
|
@ -13,7 +13,7 @@ fn bench_clean_gilpool_new(b: &mut Bencher<'_>) {
|
|||
fn bench_clean_acquire_gil(b: &mut Bencher<'_>) {
|
||||
// Acquiring first GIL will also create a "clean" GILPool, so this measures the Python overhead.
|
||||
b.iter(|| {
|
||||
let _ = Python::acquire_gil();
|
||||
let _ = Python::with_gil(|_| {});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ fn bench_dirty_acquire_gil(b: &mut Bencher<'_>) {
|
|||
let _ = obj.clone();
|
||||
},
|
||||
|_| {
|
||||
let _ = Python::acquire_gil();
|
||||
let _ = Python::with_gil(|_| {});
|
||||
},
|
||||
BatchSize::NumBatches(1),
|
||||
);
|
||||
|
|
|
@ -4,52 +4,52 @@ use pyo3::prelude::*;
|
|||
use pyo3::types::PyList;
|
||||
|
||||
fn iter_list(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let list = PyList::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for x in list.iter() {
|
||||
let i: u64 = x.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let list = PyList::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for x in list.iter() {
|
||||
let i: u64 = x.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn list_new(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 50_000;
|
||||
b.iter(|| PyList::new(py, 0..LEN));
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
b.iter(|| PyList::new(py, 0..LEN));
|
||||
});
|
||||
}
|
||||
|
||||
fn list_get_item(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 50_000;
|
||||
let list = PyList::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
sum += list.get_item(i).unwrap().extract::<usize>().unwrap();
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
let list = PyList::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
sum += list.get_item(i).unwrap().extract::<usize>().unwrap();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
fn list_get_item_unchecked(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 50_000;
|
||||
let list = PyList::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
unsafe {
|
||||
sum += list.get_item_unchecked(i).extract::<usize>().unwrap();
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
let list = PyList::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
unsafe {
|
||||
sum += list.get_item_unchecked(i).extract::<usize>().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -27,13 +27,13 @@ impl MyClass {
|
|||
}
|
||||
|
||||
pub fn first_time_init(b: &mut criterion::Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
b.iter(|| {
|
||||
// This is using an undocumented internal PyO3 API to measure pyclass performance; please
|
||||
// don't use this in your own code!
|
||||
let ty = LazyStaticType::new();
|
||||
ty.get_or_init::<MyClass>(py);
|
||||
Python::with_gil(|py| {
|
||||
b.iter(|| {
|
||||
// This is using an undocumented internal PyO3 API to measure pyclass performance; please
|
||||
// don't use this in your own code!
|
||||
let ty = LazyStaticType::new();
|
||||
ty.get_or_init::<MyClass>(py);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@ use criterion::{criterion_group, criterion_main, Bencher, Criterion};
|
|||
use pyo3::prelude::*;
|
||||
|
||||
fn drop_many_objects(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
b.iter(|| {
|
||||
for _ in 0..1000 {
|
||||
std::mem::drop(py.None());
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
b.iter(|| {
|
||||
for _ in 0..1000 {
|
||||
std::mem::drop(py.None());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -5,42 +5,42 @@ use pyo3::types::PySet;
|
|||
use std::collections::{BTreeSet, HashSet};
|
||||
|
||||
fn iter_set(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for x in set.iter() {
|
||||
let i: u64 = x.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for x in set.iter() {
|
||||
let i: u64 = x.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn extract_hashset(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
|
||||
b.iter(|| HashSet::<u64>::extract(set));
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
|
||||
b.iter(|| HashSet::<u64>::extract(set));
|
||||
});
|
||||
}
|
||||
|
||||
fn extract_btreeset(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
|
||||
b.iter(|| BTreeSet::<u64>::extract(set));
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
|
||||
b.iter(|| BTreeSet::<u64>::extract(set));
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "hashbrown")]
|
||||
fn extract_hashbrown_set(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
|
||||
b.iter(|| hashbrown::HashSet::<u64>::extract(set));
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
|
||||
b.iter(|| hashbrown::HashSet::<u64>::extract(set));
|
||||
});
|
||||
}
|
||||
|
||||
fn criterion_benchmark(c: &mut Criterion) {
|
||||
|
|
|
@ -4,52 +4,52 @@ use pyo3::prelude::*;
|
|||
use pyo3::types::PyTuple;
|
||||
|
||||
fn iter_tuple(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 100_000;
|
||||
let tuple = PyTuple::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for x in tuple.iter() {
|
||||
let i: u64 = x.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let tuple = PyTuple::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for x in tuple.iter() {
|
||||
let i: u64 = x.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn tuple_new(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 50_000;
|
||||
b.iter(|| PyTuple::new(py, 0..LEN));
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
b.iter(|| PyTuple::new(py, 0..LEN));
|
||||
});
|
||||
}
|
||||
|
||||
fn tuple_get_item(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 50_000;
|
||||
let tuple = PyTuple::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
sum += tuple.get_item(i).unwrap().extract::<usize>().unwrap();
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
let tuple = PyTuple::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
sum += tuple.get_item(i).unwrap().extract::<usize>().unwrap();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
fn tuple_get_item_unchecked(b: &mut Bencher<'_>) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 50_000;
|
||||
let tuple = PyTuple::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
unsafe {
|
||||
sum += tuple.get_item_unchecked(i).extract::<usize>().unwrap();
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
let tuple = PyTuple::new(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
unsafe {
|
||||
sum += tuple.get_item_unchecked(i).extract::<usize>().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -796,12 +796,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn set_typeerror() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let err: PyErr = exceptions::PyTypeError::new_err(());
|
||||
err.restore(py);
|
||||
assert!(PyErr::occurred(py));
|
||||
drop(PyErr::fetch(py));
|
||||
Python::with_gil(|py| {
|
||||
let err: PyErr = exceptions::PyTypeError::new_err(());
|
||||
err.restore(py);
|
||||
assert!(PyErr::occurred(py));
|
||||
drop(PyErr::fetch(py));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -41,15 +41,14 @@ impl UnaryArithmetic {
|
|||
|
||||
#[test]
|
||||
fn unary_arithmetic() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
|
||||
py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
|
||||
py_run!(py, c, "assert repr(+c) == 'UA(2.7)'");
|
||||
py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'");
|
||||
py_run!(py, c, "assert repr(round(c)) == 'UA(3)'");
|
||||
py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'");
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
|
||||
py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
|
||||
py_run!(py, c, "assert repr(+c) == 'UA(2.7)'");
|
||||
py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'");
|
||||
py_run!(py, c, "assert repr(round(c)) == 'UA(3)'");
|
||||
py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -135,26 +134,26 @@ impl InPlaceOperations {
|
|||
|
||||
#[test]
|
||||
fn inplace_operations() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let init = |value, code| {
|
||||
let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
|
||||
py_run!(py, c, code);
|
||||
};
|
||||
Python::with_gil(|py| {
|
||||
let init = |value, code| {
|
||||
let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
|
||||
py_run!(py, c, code);
|
||||
};
|
||||
|
||||
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(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(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 |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
|
||||
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.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
|
||||
);
|
||||
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(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(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 |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
|
||||
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.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -205,36 +204,35 @@ impl BinaryArithmetic {
|
|||
|
||||
#[test]
|
||||
fn binary_arithmetic() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, BinaryArithmetic {}).unwrap();
|
||||
py_run!(py, c, "assert c + c == 'BA + BA'");
|
||||
py_run!(py, c, "assert c.__add__(c) == 'BA + BA'");
|
||||
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();
|
||||
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)'");
|
||||
// Class with __add__ only should not allow the reverse op;
|
||||
// this is consistent with Python classes.
|
||||
|
||||
// Class with __add__ only should not allow the reverse op;
|
||||
// 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_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_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -281,28 +279,27 @@ impl RhsArithmetic {
|
|||
|
||||
#[test]
|
||||
fn rhs_arithmetic() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, RhsArithmetic {}).unwrap();
|
||||
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
|
||||
py_run!(py, c, "assert 1 + c == '1 + RA'");
|
||||
py_run!(py, c, "assert c.__rsub__(1) == '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 1 * c == '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 c.__rrshift__(1) == '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 1 & c == '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 c.__ror__(1) == '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'");
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, RhsArithmetic {}).unwrap();
|
||||
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
|
||||
py_run!(py, c, "assert 1 + c == '1 + RA'");
|
||||
py_run!(py, c, "assert c.__rsub__(1) == '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 1 * c == '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 c.__rrshift__(1) == '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 1 & c == '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 c.__ror__(1) == '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]
|
||||
|
@ -411,32 +408,31 @@ impl LhsAndRhs {
|
|||
|
||||
#[test]
|
||||
fn lhs_fellback_to_rhs() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, LhsAndRhs {}).unwrap();
|
||||
// If the light hand value is `LhsAndRhs`, LHS is used.
|
||||
py_run!(py, c, "assert c + 1 == 'LR + 1'");
|
||||
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 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'");
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, LhsAndRhs {}).unwrap();
|
||||
// If the light hand value is `LhsAndRhs`, LHS is used.
|
||||
py_run!(py, c, "assert c + 1 == 'LR + 1'");
|
||||
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 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]
|
||||
|
@ -480,54 +476,52 @@ impl RichComparisons2 {
|
|||
|
||||
#[test]
|
||||
fn rich_comparisons() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, RichComparisons {}).unwrap();
|
||||
py_run!(py, c, "assert (c < c) == 'RC < RC'");
|
||||
py_run!(py, c, "assert (c < 1) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (1 < c) == 'RC > 1'");
|
||||
py_run!(py, c, "assert (c <= c) == 'RC <= RC'");
|
||||
py_run!(py, c, "assert (c <= 1) == 'RC <= 1'");
|
||||
py_run!(py, c, "assert (1 <= c) == 'RC >= 1'");
|
||||
py_run!(py, c, "assert (c == c) == 'RC == RC'");
|
||||
py_run!(py, c, "assert (c == 1) == 'RC == 1'");
|
||||
py_run!(py, c, "assert (1 == c) == 'RC == 1'");
|
||||
py_run!(py, c, "assert (c != c) == 'RC != RC'");
|
||||
py_run!(py, c, "assert (c != 1) == 'RC != 1'");
|
||||
py_run!(py, c, "assert (1 != c) == 'RC != 1'");
|
||||
py_run!(py, c, "assert (c > c) == 'RC > RC'");
|
||||
py_run!(py, c, "assert (c > 1) == 'RC > 1'");
|
||||
py_run!(py, c, "assert (1 > c) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (c >= c) == 'RC >= RC'");
|
||||
py_run!(py, c, "assert (c >= 1) == 'RC >= 1'");
|
||||
py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, RichComparisons {}).unwrap();
|
||||
py_run!(py, c, "assert (c < c) == 'RC < RC'");
|
||||
py_run!(py, c, "assert (c < 1) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (1 < c) == 'RC > 1'");
|
||||
py_run!(py, c, "assert (c <= c) == 'RC <= RC'");
|
||||
py_run!(py, c, "assert (c <= 1) == 'RC <= 1'");
|
||||
py_run!(py, c, "assert (1 <= c) == 'RC >= 1'");
|
||||
py_run!(py, c, "assert (c == c) == 'RC == RC'");
|
||||
py_run!(py, c, "assert (c == 1) == 'RC == 1'");
|
||||
py_run!(py, c, "assert (1 == c) == 'RC == 1'");
|
||||
py_run!(py, c, "assert (c != c) == 'RC != RC'");
|
||||
py_run!(py, c, "assert (c != 1) == 'RC != 1'");
|
||||
py_run!(py, c, "assert (1 != c) == 'RC != 1'");
|
||||
py_run!(py, c, "assert (c > c) == 'RC > RC'");
|
||||
py_run!(py, c, "assert (c > 1) == 'RC > 1'");
|
||||
py_run!(py, c, "assert (1 > c) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (c >= c) == 'RC >= RC'");
|
||||
py_run!(py, c, "assert (c >= 1) == 'RC >= 1'");
|
||||
py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rich_comparisons_python_3_type_error() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
|
||||
py_expect_exception!(py, c2, "c2 < c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 < 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 < c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 <= c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 <= 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 <= c2", PyTypeError);
|
||||
py_run!(py, c2, "assert (c2 == c2) == True");
|
||||
py_run!(py, c2, "assert (c2 == 1) == True");
|
||||
py_run!(py, c2, "assert (1 == c2) == True");
|
||||
py_run!(py, c2, "assert (c2 != c2) == False");
|
||||
py_run!(py, c2, "assert (c2 != 1) == False");
|
||||
py_run!(py, c2, "assert (1 != c2) == False");
|
||||
py_expect_exception!(py, c2, "c2 > c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 > 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 > c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 >= c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 >= 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 >= c2", PyTypeError);
|
||||
Python::with_gil(|py| {
|
||||
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
|
||||
py_expect_exception!(py, c2, "c2 < c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 < 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 < c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 <= c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 <= 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 <= c2", PyTypeError);
|
||||
py_run!(py, c2, "assert (c2 == c2) == True");
|
||||
py_run!(py, c2, "assert (c2 == 1) == True");
|
||||
py_run!(py, c2, "assert (1 == c2) == True");
|
||||
py_run!(py, c2, "assert (c2 != c2) == False");
|
||||
py_run!(py, c2, "assert (c2 != 1) == False");
|
||||
py_run!(py, c2, "assert (1 != c2) == False");
|
||||
py_expect_exception!(py, c2, "c2 > c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 > 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 > c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 >= c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 >= 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 >= c2", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
// Checks that binary operations for which the arguments don't match the
|
||||
|
@ -608,31 +602,31 @@ mod return_not_implemented {
|
|||
}
|
||||
|
||||
fn _test_binary_dunder(dunder: &str) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
c2,
|
||||
&format!(
|
||||
"class Other: pass\nassert c2.__{}__(Other()) is NotImplemented",
|
||||
dunder
|
||||
)
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
c2,
|
||||
&format!(
|
||||
"class Other: pass\nassert c2.__{}__(Other()) is NotImplemented",
|
||||
dunder
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn _test_binary_operator(operator: &str, dunder: &str) {
|
||||
_test_binary_dunder(dunder);
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
|
||||
py_expect_exception!(
|
||||
py,
|
||||
c2,
|
||||
&format!("class Other: pass\nc2 {} Other()", operator),
|
||||
PyTypeError
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
|
||||
py_expect_exception!(
|
||||
py,
|
||||
c2,
|
||||
&format!("class Other: pass\nc2 {} Other()", operator),
|
||||
PyTypeError
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn _test_inplace_binary_operator(operator: &str, dunder: &str) {
|
||||
|
|
|
@ -44,13 +44,12 @@ impl PyNumberProtocol for UnaryArithmetic {
|
|||
|
||||
#[test]
|
||||
fn unary_arithmetic() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
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)'");
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, UnaryArithmetic::new(2.7)).unwrap();
|
||||
py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'");
|
||||
py_run!(py, c, "assert repr(+c) == 'UA(2.7)'");
|
||||
py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -115,26 +114,26 @@ impl PyNumberProtocol for InPlaceOperations {
|
|||
}
|
||||
#[test]
|
||||
fn inplace_operations() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let init = |value, code| {
|
||||
let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
|
||||
py_run!(py, c, code);
|
||||
};
|
||||
Python::with_gil(|py| {
|
||||
let init = |value, code| {
|
||||
let c = PyCell::new(py, InPlaceOperations { value }).unwrap();
|
||||
py_run!(py, c, code);
|
||||
};
|
||||
|
||||
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(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(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 |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
|
||||
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.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
|
||||
);
|
||||
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(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(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 |= 3; assert repr(c) == repr(d) == 'IPO(15)'");
|
||||
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.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyproto]
|
||||
|
@ -182,35 +181,34 @@ impl PyNumberProtocol for BinaryArithmetic {
|
|||
|
||||
#[test]
|
||||
fn binary_arithmetic() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, BinaryArithmetic {}).unwrap();
|
||||
py_run!(py, c, "assert c + c == 'BA + BA'");
|
||||
py_run!(py, c, "assert c.__add__(c) == 'BA + BA'");
|
||||
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 + 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'");
|
||||
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'");
|
||||
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 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))'");
|
||||
py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -261,30 +259,29 @@ impl PyNumberProtocol for RhsArithmetic {
|
|||
|
||||
#[test]
|
||||
fn rhs_arithmetic() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, RhsArithmetic {}).unwrap();
|
||||
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
|
||||
py_run!(py, c, "assert 1 + c == '1 + RA'");
|
||||
py_run!(py, c, "assert c.__rsub__(1) == '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 1 % c == '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 c.__rlshift__(1) == '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 1 >> c == '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 c.__rxor__(1) == '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 1 | c == '1 | RA'");
|
||||
py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
|
||||
py_run!(py, c, "assert 1 ** c == '1 ** RA'");
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, RhsArithmetic {}).unwrap();
|
||||
py_run!(py, c, "assert c.__radd__(1) == '1 + RA'");
|
||||
py_run!(py, c, "assert 1 + c == '1 + RA'");
|
||||
py_run!(py, c, "assert c.__rsub__(1) == '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 1 % c == '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 c.__rlshift__(1) == '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 1 >> c == '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 c.__rxor__(1) == '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 1 | c == '1 | RA'");
|
||||
py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'");
|
||||
py_run!(py, c, "assert 1 ** c == '1 ** RA'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -396,34 +393,33 @@ impl PyObjectProtocol for LhsAndRhs {
|
|||
|
||||
#[test]
|
||||
fn lhs_fellback_to_rhs() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, LhsAndRhs {}).unwrap();
|
||||
// If the light hand value is `LhsAndRhs`, LHS is used.
|
||||
py_run!(py, c, "assert c + 1 == 'LR + 1'");
|
||||
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 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'");
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, LhsAndRhs {}).unwrap();
|
||||
// If the light hand value is `LhsAndRhs`, LHS is used.
|
||||
py_run!(py, c, "assert c + 1 == 'LR + 1'");
|
||||
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 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]
|
||||
|
@ -467,54 +463,52 @@ impl PyObjectProtocol for RichComparisons2 {
|
|||
|
||||
#[test]
|
||||
fn rich_comparisons() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, RichComparisons {}).unwrap();
|
||||
py_run!(py, c, "assert (c < c) == 'RC < RC'");
|
||||
py_run!(py, c, "assert (c < 1) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (1 < c) == 'RC > 1'");
|
||||
py_run!(py, c, "assert (c <= c) == 'RC <= RC'");
|
||||
py_run!(py, c, "assert (c <= 1) == 'RC <= 1'");
|
||||
py_run!(py, c, "assert (1 <= c) == 'RC >= 1'");
|
||||
py_run!(py, c, "assert (c == c) == 'RC == RC'");
|
||||
py_run!(py, c, "assert (c == 1) == 'RC == 1'");
|
||||
py_run!(py, c, "assert (1 == c) == 'RC == 1'");
|
||||
py_run!(py, c, "assert (c != c) == 'RC != RC'");
|
||||
py_run!(py, c, "assert (c != 1) == 'RC != 1'");
|
||||
py_run!(py, c, "assert (1 != c) == 'RC != 1'");
|
||||
py_run!(py, c, "assert (c > c) == 'RC > RC'");
|
||||
py_run!(py, c, "assert (c > 1) == 'RC > 1'");
|
||||
py_run!(py, c, "assert (1 > c) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (c >= c) == 'RC >= RC'");
|
||||
py_run!(py, c, "assert (c >= 1) == 'RC >= 1'");
|
||||
py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
|
||||
Python::with_gil(|py| {
|
||||
let c = PyCell::new(py, RichComparisons {}).unwrap();
|
||||
py_run!(py, c, "assert (c < c) == 'RC < RC'");
|
||||
py_run!(py, c, "assert (c < 1) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (1 < c) == 'RC > 1'");
|
||||
py_run!(py, c, "assert (c <= c) == 'RC <= RC'");
|
||||
py_run!(py, c, "assert (c <= 1) == 'RC <= 1'");
|
||||
py_run!(py, c, "assert (1 <= c) == 'RC >= 1'");
|
||||
py_run!(py, c, "assert (c == c) == 'RC == RC'");
|
||||
py_run!(py, c, "assert (c == 1) == 'RC == 1'");
|
||||
py_run!(py, c, "assert (1 == c) == 'RC == 1'");
|
||||
py_run!(py, c, "assert (c != c) == 'RC != RC'");
|
||||
py_run!(py, c, "assert (c != 1) == 'RC != 1'");
|
||||
py_run!(py, c, "assert (1 != c) == 'RC != 1'");
|
||||
py_run!(py, c, "assert (c > c) == 'RC > RC'");
|
||||
py_run!(py, c, "assert (c > 1) == 'RC > 1'");
|
||||
py_run!(py, c, "assert (1 > c) == 'RC < 1'");
|
||||
py_run!(py, c, "assert (c >= c) == 'RC >= RC'");
|
||||
py_run!(py, c, "assert (c >= 1) == 'RC >= 1'");
|
||||
py_run!(py, c, "assert (1 >= c) == 'RC <= 1'");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rich_comparisons_python_3_type_error() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
|
||||
py_expect_exception!(py, c2, "c2 < c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 < 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 < c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 <= c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 <= 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 <= c2", PyTypeError);
|
||||
py_run!(py, c2, "assert (c2 == c2) == True");
|
||||
py_run!(py, c2, "assert (c2 == 1) == True");
|
||||
py_run!(py, c2, "assert (1 == c2) == True");
|
||||
py_run!(py, c2, "assert (c2 != c2) == False");
|
||||
py_run!(py, c2, "assert (c2 != 1) == False");
|
||||
py_run!(py, c2, "assert (1 != c2) == False");
|
||||
py_expect_exception!(py, c2, "c2 > c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 > 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 > c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 >= c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 >= 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 >= c2", PyTypeError);
|
||||
Python::with_gil(|py| {
|
||||
let c2 = PyCell::new(py, RichComparisons2 {}).unwrap();
|
||||
py_expect_exception!(py, c2, "c2 < c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 < 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 < c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 <= c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 <= 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 <= c2", PyTypeError);
|
||||
py_run!(py, c2, "assert (c2 == c2) == True");
|
||||
py_run!(py, c2, "assert (c2 == 1) == True");
|
||||
py_run!(py, c2, "assert (1 == c2) == True");
|
||||
py_run!(py, c2, "assert (c2 != c2) == False");
|
||||
py_run!(py, c2, "assert (c2 != 1) == False");
|
||||
py_run!(py, c2, "assert (1 != c2) == False");
|
||||
py_expect_exception!(py, c2, "c2 > c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 > 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 > c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 >= c2", PyTypeError);
|
||||
py_expect_exception!(py, c2, "c2 >= 1", PyTypeError);
|
||||
py_expect_exception!(py, c2, "1 >= c2", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
// Checks that binary operations for which the arguments don't match the
|
||||
|
@ -598,31 +592,31 @@ mod return_not_implemented {
|
|||
}
|
||||
|
||||
fn _test_binary_dunder(dunder: &str) {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
c2,
|
||||
&format!(
|
||||
"class Other: pass\nassert c2.__{}__(Other()) is NotImplemented",
|
||||
dunder
|
||||
)
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
c2,
|
||||
&format!(
|
||||
"class Other: pass\nassert c2.__{}__(Other()) is NotImplemented",
|
||||
dunder
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn _test_binary_operator(operator: &str, dunder: &str) {
|
||||
_test_binary_dunder(dunder);
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
|
||||
py_expect_exception!(
|
||||
py,
|
||||
c2,
|
||||
&format!("class Other: pass\nc2 {} Other()", operator),
|
||||
PyTypeError
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
|
||||
py_expect_exception!(
|
||||
py,
|
||||
c2,
|
||||
&format!("class Other: pass\nc2 {} Other()", operator),
|
||||
PyTypeError
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn _test_inplace_binary_operator(operator: &str, dunder: &str) {
|
||||
|
|
|
@ -87,18 +87,18 @@ fn test_buffer() {
|
|||
let drop_called = Arc::new(AtomicBool::new(false));
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let instance = Py::new(
|
||||
py,
|
||||
TestBufferClass {
|
||||
vec: vec![b' ', b'2', b'3'],
|
||||
drop_called: drop_called.clone(),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let env = [("ob", instance)].into_py_dict(py);
|
||||
py_assert!(py, *env, "bytes(ob) == b' 23'");
|
||||
Python::with_gil(|py| {
|
||||
let instance = Py::new(
|
||||
py,
|
||||
TestBufferClass {
|
||||
vec: vec![b' ', b'2', b'3'],
|
||||
drop_called: drop_called.clone(),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let env = [("ob", instance)].into_py_dict(py);
|
||||
py_assert!(py, *env, "bytes(ob) == b' 23'");
|
||||
});
|
||||
}
|
||||
|
||||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
|
@ -110,26 +110,25 @@ fn test_buffer_referenced() {
|
|||
|
||||
let buf = {
|
||||
let input = vec![b' ', b'2', b'3'];
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let instance: PyObject = TestBufferClass {
|
||||
vec: input.clone(),
|
||||
drop_called: drop_called.clone(),
|
||||
}
|
||||
.into_py(py);
|
||||
Python::with_gil(|py| {
|
||||
let instance: PyObject = TestBufferClass {
|
||||
vec: input.clone(),
|
||||
drop_called: drop_called.clone(),
|
||||
}
|
||||
.into_py(py);
|
||||
|
||||
let buf = PyBuffer::<u8>::get(instance.as_ref(py)).unwrap();
|
||||
assert_eq!(buf.to_vec(py).unwrap(), input);
|
||||
drop(instance);
|
||||
buf
|
||||
let buf = PyBuffer::<u8>::get(instance.as_ref(py)).unwrap();
|
||||
assert_eq!(buf.to_vec(py).unwrap(), input);
|
||||
drop(instance);
|
||||
buf
|
||||
})
|
||||
};
|
||||
|
||||
assert!(!drop_called.load(Ordering::Relaxed));
|
||||
|
||||
{
|
||||
let _py = Python::acquire_gil().python();
|
||||
Python::with_gil(|_| {
|
||||
drop(buf);
|
||||
}
|
||||
});
|
||||
|
||||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
}
|
||||
|
|
|
@ -85,9 +85,7 @@ impl Drop for TestBufferClass {
|
|||
fn test_buffer() {
|
||||
let drop_called = Arc::new(AtomicBool::new(false));
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let instance = Py::new(
|
||||
py,
|
||||
TestBufferClass {
|
||||
|
@ -98,7 +96,7 @@ fn test_buffer() {
|
|||
.unwrap();
|
||||
let env = [("ob", instance)].into_py_dict(py);
|
||||
py_assert!(py, *env, "bytes(ob) == b' 23'");
|
||||
}
|
||||
});
|
||||
|
||||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
}
|
||||
|
@ -107,28 +105,27 @@ fn test_buffer() {
|
|||
fn test_buffer_referenced() {
|
||||
let drop_called = Arc::new(AtomicBool::new(false));
|
||||
|
||||
let buf = {
|
||||
let buf: PyBuffer<u8> = {
|
||||
let input = vec![b' ', b'2', b'3'];
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let instance: PyObject = TestBufferClass {
|
||||
vec: input.clone(),
|
||||
drop_called: drop_called.clone(),
|
||||
}
|
||||
.into_py(py);
|
||||
Python::with_gil(|py| {
|
||||
let instance: PyObject = TestBufferClass {
|
||||
vec: input.clone(),
|
||||
drop_called: drop_called.clone(),
|
||||
}
|
||||
.into_py(py);
|
||||
|
||||
let buf = PyBuffer::<u8>::get(instance.as_ref(py)).unwrap();
|
||||
assert_eq!(buf.to_vec(py).unwrap(), input);
|
||||
drop(instance);
|
||||
buf
|
||||
let buf = PyBuffer::<u8>::get(instance.as_ref(py)).unwrap();
|
||||
assert_eq!(buf.to_vec(py).unwrap(), input);
|
||||
drop(instance);
|
||||
buf
|
||||
})
|
||||
};
|
||||
|
||||
assert!(!drop_called.load(Ordering::Relaxed));
|
||||
|
||||
{
|
||||
let _py = Python::acquire_gil().python();
|
||||
Python::with_gil(|_| {
|
||||
drop(buf);
|
||||
}
|
||||
});
|
||||
|
||||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
}
|
||||
|
|
|
@ -12,11 +12,10 @@ fn bytes_pybytes_conversion(bytes: &[u8]) -> &[u8] {
|
|||
|
||||
#[test]
|
||||
fn test_pybytes_bytes_conversion() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let f = wrap_pyfunction!(bytes_pybytes_conversion)(py).unwrap();
|
||||
py_assert!(py, f, "f(b'Hello World') == b'Hello World'");
|
||||
Python::with_gil(|py| {
|
||||
let f = wrap_pyfunction!(bytes_pybytes_conversion)(py).unwrap();
|
||||
py_assert!(py, f, "f(b'Hello World') == b'Hello World'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
@ -26,33 +25,26 @@ fn bytes_vec_conversion(py: Python<'_>, bytes: Vec<u8>) -> &PyBytes {
|
|||
|
||||
#[test]
|
||||
fn test_pybytes_vec_conversion() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();
|
||||
py_assert!(py, f, "f(b'Hello World') == b'Hello World'");
|
||||
Python::with_gil(|py| {
|
||||
let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();
|
||||
py_assert!(py, f, "f(b'Hello World') == b'Hello World'");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bytearray_vec_conversion() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();
|
||||
py_assert!(py, f, "f(bytearray(b'Hello World')) == b'Hello World'");
|
||||
Python::with_gil(|py| {
|
||||
let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();
|
||||
py_assert!(py, f, "f(bytearray(b'Hello World')) == b'Hello World'");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_py_as_bytes() {
|
||||
let pyobj: pyo3::Py<pyo3::types::PyBytes>;
|
||||
let data: &[u8];
|
||||
let pyobj: pyo3::Py<pyo3::types::PyBytes> =
|
||||
Python::with_gil(|py| pyo3::types::PyBytes::new(py, b"abc").into_py(py));
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
pyobj = pyo3::types::PyBytes::new(py, b"abc").into_py(py);
|
||||
data = pyobj.as_bytes(py);
|
||||
}
|
||||
let data = Python::with_gil(|py| pyobj.as_bytes(py));
|
||||
|
||||
assert_eq!(data, b"abc");
|
||||
}
|
||||
|
|
|
@ -54,15 +54,15 @@ impl Foo {
|
|||
|
||||
#[test]
|
||||
fn class_attributes() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let foo_obj = py.get_type::<Foo>();
|
||||
py_assert!(py, foo_obj, "foo_obj.MY_CONST == 'foobar'");
|
||||
py_assert!(py, foo_obj, "foo_obj.RENAMED_CONST == 'foobar_2'");
|
||||
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.a_foo.x == 1");
|
||||
py_assert!(py, foo_obj, "foo_obj.a_foo_with_py.x == 1");
|
||||
Python::with_gil(|py| {
|
||||
let foo_obj = py.get_type::<Foo>();
|
||||
py_assert!(py, foo_obj, "foo_obj.MY_CONST == 'foobar'");
|
||||
py_assert!(py, foo_obj, "foo_obj.RENAMED_CONST == 'foobar_2'");
|
||||
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.a_foo.x == 1");
|
||||
py_assert!(py, foo_obj, "foo_obj.a_foo_with_py.x == 1");
|
||||
});
|
||||
}
|
||||
|
||||
// Ignored because heap types are not immutable:
|
||||
|
@ -70,10 +70,10 @@ fn class_attributes() {
|
|||
#[test]
|
||||
#[ignore]
|
||||
fn class_attributes_are_immutable() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let foo_obj = py.get_type::<Foo>();
|
||||
py_expect_exception!(py, foo_obj, "foo_obj.a = 6", PyTypeError);
|
||||
Python::with_gil(|py| {
|
||||
let foo_obj = py.get_type::<Foo>();
|
||||
py_expect_exception!(py, foo_obj, "foo_obj.a = 6", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
|
@ -86,14 +86,13 @@ impl Bar {
|
|||
|
||||
#[test]
|
||||
fn recursive_class_attributes() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let foo_obj = py.get_type::<Foo>();
|
||||
let bar_obj = py.get_type::<Bar>();
|
||||
py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1");
|
||||
py_assert!(py, foo_obj, "foo_obj.bar.x == 2");
|
||||
py_assert!(py, bar_obj, "bar_obj.a_foo.x == 3");
|
||||
Python::with_gil(|py| {
|
||||
let foo_obj = py.get_type::<Foo>();
|
||||
let bar_obj = py.get_type::<Bar>();
|
||||
py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1");
|
||||
py_assert!(py, foo_obj, "foo_obj.bar.x == 2");
|
||||
py_assert!(py, bar_obj, "bar_obj.a_foo.x == 3");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -11,13 +11,13 @@ struct EmptyClass {}
|
|||
|
||||
#[test]
|
||||
fn empty_class() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<EmptyClass>();
|
||||
// By default, don't allow creating instances from python.
|
||||
assert!(typeobj.call((), None).is_err());
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<EmptyClass>();
|
||||
// By default, don't allow creating instances from python.
|
||||
assert!(typeobj.call((), None).is_err());
|
||||
|
||||
py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
|
||||
py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -56,9 +56,7 @@ struct ClassWithDocs {
|
|||
|
||||
#[test]
|
||||
fn class_with_docstr() {
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<ClassWithDocs>();
|
||||
py_run!(
|
||||
py,
|
||||
|
@ -80,7 +78,7 @@ fn class_with_docstr() {
|
|||
typeobj,
|
||||
"assert typeobj.writeonly.__doc__ == 'Write-only property field'"
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(name = "CustomName")]
|
||||
|
@ -104,24 +102,24 @@ impl EmptyClass2 {
|
|||
|
||||
#[test]
|
||||
fn custom_names() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<EmptyClass2>();
|
||||
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
|
||||
py_assert!(py, typeobj, "typeobj.custom_fn.__name__ == 'custom_fn'");
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.custom_static.__name__ == 'custom_static'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.custom_getter.__name__ == 'custom_getter'"
|
||||
);
|
||||
py_assert!(py, typeobj, "not hasattr(typeobj, 'bar')");
|
||||
py_assert!(py, typeobj, "not hasattr(typeobj, 'bar_static')");
|
||||
py_assert!(py, typeobj, "not hasattr(typeobj, 'foo')");
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<EmptyClass2>();
|
||||
py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'");
|
||||
py_assert!(py, typeobj, "typeobj.custom_fn.__name__ == 'custom_fn'");
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.custom_static.__name__ == 'custom_static'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.custom_getter.__name__ == 'custom_getter'"
|
||||
);
|
||||
py_assert!(py, typeobj, "not hasattr(typeobj, 'bar')");
|
||||
py_assert!(py, typeobj, "not hasattr(typeobj, 'bar_static')");
|
||||
py_assert!(py, typeobj, "not hasattr(typeobj, 'foo')");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -137,12 +135,12 @@ impl RawIdents {
|
|||
|
||||
#[test]
|
||||
fn test_raw_idents() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<RawIdents>();
|
||||
py_assert!(py, typeobj, "not hasattr(typeobj, 'r#fn')");
|
||||
py_assert!(py, typeobj, "hasattr(typeobj, 'fn')");
|
||||
py_assert!(py, typeobj, "hasattr(typeobj, 'type')");
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<RawIdents>();
|
||||
py_assert!(py, typeobj, "not hasattr(typeobj, 'r#fn')");
|
||||
py_assert!(py, typeobj, "hasattr(typeobj, 'fn')");
|
||||
py_assert!(py, typeobj, "hasattr(typeobj, 'type')");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -154,23 +152,23 @@ struct EmptyClassInModule {}
|
|||
#[test]
|
||||
#[ignore]
|
||||
fn empty_class_in_module() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let module = PyModule::new(py, "test_module.nested").unwrap();
|
||||
module.add_class::<EmptyClassInModule>().unwrap();
|
||||
Python::with_gil(|py| {
|
||||
let module = PyModule::new(py, "test_module.nested").unwrap();
|
||||
module.add_class::<EmptyClassInModule>().unwrap();
|
||||
|
||||
let ty = module.getattr("EmptyClassInModule").unwrap();
|
||||
assert_eq!(
|
||||
ty.getattr("__name__").unwrap().extract::<String>().unwrap(),
|
||||
"EmptyClassInModule"
|
||||
);
|
||||
let ty = module.getattr("EmptyClassInModule").unwrap();
|
||||
assert_eq!(
|
||||
ty.getattr("__name__").unwrap().extract::<String>().unwrap(),
|
||||
"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.
|
||||
// We currently have no way of determining a canonical module, so builtins is better
|
||||
// than using whatever calls init first.
|
||||
assert_eq!(module, "builtins");
|
||||
// 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
|
||||
// than using whatever calls init first.
|
||||
assert_eq!(module, "builtins");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -191,11 +189,11 @@ impl ClassWithObjectField {
|
|||
|
||||
#[test]
|
||||
fn class_with_object_field() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let ty = py.get_type::<ClassWithObjectField>();
|
||||
py_assert!(py, ty, "ty(5).value == 5");
|
||||
py_assert!(py, ty, "ty(None).value == None");
|
||||
Python::with_gil(|py| {
|
||||
let ty = py.get_type::<ClassWithObjectField>();
|
||||
py_assert!(py, ty, "ty(5).value == 5");
|
||||
py_assert!(py, ty, "ty(None).value == None");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(unsendable, subclass)]
|
||||
|
@ -355,46 +353,46 @@ struct DunderDictSupport {
|
|||
#[test]
|
||||
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
|
||||
fn dunder_dict_support() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
DunderDictSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
DunderDictSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
r#"
|
||||
inst.a = 1
|
||||
assert inst.a == 1
|
||||
"#
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Accessing inst.__dict__ only supported in limited API from Python 3.10
|
||||
#[test]
|
||||
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]
|
||||
fn access_dunder_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
DunderDictSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
DunderDictSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
r#"
|
||||
inst.a = 1
|
||||
assert inst.__dict__ == {'a': 1}
|
||||
"#
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// If the base class has dict support, child class also has dict
|
||||
|
@ -406,26 +404,26 @@ struct InheritDict {
|
|||
#[test]
|
||||
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
|
||||
fn inherited_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
(
|
||||
InheritDict { _value: 0 },
|
||||
DunderDictSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
(
|
||||
InheritDict { _value: 0 },
|
||||
DunderDictSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
r#"
|
||||
inst.a = 1
|
||||
assert inst.a == 1
|
||||
"#
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(weakref, dict)]
|
||||
|
@ -437,20 +435,20 @@ struct WeakRefDunderDictSupport {
|
|||
#[test]
|
||||
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
|
||||
fn weakref_dunder_dict_support() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
WeakRefDunderDictSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
WeakRefDunderDictSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(weakref, subclass)]
|
||||
|
@ -461,20 +459,20 @@ struct WeakRefSupport {
|
|||
#[test]
|
||||
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
|
||||
fn weakref_support() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
WeakRefSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"import weakref; assert weakref.ref(inst)() is inst"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
WeakRefSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"import weakref; assert weakref.ref(inst)() is inst"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// If the base class has weakref support, child class also has weakref.
|
||||
|
@ -486,21 +484,21 @@ struct InheritWeakRef {
|
|||
#[test]
|
||||
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_9)), ignore)]
|
||||
fn inherited_weakref() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
(
|
||||
InheritWeakRef { _value: 0 },
|
||||
WeakRefSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"import weakref; assert weakref.ref(inst)() is inst"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
(
|
||||
InheritWeakRef { _value: 0 },
|
||||
WeakRefSupport {
|
||||
_pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF",
|
||||
},
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"import weakref; assert weakref.ref(inst)() is inst"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,20 +16,19 @@ struct Cloneable {
|
|||
fn test_cloneable_pyclass() {
|
||||
let c = Cloneable { x: 10 };
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let py_c = Py::new(py, c.clone()).unwrap().to_object(py);
|
||||
|
||||
let py_c = Py::new(py, c.clone()).unwrap().to_object(py);
|
||||
|
||||
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);
|
||||
// Drops PyRef before taking PyRefMut
|
||||
}
|
||||
let mrc: PyRefMut<'_, Cloneable> = py_c.extract(py).unwrap();
|
||||
assert_eq!(&c, &*mrc);
|
||||
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);
|
||||
// Drops PyRef before taking PyRefMut
|
||||
}
|
||||
let mrc: PyRefMut<'_, Cloneable> = py_c.extract(py).unwrap();
|
||||
assert_eq!(&c, &*mrc);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(subclass)]
|
||||
|
@ -63,103 +62,98 @@ struct PolymorphicContainer {
|
|||
|
||||
#[test]
|
||||
fn test_polymorphic_container_stores_base_class() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let p = PyCell::new(
|
||||
py,
|
||||
PolymorphicContainer {
|
||||
inner: Py::new(py, BaseClass::default()).unwrap(),
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
.to_object(py);
|
||||
|
||||
let p = PyCell::new(
|
||||
py,
|
||||
PolymorphicContainer {
|
||||
inner: Py::new(py, BaseClass::default()).unwrap(),
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
.to_object(py);
|
||||
|
||||
py_assert!(py, p, "p.inner.foo() == 'BaseClass'");
|
||||
py_assert!(py, p, "p.inner.foo() == 'BaseClass'");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_polymorphic_container_stores_sub_class() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let p = PyCell::new(
|
||||
py,
|
||||
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(),
|
||||
Python::with_gil(|py| {
|
||||
let p = PyCell::new(
|
||||
py,
|
||||
PolymorphicContainer {
|
||||
inner: Py::new(py, BaseClass::default()).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]
|
||||
fn test_polymorphic_container_does_not_accept_other_types() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let p = PyCell::new(
|
||||
py,
|
||||
PolymorphicContainer {
|
||||
inner: Py::new(py, BaseClass::default()).unwrap(),
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
.to_object(py);
|
||||
|
||||
let p = PyCell::new(
|
||||
py,
|
||||
PolymorphicContainer {
|
||||
inner: Py::new(py, BaseClass::default()).unwrap(),
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
.to_object(py);
|
||||
let setattr = |value: PyObject| p.as_ref(py).setattr("inner", value);
|
||||
|
||||
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, 2i32).into_py(py)).is_err());
|
||||
assert!(setattr(1i32.into_py(py)).is_err());
|
||||
assert!(setattr(py.None()).is_err());
|
||||
assert!(setattr((1i32, 2i32).into_py(py)).is_err());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pyref_as_base() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let cell = PyCell::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap();
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
// Repeat for PyRef
|
||||
let sub: PyRef<'_, SubClass> = cell.borrow();
|
||||
let base: PyRef<'_, BaseClass> = sub.into_super();
|
||||
assert_eq!(999, base.value);
|
||||
// Repeat for PyRef
|
||||
let sub: PyRef<'_, SubClass> = cell.borrow();
|
||||
let base: PyRef<'_, BaseClass> = sub.into_super();
|
||||
assert_eq!(999, base.value);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pycell_deref() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let cell = PyCell::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap();
|
||||
|
||||
let cell = PyCell::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap();
|
||||
|
||||
// Should be able to deref as PyAny
|
||||
assert_eq!(
|
||||
cell.call_method0("foo")
|
||||
.and_then(PyAny::extract::<&str>)
|
||||
.unwrap(),
|
||||
"SubClass"
|
||||
);
|
||||
// Should be able to deref as PyAny
|
||||
assert_eq!(
|
||||
cell.call_method0("foo")
|
||||
.and_then(PyAny::extract::<&str>)
|
||||
.unwrap(),
|
||||
"SubClass"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,14 +16,14 @@ impl EmptyClassWithNew {
|
|||
|
||||
#[test]
|
||||
fn empty_class_with_new() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<EmptyClassWithNew>();
|
||||
assert!(typeobj
|
||||
.call((), None)
|
||||
.unwrap()
|
||||
.cast_as::<PyCell<EmptyClassWithNew>>()
|
||||
.is_ok());
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<EmptyClassWithNew>();
|
||||
assert!(typeobj
|
||||
.call((), None)
|
||||
.unwrap()
|
||||
.cast_as::<PyCell<EmptyClassWithNew>>()
|
||||
.is_ok());
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -87,13 +87,13 @@ impl NewWithOneArg {
|
|||
|
||||
#[test]
|
||||
fn new_with_one_arg() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<NewWithOneArg>();
|
||||
let wrp = typeobj.call((42,), None).unwrap();
|
||||
let obj = wrp.cast_as::<PyCell<NewWithOneArg>>().unwrap();
|
||||
let obj_ref = obj.borrow();
|
||||
assert_eq!(obj_ref._data, 42);
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<NewWithOneArg>();
|
||||
let wrp = typeobj.call((42,), None).unwrap();
|
||||
let obj = wrp.cast_as::<PyCell<NewWithOneArg>>().unwrap();
|
||||
let obj_ref = obj.borrow();
|
||||
assert_eq!(obj_ref._data, 42);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -115,17 +115,17 @@ impl NewWithTwoArgs {
|
|||
|
||||
#[test]
|
||||
fn new_with_two_args() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<NewWithTwoArgs>();
|
||||
let wrp = typeobj
|
||||
.call((10, 20), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
let obj = wrp.cast_as::<PyCell<NewWithTwoArgs>>().unwrap();
|
||||
let obj_ref = obj.borrow();
|
||||
assert_eq!(obj_ref._data1, 10);
|
||||
assert_eq!(obj_ref._data2, 20);
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<NewWithTwoArgs>();
|
||||
let wrp = typeobj
|
||||
.call((10, 20), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
let obj = wrp.cast_as::<PyCell<NewWithTwoArgs>>().unwrap();
|
||||
let obj_ref = obj.borrow();
|
||||
assert_eq!(obj_ref._data1, 10);
|
||||
assert_eq!(obj_ref._data2, 20);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(subclass)]
|
||||
|
@ -146,11 +146,10 @@ impl SuperClass {
|
|||
/// See https://github.com/PyO3/pyo3/issues/947 for the corresponding bug.
|
||||
#[test]
|
||||
fn subclass_new() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let super_cls = py.get_type::<SuperClass>();
|
||||
let source = pyo3::indoc::indoc!(
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let super_cls = py.get_type::<SuperClass>();
|
||||
let source = pyo3::indoc::indoc!(
|
||||
r#"
|
||||
class Class(SuperClass):
|
||||
def __new__(cls):
|
||||
return super().__new__(cls) # This should return an instance of Class
|
||||
|
@ -161,12 +160,13 @@ class Class(SuperClass):
|
|||
c = Class()
|
||||
assert c.from_rust is False
|
||||
"#
|
||||
);
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("SuperClass", super_cls).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
);
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("SuperClass", super_cls).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -191,9 +191,9 @@ impl NewWithCustomError {
|
|||
|
||||
#[test]
|
||||
fn new_with_custom_error() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<NewWithCustomError>();
|
||||
let err = typeobj.call0().unwrap_err();
|
||||
assert_eq!(err.to_string(), "ValueError: custom error");
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<NewWithCustomError>();
|
||||
let err = typeobj.call0().unwrap_err();
|
||||
assert_eq!(err.to_string(), "ValueError: custom error");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -55,52 +55,52 @@ macro_rules! assert_check_only {
|
|||
|
||||
#[test]
|
||||
fn test_date_check() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "date", "2018, 1, 1").unwrap();
|
||||
unsafe { PyDateTime_IMPORT() }
|
||||
assert_check_exact!(PyDate_Check, PyDate_CheckExact, obj);
|
||||
assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_obj);
|
||||
assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_sub_obj);
|
||||
Python::with_gil(|py| {
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "date", "2018, 1, 1").unwrap();
|
||||
unsafe { PyDateTime_IMPORT() }
|
||||
assert_check_exact!(PyDate_Check, PyDate_CheckExact, obj);
|
||||
assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_obj);
|
||||
assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_sub_obj);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_time_check() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "time", "12, 30, 15").unwrap();
|
||||
unsafe { PyDateTime_IMPORT() }
|
||||
Python::with_gil(|py| {
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "time", "12, 30, 15").unwrap();
|
||||
unsafe { PyDateTime_IMPORT() }
|
||||
|
||||
assert_check_exact!(PyTime_Check, PyTime_CheckExact, obj);
|
||||
assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_obj);
|
||||
assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_sub_obj);
|
||||
assert_check_exact!(PyTime_Check, PyTime_CheckExact, obj);
|
||||
assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_obj);
|
||||
assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_sub_obj);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_check() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "datetime", "2018, 1, 1, 13, 30, 15")
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
unsafe { PyDateTime_IMPORT() }
|
||||
Python::with_gil(|py| {
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "datetime", "2018, 1, 1, 13, 30, 15")
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
unsafe { PyDateTime_IMPORT() }
|
||||
|
||||
assert_check_only!(PyDate_Check, PyDate_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_sub_obj);
|
||||
assert_check_only!(PyDate_Check, PyDate_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_sub_obj);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delta_check() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "timedelta", "1, -3").unwrap();
|
||||
unsafe { PyDateTime_IMPORT() }
|
||||
Python::with_gil(|py| {
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "timedelta", "1, -3").unwrap();
|
||||
unsafe { PyDateTime_IMPORT() }
|
||||
|
||||
assert_check_exact!(PyDelta_Check, PyDelta_CheckExact, obj);
|
||||
assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_obj);
|
||||
assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_sub_obj);
|
||||
assert_check_exact!(PyDelta_Check, PyDelta_CheckExact, obj);
|
||||
assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_obj);
|
||||
assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_sub_obj);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -108,20 +108,20 @@ fn test_datetime_utc() {
|
|||
use assert_approx_eq::assert_approx_eq;
|
||||
use pyo3::types::PyDateTime;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let utc = timezone_utc(py);
|
||||
Python::with_gil(|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
|
||||
.eval("dt.utcoffset().total_seconds()", None, Some(locals))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap();
|
||||
assert_approx_eq!(offset, 0f32);
|
||||
let offset: f32 = py
|
||||
.eval("dt.utcoffset().total_seconds()", None, Some(locals))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap();
|
||||
assert_approx_eq!(offset, 0f32);
|
||||
});
|
||||
}
|
||||
|
||||
static INVALID_DATES: &[(i32, u8, u8)] = &[
|
||||
|
@ -143,26 +143,26 @@ static INVALID_TIMES: &[(u8, u8, u8, u32)] =
|
|||
fn test_pydate_out_of_bounds() {
|
||||
use pyo3::types::PyDate;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
for val in INVALID_DATES {
|
||||
let (year, month, day) = val;
|
||||
let dt = PyDate::new(py, *year, *month, *day);
|
||||
dt.unwrap_err();
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
for val in INVALID_DATES {
|
||||
let (year, month, day) = val;
|
||||
let dt = PyDate::new(py, *year, *month, *day);
|
||||
dt.unwrap_err();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pytime_out_of_bounds() {
|
||||
use pyo3::types::PyTime;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
for val in INVALID_TIMES {
|
||||
let (hour, minute, second, microsecond) = val;
|
||||
let dt = PyTime::new(py, *hour, *minute, *second, *microsecond, None);
|
||||
dt.unwrap_err();
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
for val in INVALID_TIMES {
|
||||
let (hour, minute, second, microsecond) = val;
|
||||
let dt = PyTime::new(py, *hour, *minute, *second, *microsecond, None);
|
||||
dt.unwrap_err();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -170,31 +170,31 @@ fn test_pydatetime_out_of_bounds() {
|
|||
use pyo3::types::PyDateTime;
|
||||
use std::iter;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let valid_time = (0, 0, 0, 0);
|
||||
let valid_date = (2018, 1, 1);
|
||||
Python::with_gil(|py| {
|
||||
let valid_time = (0, 0, 0, 0);
|
||||
let valid_date = (2018, 1, 1);
|
||||
|
||||
let invalid_dates = INVALID_DATES.iter().zip(iter::repeat(&valid_time));
|
||||
let invalid_times = iter::repeat(&valid_date).zip(INVALID_TIMES.iter());
|
||||
let invalid_dates = INVALID_DATES.iter().zip(iter::repeat(&valid_time));
|
||||
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 {
|
||||
let (date, time) = val;
|
||||
let (year, month, day) = date;
|
||||
let (hour, minute, second, microsecond) = time;
|
||||
let dt = PyDateTime::new(
|
||||
py,
|
||||
*year,
|
||||
*month,
|
||||
*day,
|
||||
*hour,
|
||||
*minute,
|
||||
*second,
|
||||
*microsecond,
|
||||
None,
|
||||
);
|
||||
dt.unwrap_err();
|
||||
}
|
||||
for val in vals {
|
||||
let (date, time) = val;
|
||||
let (year, month, day) = date;
|
||||
let (hour, minute, second, microsecond) = time;
|
||||
let dt = PyDateTime::new(
|
||||
py,
|
||||
*year,
|
||||
*month,
|
||||
*day,
|
||||
*hour,
|
||||
*minute,
|
||||
*second,
|
||||
*microsecond,
|
||||
None,
|
||||
);
|
||||
dt.unwrap_err();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@ use pyo3::types::IntoPyDict;
|
|||
#[test]
|
||||
#[cfg_attr(target_arch = "wasm32", ignore)] // Not sure why this fails.
|
||||
fn iter_dict_nosegv() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
const LEN: usize = 10_000_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
let mut sum = 0;
|
||||
for (k, _v) in dict.iter() {
|
||||
let i: u64 = k.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
assert_eq!(sum, 49_999_995_000_000);
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 10_000_000;
|
||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
||||
let mut sum = 0;
|
||||
for (k, _v) in dict.iter() {
|
||||
let i: u64 = k.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
assert_eq!(sum, 49_999_995_000_000);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -28,12 +28,12 @@ fn return_enum() -> MyEnum {
|
|||
|
||||
#[test]
|
||||
fn test_return_enum() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let f = wrap_pyfunction!(return_enum)(py).unwrap();
|
||||
let mynum = py.get_type::<MyEnum>();
|
||||
Python::with_gil(|py| {
|
||||
let f = wrap_pyfunction!(return_enum)(py).unwrap();
|
||||
let mynum = py.get_type::<MyEnum>();
|
||||
|
||||
py_run!(py, f mynum, "assert f() == mynum.Variant")
|
||||
py_run!(py, f mynum, "assert f() == mynum.Variant")
|
||||
});
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
|
|
@ -20,20 +20,20 @@ fn fail_to_open_file() -> PyResult<()> {
|
|||
#[cfg_attr(target_arch = "wasm32", ignore)] // Not sure why this fails.
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn test_filenotfounderror() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let fail_to_open_file = wrap_pyfunction!(fail_to_open_file)(py).unwrap();
|
||||
Python::with_gil(|py| {
|
||||
let fail_to_open_file = wrap_pyfunction!(fail_to_open_file)(py).unwrap();
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
fail_to_open_file,
|
||||
r#"
|
||||
py_run!(
|
||||
py,
|
||||
fail_to_open_file,
|
||||
r#"
|
||||
try:
|
||||
fail_to_open_file()
|
||||
except FileNotFoundError as e:
|
||||
assert str(e) == "No such file or directory (os error 2)"
|
||||
"#
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -65,20 +65,21 @@ fn call_fail_with_custom_error() -> PyResult<()> {
|
|||
|
||||
#[test]
|
||||
fn test_custom_error() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let call_fail_with_custom_error = wrap_pyfunction!(call_fail_with_custom_error)(py).unwrap();
|
||||
Python::with_gil(|py| {
|
||||
let call_fail_with_custom_error =
|
||||
wrap_pyfunction!(call_fail_with_custom_error)(py).unwrap();
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
call_fail_with_custom_error,
|
||||
r#"
|
||||
py_run!(
|
||||
py,
|
||||
call_fail_with_custom_error,
|
||||
r#"
|
||||
try:
|
||||
call_fail_with_custom_error()
|
||||
except OSError as e:
|
||||
assert str(e) == "Oh no!"
|
||||
"#
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
112
tests/test_gc.rs
112
tests/test_gc.rs
|
@ -15,27 +15,21 @@ struct ClassWithFreelist {}
|
|||
|
||||
#[test]
|
||||
fn class_with_freelist() {
|
||||
let ptr;
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let ptr = Python::with_gil(|py| {
|
||||
let inst = Py::new(py, ClassWithFreelist {}).unwrap();
|
||||
let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap();
|
||||
ptr = inst.as_ptr();
|
||||
let ptr = inst.as_ptr();
|
||||
drop(inst);
|
||||
}
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
ptr
|
||||
});
|
||||
|
||||
Python::with_gil(|py| {
|
||||
let inst3 = Py::new(py, ClassWithFreelist {}).unwrap();
|
||||
assert_eq!(ptr, inst3.as_ptr());
|
||||
|
||||
let inst4 = Py::new(py, ClassWithFreelist {}).unwrap();
|
||||
assert_ne!(ptr, inst4.as_ptr())
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
struct TestDropCall {
|
||||
|
@ -60,9 +54,7 @@ fn data_is_dropped() {
|
|||
let drop_called1 = Arc::new(AtomicBool::new(false));
|
||||
let drop_called2 = Arc::new(AtomicBool::new(false));
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let data_is_dropped = DataIsDropped {
|
||||
member1: TestDropCall {
|
||||
drop_called: Arc::clone(&drop_called1),
|
||||
|
@ -75,7 +67,7 @@ fn data_is_dropped() {
|
|||
assert!(!drop_called1.load(Ordering::Relaxed));
|
||||
assert!(!drop_called2.load(Ordering::Relaxed));
|
||||
drop(inst);
|
||||
}
|
||||
});
|
||||
|
||||
assert!(drop_called1.load(Ordering::Relaxed));
|
||||
assert!(drop_called2.load(Ordering::Relaxed));
|
||||
|
@ -95,8 +87,9 @@ impl GcIntegration {
|
|||
}
|
||||
|
||||
fn __clear__(&mut self) {
|
||||
let gil = Python::acquire_gil();
|
||||
self.self_ref = gil.python().None();
|
||||
Python::with_gil(|py| {
|
||||
self.self_ref = py.None();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,9 +97,7 @@ impl GcIntegration {
|
|||
fn gc_integration() {
|
||||
let drop_called = Arc::new(AtomicBool::new(false));
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
GcIntegration {
|
||||
|
@ -122,12 +113,12 @@ fn gc_integration() {
|
|||
borrow.self_ref = inst.to_object(py);
|
||||
|
||||
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
||||
}
|
||||
});
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
py.run("import gc; gc.collect()", None, None).unwrap();
|
||||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
Python::with_gil(|py| {
|
||||
py.run("import gc; gc.collect()", None, None).unwrap();
|
||||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(subclass)]
|
||||
|
@ -180,9 +171,7 @@ fn inheritance_with_new_methods_with_drop() {
|
|||
let drop_called1 = Arc::new(AtomicBool::new(false));
|
||||
let drop_called2 = Arc::new(AtomicBool::new(false));
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let _typebase = py.get_type::<BaseClassWithDrop>();
|
||||
let typeobj = py.get_type::<SubClassWithDrop>();
|
||||
let inst = typeobj.call((), None).unwrap();
|
||||
|
@ -192,7 +181,7 @@ fn inheritance_with_new_methods_with_drop() {
|
|||
obj_ref_mut.data = Some(Arc::clone(&drop_called1));
|
||||
let base: &mut BaseClassWithDrop = obj_ref_mut.as_mut();
|
||||
base.data = Some(Arc::clone(&drop_called2));
|
||||
}
|
||||
});
|
||||
|
||||
assert!(drop_called1.load(Ordering::Relaxed));
|
||||
assert!(drop_called2.load(Ordering::Relaxed));
|
||||
|
@ -228,40 +217,39 @@ unsafe fn get_type_traverse(tp: *mut pyo3::ffi::PyTypeObject) -> Option<pyo3::ff
|
|||
|
||||
#[test]
|
||||
fn gc_during_borrow() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
unsafe {
|
||||
// declare a dummy visitor function
|
||||
extern "C" fn novisit(
|
||||
_object: *mut pyo3::ffi::PyObject,
|
||||
_arg: *mut core::ffi::c_void,
|
||||
) -> std::os::raw::c_int {
|
||||
0
|
||||
}
|
||||
|
||||
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
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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]
|
||||
|
|
|
@ -17,27 +17,21 @@ struct ClassWithFreelist {}
|
|||
|
||||
#[test]
|
||||
fn class_with_freelist() {
|
||||
let ptr;
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let ptr = Python::with_gil(|py| {
|
||||
let inst = Py::new(py, ClassWithFreelist {}).unwrap();
|
||||
let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap();
|
||||
ptr = inst.as_ptr();
|
||||
let ptr = inst.as_ptr();
|
||||
drop(inst);
|
||||
}
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
ptr
|
||||
});
|
||||
|
||||
Python::with_gil(|py| {
|
||||
let inst3 = Py::new(py, ClassWithFreelist {}).unwrap();
|
||||
assert_eq!(ptr, inst3.as_ptr());
|
||||
|
||||
let inst4 = Py::new(py, ClassWithFreelist {}).unwrap();
|
||||
assert_ne!(ptr, inst4.as_ptr())
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
struct TestDropCall {
|
||||
|
@ -62,9 +56,7 @@ fn data_is_dropped() {
|
|||
let drop_called1 = Arc::new(AtomicBool::new(false));
|
||||
let drop_called2 = Arc::new(AtomicBool::new(false));
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let data_is_dropped = DataIsDropped {
|
||||
member1: TestDropCall {
|
||||
drop_called: Arc::clone(&drop_called1),
|
||||
|
@ -77,7 +69,7 @@ fn data_is_dropped() {
|
|||
assert!(!drop_called1.load(Ordering::Relaxed));
|
||||
assert!(!drop_called2.load(Ordering::Relaxed));
|
||||
drop(inst);
|
||||
}
|
||||
});
|
||||
|
||||
assert!(drop_called1.load(Ordering::Relaxed));
|
||||
assert!(drop_called2.load(Ordering::Relaxed));
|
||||
|
@ -97,8 +89,9 @@ impl PyGCProtocol for GcIntegration {
|
|||
}
|
||||
|
||||
fn __clear__(&mut self) {
|
||||
let gil = Python::acquire_gil();
|
||||
self.self_ref = gil.python().None();
|
||||
Python::with_gil(|py| {
|
||||
self.self_ref = py.None();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,9 +99,7 @@ impl PyGCProtocol for GcIntegration {
|
|||
fn gc_integration() {
|
||||
let drop_called = Arc::new(AtomicBool::new(false));
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(
|
||||
py,
|
||||
GcIntegration {
|
||||
|
@ -122,12 +113,12 @@ fn gc_integration() {
|
|||
|
||||
let mut borrow = inst.borrow_mut();
|
||||
borrow.self_ref = inst.to_object(py);
|
||||
}
|
||||
});
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
py.run("import gc; gc.collect()", None, None).unwrap();
|
||||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
Python::with_gil(|py| {
|
||||
py.run("import gc; gc.collect()", None, None).unwrap();
|
||||
assert!(drop_called.load(Ordering::Relaxed));
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -143,10 +134,10 @@ impl PyGCProtocol for GcIntegration2 {
|
|||
|
||||
#[test]
|
||||
fn gc_integration2() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(py, GcIntegration2 {}).unwrap();
|
||||
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(py, GcIntegration2 {}).unwrap();
|
||||
py_run!(py, inst, "import gc; assert inst in gc.get_objects()");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(subclass)]
|
||||
|
@ -199,9 +190,7 @@ fn inheritance_with_new_methods_with_drop() {
|
|||
let drop_called1 = Arc::new(AtomicBool::new(false));
|
||||
let drop_called2 = Arc::new(AtomicBool::new(false));
|
||||
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let _typebase = py.get_type::<BaseClassWithDrop>();
|
||||
let typeobj = py.get_type::<SubClassWithDrop>();
|
||||
let inst = typeobj.call((), None).unwrap();
|
||||
|
@ -211,7 +200,7 @@ fn inheritance_with_new_methods_with_drop() {
|
|||
obj_ref_mut.data = Some(Arc::clone(&drop_called1));
|
||||
let base: &mut BaseClassWithDrop = obj_ref_mut.as_mut();
|
||||
base.data = Some(Arc::clone(&drop_called2));
|
||||
}
|
||||
});
|
||||
|
||||
assert!(drop_called1.load(Ordering::Relaxed));
|
||||
assert!(drop_called2.load(Ordering::Relaxed));
|
||||
|
@ -245,38 +234,37 @@ unsafe fn get_type_traverse(tp: *mut pyo3::ffi::PyTypeObject) -> Option<pyo3::ff
|
|||
|
||||
#[test]
|
||||
fn gc_during_borrow() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
unsafe {
|
||||
// declare a dummy visitor function
|
||||
extern "C" fn novisit(
|
||||
_object: *mut pyo3::ffi::PyObject,
|
||||
_arg: *mut core::ffi::c_void,
|
||||
) -> std::os::raw::c_int {
|
||||
0
|
||||
}
|
||||
|
||||
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
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -46,25 +46,24 @@ impl ClassWithProperties {
|
|||
|
||||
#[test]
|
||||
fn class_with_properties() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(py, ClassWithProperties { num: 10 }).unwrap();
|
||||
|
||||
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_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_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");
|
||||
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]");
|
||||
|
||||
let d = [("C", py.get_type::<ClassWithProperties>())].into_py_dict(py);
|
||||
py_assert!(py, *d, "C.DATA.__doc__ == 'a getter for data'");
|
||||
let d = [("C", py.get_type::<ClassWithProperties>())].into_py_dict(py);
|
||||
py_assert!(py, *d, "C.DATA.__doc__ == 'a getter for data'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -84,25 +83,24 @@ impl GetterSetter {
|
|||
|
||||
#[test]
|
||||
fn getter_setter_autogen() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(
|
||||
py,
|
||||
GetterSetter {
|
||||
num: 10,
|
||||
text: "Hello".to_string(),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let inst = Py::new(
|
||||
py,
|
||||
GetterSetter {
|
||||
num: 10,
|
||||
text: "Hello".to_string(),
|
||||
},
|
||||
)
|
||||
.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'"
|
||||
);
|
||||
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]
|
||||
|
@ -126,13 +124,12 @@ impl RefGetterSetter {
|
|||
#[test]
|
||||
fn ref_getter_setter() {
|
||||
// Regression test for #837
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(py, RefGetterSetter { num: 10 }).unwrap();
|
||||
|
||||
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]
|
||||
|
@ -153,12 +150,11 @@ impl TupleClassGetterSetter {
|
|||
|
||||
#[test]
|
||||
fn tuple_struct_getter_setter() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(py, TupleClassGetterSetter(10)).unwrap();
|
||||
|
||||
let inst = Py::new(py, TupleClassGetterSetter(10)).unwrap();
|
||||
|
||||
py_assert!(py, inst, "inst.num == 10");
|
||||
py_run!(py, inst, "inst.num = 20");
|
||||
py_assert!(py, inst, "inst.num == 20");
|
||||
py_assert!(py, inst, "inst.num == 10");
|
||||
py_run!(py, inst, "inst.num = 20");
|
||||
py_assert!(py, inst, "inst.num == 20");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,17 +18,17 @@ struct SubclassAble {}
|
|||
|
||||
#[test]
|
||||
fn subclass() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let d = [("SubclassAble", py.get_type::<SubclassAble>())].into_py_dict(py);
|
||||
Python::with_gil(|py| {
|
||||
let d = [("SubclassAble", py.get_type::<SubclassAble>())].into_py_dict(py);
|
||||
|
||||
py.run(
|
||||
"class A(SubclassAble): pass\nassert issubclass(A, SubclassAble)",
|
||||
None,
|
||||
Some(d),
|
||||
)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
py.run(
|
||||
"class A(SubclassAble): pass\nassert issubclass(A, SubclassAble)",
|
||||
None,
|
||||
Some(d),
|
||||
)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
|
@ -70,55 +70,54 @@ impl SubClass {
|
|||
|
||||
#[test]
|
||||
fn inheritance_with_new_methods() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<SubClass>();
|
||||
let inst = typeobj.call((), None).unwrap();
|
||||
py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5");
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<SubClass>();
|
||||
let inst = typeobj.call((), None).unwrap();
|
||||
py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_base_and_sub_methods() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let obj = PyCell::new(py, SubClass::new()).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
obj,
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let obj = PyCell::new(py, SubClass::new()).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
obj,
|
||||
r#"
|
||||
assert obj.base_method(10) == 100
|
||||
assert obj.sub_method(10) == 50
|
||||
"#
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mutation_fails() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let obj = PyCell::new(py, SubClass::new()).unwrap();
|
||||
let global = Some([("obj", obj)].into_py_dict(py));
|
||||
let e = py
|
||||
.run("obj.base_set(lambda: obj.sub_set_and_ret(1))", global, None)
|
||||
.unwrap_err();
|
||||
assert_eq!(&e.to_string(), "RuntimeError: Already borrowed")
|
||||
Python::with_gil(|py| {
|
||||
let obj = PyCell::new(py, SubClass::new()).unwrap();
|
||||
let global = Some([("obj", obj)].into_py_dict(py));
|
||||
let e = py
|
||||
.run("obj.base_set(lambda: obj.sub_set_and_ret(1))", global, None)
|
||||
.unwrap_err();
|
||||
assert_eq!(&e.to_string(), "RuntimeError: Already borrowed");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_subclass_and_is_instance() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let sub_ty = SubClass::type_object(py);
|
||||
let base_ty = BaseClass::type_object(py);
|
||||
assert!(sub_ty.is_subclass_of::<BaseClass>().unwrap());
|
||||
assert!(sub_ty.is_subclass(base_ty).unwrap());
|
||||
|
||||
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 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());
|
||||
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)]
|
||||
|
@ -150,13 +149,12 @@ impl SubClass2 {
|
|||
|
||||
#[test]
|
||||
fn handle_result_in_new() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let subclass = py.get_type::<SubClass2>();
|
||||
py_run!(
|
||||
py,
|
||||
subclass,
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let subclass = py.get_type::<SubClass2>();
|
||||
py_run!(
|
||||
py,
|
||||
subclass,
|
||||
r#"
|
||||
try:
|
||||
subclass(-10)
|
||||
assert Fals
|
||||
|
@ -165,7 +163,8 @@ except ValueError as e:
|
|||
except Exception as e:
|
||||
raise e
|
||||
"#
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Subclassing builtin types is not allowed in the LIMITED API.
|
||||
|
@ -197,14 +196,14 @@ mod inheriting_native_type {
|
|||
}
|
||||
}
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let set_sub = pyo3::PyCell::new(py, SetWithName::new()).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
set_sub,
|
||||
r#"set_sub.add(10); assert list(set_sub) == [10]; assert set_sub.name == "Hello :)""#
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let set_sub = pyo3::PyCell::new(py, SetWithName::new()).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
set_sub,
|
||||
r#"set_sub.add(10); assert list(set_sub) == [10]; assert set_sub.name == "Hello :)""#
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(extends=PyDict)]
|
||||
|
@ -224,14 +223,14 @@ mod inheriting_native_type {
|
|||
|
||||
#[test]
|
||||
fn inherit_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let dict_sub = pyo3::PyCell::new(py, DictWithName::new()).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
dict_sub,
|
||||
r#"dict_sub[0] = 1; assert dict_sub[0] == 1; assert dict_sub.name == "Hello :)""#
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let dict_sub = pyo3::PyCell::new(py, DictWithName::new()).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
dict_sub,
|
||||
r#"dict_sub[0] = 1; assert dict_sub[0] == 1; assert dict_sub.name == "Hello :)""#
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -75,42 +75,41 @@ fn map_dict(py: Python<'_>) -> &pyo3::types::PyDict {
|
|||
|
||||
#[test]
|
||||
fn test_getitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let d = map_dict(py);
|
||||
Python::with_gil(|py| {
|
||||
let d = map_dict(py);
|
||||
|
||||
py_assert!(py, *d, "m['1'] == 0");
|
||||
py_assert!(py, *d, "m['2'] == 1");
|
||||
py_assert!(py, *d, "m['3'] == 2");
|
||||
py_expect_exception!(py, *d, "print(m['4'])", PyKeyError);
|
||||
py_assert!(py, *d, "m['1'] == 0");
|
||||
py_assert!(py, *d, "m['2'] == 1");
|
||||
py_assert!(py, *d, "m['3'] == 2");
|
||||
py_expect_exception!(py, *d, "print(m['4'])", PyKeyError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_setitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let d = map_dict(py);
|
||||
Python::with_gil(|py| {
|
||||
let d = map_dict(py);
|
||||
|
||||
py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4");
|
||||
py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0");
|
||||
py_assert!(py, *d, "len(m) == 4");
|
||||
py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError);
|
||||
py_expect_exception!(py, *d, "m[0] = -1", PyTypeError);
|
||||
py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4");
|
||||
py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0");
|
||||
py_assert!(py, *d, "len(m) == 4");
|
||||
py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError);
|
||||
py_expect_exception!(py, *d, "m[0] = -1", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let d = map_dict(py);
|
||||
py_run!(
|
||||
py,
|
||||
*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);
|
||||
Python::with_gil(|py| {
|
||||
let d = map_dict(py);
|
||||
py_run!(
|
||||
py,
|
||||
*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);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -72,40 +72,39 @@ fn map_dict(py: Python<'_>) -> &pyo3::types::PyDict {
|
|||
|
||||
#[test]
|
||||
fn test_getitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let d = map_dict(py);
|
||||
Python::with_gil(|py| {
|
||||
let d = map_dict(py);
|
||||
|
||||
py_assert!(py, *d, "m['1'] == 0");
|
||||
py_assert!(py, *d, "m['2'] == 1");
|
||||
py_assert!(py, *d, "m['3'] == 2");
|
||||
py_expect_exception!(py, *d, "print(m['4'])", PyKeyError);
|
||||
py_assert!(py, *d, "m['1'] == 0");
|
||||
py_assert!(py, *d, "m['2'] == 1");
|
||||
py_assert!(py, *d, "m['3'] == 2");
|
||||
py_expect_exception!(py, *d, "print(m['4'])", PyKeyError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_setitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let d = map_dict(py);
|
||||
Python::with_gil(|py| {
|
||||
let d = map_dict(py);
|
||||
|
||||
py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4");
|
||||
py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0");
|
||||
py_assert!(py, *d, "len(m) == 4");
|
||||
py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError);
|
||||
py_expect_exception!(py, *d, "m[0] = -1", PyTypeError);
|
||||
py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4");
|
||||
py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0");
|
||||
py_assert!(py, *d, "len(m) == 4");
|
||||
py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError);
|
||||
py_expect_exception!(py, *d, "m[0] = -1", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let d = map_dict(py);
|
||||
py_run!(
|
||||
py,
|
||||
*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);
|
||||
Python::with_gil(|py| {
|
||||
let d = map_dict(py);
|
||||
py_run!(
|
||||
py,
|
||||
*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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -27,15 +27,14 @@ impl InstanceMethod {
|
|||
|
||||
#[test]
|
||||
fn instance_method() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let obj = PyCell::new(py, InstanceMethod { member: 42 }).unwrap();
|
||||
let obj_ref = obj.borrow();
|
||||
assert_eq!(obj_ref.method(), 42);
|
||||
py_assert!(py, obj, "obj.method() == 42");
|
||||
py_assert!(py, obj, "obj.add_other(obj) == 84");
|
||||
py_assert!(py, obj, "obj.method.__doc__ == 'Test method'");
|
||||
Python::with_gil(|py| {
|
||||
let obj = PyCell::new(py, InstanceMethod { member: 42 }).unwrap();
|
||||
let obj_ref = obj.borrow();
|
||||
assert_eq!(obj_ref.method(), 42);
|
||||
py_assert!(py, obj, "obj.method() == 42");
|
||||
py_assert!(py, obj, "obj.add_other(obj) == 84");
|
||||
py_assert!(py, obj, "obj.method.__doc__ == 'Test method'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -52,14 +51,13 @@ impl InstanceMethodWithArgs {
|
|||
|
||||
#[test]
|
||||
fn instance_method_with_args() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let obj = PyCell::new(py, InstanceMethodWithArgs { member: 7 }).unwrap();
|
||||
let obj_ref = obj.borrow();
|
||||
assert_eq!(obj_ref.method(6), 42);
|
||||
py_assert!(py, obj, "obj.method(3) == 21");
|
||||
py_assert!(py, obj, "obj.method(multiplier=6) == 42");
|
||||
Python::with_gil(|py| {
|
||||
let obj = PyCell::new(py, InstanceMethodWithArgs { member: 7 }).unwrap();
|
||||
let obj_ref = obj.borrow();
|
||||
assert_eq!(obj_ref.method(6), 42);
|
||||
py_assert!(py, obj, "obj.method(3) == 21");
|
||||
py_assert!(py, obj, "obj.method(multiplier=6) == 42");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -81,14 +79,13 @@ impl ClassMethod {
|
|||
|
||||
#[test]
|
||||
fn class_method() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let d = [("C", py.get_type::<ClassMethod>())].into_py_dict(py);
|
||||
py_assert!(py, *d, "C.method() == 'ClassMethod.method()!'");
|
||||
py_assert!(py, *d, "C().method() == 'ClassMethod.method()!'");
|
||||
py_assert!(py, *d, "C.method.__doc__ == 'Test class method.'");
|
||||
py_assert!(py, *d, "C().method.__doc__ == 'Test class method.'");
|
||||
Python::with_gil(|py| {
|
||||
let d = [("C", py.get_type::<ClassMethod>())].into_py_dict(py);
|
||||
py_assert!(py, *d, "C.method() == 'ClassMethod.method()!'");
|
||||
py_assert!(py, *d, "C().method() == 'ClassMethod.method()!'");
|
||||
py_assert!(py, *d, "C.method.__doc__ == 'Test class method.'");
|
||||
py_assert!(py, *d, "C().method.__doc__ == 'Test class method.'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -104,15 +101,14 @@ impl ClassMethodWithArgs {
|
|||
|
||||
#[test]
|
||||
fn class_method_with_args() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let d = [("C", py.get_type::<ClassMethodWithArgs>())].into_py_dict(py);
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"C.method('abc') == 'ClassMethodWithArgs.method(abc)'"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let d = [("C", py.get_type::<ClassMethodWithArgs>())].into_py_dict(py);
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"C.method('abc') == 'ClassMethodWithArgs.method(abc)'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -134,16 +130,15 @@ impl StaticMethod {
|
|||
|
||||
#[test]
|
||||
fn static_method() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
assert_eq!(StaticMethod::method(py), "StaticMethod.method()!");
|
||||
|
||||
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()!'");
|
||||
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.'");
|
||||
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.__doc__ == 'Test static method.'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -159,13 +154,12 @@ impl StaticMethodWithArgs {
|
|||
|
||||
#[test]
|
||||
fn static_method_with_args() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
assert_eq!(StaticMethodWithArgs::method(py, 1234), "0x4d2");
|
||||
|
||||
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]
|
||||
|
@ -305,315 +299,315 @@ impl MethArgs {
|
|||
|
||||
#[test]
|
||||
fn meth_args() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = Py::new(py, MethArgs {}).unwrap();
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(py, MethArgs {}).unwrap();
|
||||
|
||||
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_optional2() == None");
|
||||
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(100) == 100");
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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_default() == 10");
|
||||
py_run!(py, inst, "assert inst.get_default(100) == 100");
|
||||
py_run!(py, inst, "assert inst.get_kwarg() == 10");
|
||||
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_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(t=1,n=2) == [(), {'t': 1, 'n': 2}]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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_optional() == 10");
|
||||
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(100) == 100");
|
||||
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_optional_positional(1, 2, 3) == 2"
|
||||
);
|
||||
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(100) == 100");
|
||||
py_run!(py, inst, "assert inst.get_kwarg() == 10");
|
||||
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_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(t=1,n=2) == [(), {'t': 1, 'n': 2}]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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, 2, 3) == [1, (2, 3), None]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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_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(b=2)", PyTypeError);
|
||||
py_run!(py, inst, "assert inst.get_pos_arg_kw(1) == [1, (), None]");
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_arg_kw(1, 2, 3) == [1, (2, 3), None]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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_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(b=2)", PyTypeError);
|
||||
|
||||
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(a = 10, b = 11)", PyTypeError);
|
||||
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(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, b = 11) == 21"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_pos(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, b = 11) == 21"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_pos(a = 10, b = 11)",
|
||||
PyTypeError
|
||||
);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_pos_and_kw(10, 11) == 26"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_pos_and_kw(10, b = 11) == 26"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_pos_and_kw(10, 11, c = 0) == 21"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_pos_and_kw(10, b = 11, c = 0) == 21"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_pos_and_kw(a = 10, b = 11)",
|
||||
PyTypeError
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_pos_and_kw(10, 11) == 26"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_pos_and_kw(10, b = 11) == 26"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_pos_and_kw(10, 11, c = 0) == 21"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_pos_and_kw(10, b = 11, c = 0) == 21"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_pos_and_kw(a = 10, b = 11)",
|
||||
PyTypeError
|
||||
);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_kw_only(10, b = 11) == 21"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_kw_only(10, 11)",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_kw_only(a = 10, b = 11)",
|
||||
PyTypeError
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_kw_only(10, b = 11) == 21"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_kw_only(10, 11)",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_kw_only(a = 10, b = 11)",
|
||||
PyTypeError
|
||||
);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_kw_only_with_default(10) == 13"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_kw_only_with_default(10, b = 11) == 21"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_kw_only_with_default(10, 11)",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_kw_only_with_default(a = 10, b = 11)",
|
||||
PyTypeError
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_kw_only_with_default(10) == 13"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_and_kw_only_with_default(10, b = 11) == 21"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_kw_only_with_default(10, 11)",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_and_kw_only_with_default(a = 10, b = 11)",
|
||||
PyTypeError
|
||||
);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_all_arg_types_together(10, 10, c = 10) == 35"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_all_arg_types_together(10, 10, c = 10, d = 10) == 40"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_all_arg_types_together(10, b = 10, c = 10, d = 10) == 40"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_all_arg_types_together(10, 10, 10)",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_all_arg_types_together(a = 10, b = 10, c = 10)",
|
||||
PyTypeError
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_all_arg_types_together(10, 10, c = 10) == 35"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_all_arg_types_together(10, 10, c = 10, d = 10) == 40"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_all_arg_types_together(10, b = 10, c = 10, d = 10) == 40"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_all_arg_types_together(10, 10, 10)",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_all_arg_types_together(a = 10, b = 10, c = 10)",
|
||||
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) == 20"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_with_varargs(10, 10, 10, 10, 10) == 50"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_with_varargs(a = 10)",
|
||||
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) == 20"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_with_varargs(10, 10, 10, 10, 10) == 50"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_with_varargs(a = 10)",
|
||||
PyTypeError
|
||||
);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_with_kwargs(10) == [10, None]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_with_kwargs(10, b = 10) == [10, {'b': 10}]"
|
||||
);
|
||||
py_run!(
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_with_kwargs(10) == [10, None]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_only_with_kwargs(10, b = 10) == [10, {'b': 10}]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
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}]"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_with_kwargs(a = 10)",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_with_kwargs(a = 10, b = 10)",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_with_kwargs(a = 10)",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_pos_only_with_kwargs(a = 10, b = 10)",
|
||||
PyTypeError
|
||||
);
|
||||
|
||||
py_run!(py, inst, "assert inst.get_kwargs_only_with_defaults() == 5");
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_defaults(a = 8) == 11"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_defaults(b = 8) == 10"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_defaults(a = 1, b = 1) == 2"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_defaults(b = 1, a = 1) == 2"
|
||||
);
|
||||
py_run!(py, inst, "assert inst.get_kwargs_only_with_defaults() == 5");
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_defaults(a = 8) == 11"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_defaults(b = 8) == 10"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_defaults(a = 1, b = 1) == 2"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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(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(b = 1, a = 1) == 2");
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_some_default(a = 2, b = 1) == 3"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_some_default(b = 1) == 2"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_some_default(b = 1, a = 2) == 3"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_kwargs_only_with_some_default()",
|
||||
PyTypeError
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_some_default(a = 2, b = 1) == 3"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_some_default(b = 1) == 2"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_kwargs_only_with_some_default(b = 1, a = 2) == 3"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_kwargs_only_with_some_default()",
|
||||
PyTypeError
|
||||
);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_args_and_required_keyword(1, 2, a=3) == ((1, 2), 3)"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_args_and_required_keyword(a=1) == ((), 1)"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_args_and_required_keyword()",
|
||||
PyTypeError
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_args_and_required_keyword(1, 2, a=3) == ((1, 2), 3)"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_args_and_required_keyword(a=1) == ((), 1)"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
inst,
|
||||
"inst.get_args_and_required_keyword()",
|
||||
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, 2) == 6");
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_arg_kw_sep1(1, 2, c=13) == 16"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_arg_kw_sep1(a=1, b=2, c=13) == 16"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_arg_kw_sep1(b=2, c=13, a=1) == 16"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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_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, c=13) == 16"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_arg_kw_sep1(a=1, b=2, c=13) == 16"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"assert inst.get_pos_arg_kw_sep1(b=2, c=13, a=1) == 16"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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_run!(py, inst, "assert inst.get_pos_arg_kw_sep2(1) == 6");
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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_run!(py, inst, "assert inst.get_pos_arg_kw_sep2(1) == 6");
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"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_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_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_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]
|
||||
|
@ -638,20 +632,20 @@ impl MethDocs {
|
|||
|
||||
#[test]
|
||||
fn meth_doc() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
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.method.__doc__ == 'A method with \"documentation\" as well.'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"C.x.__doc__ == '`int`: a very \"important\" member of \\'this\\' instance.'"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let d = [("C", py.get_type::<MethDocs>())].into_py_dict(py);
|
||||
py_assert!(py, *d, "C.__doc__ == 'A class with \"documentation\".'");
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"C.method.__doc__ == 'A method with \"documentation\" as well.'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"C.x.__doc__ == '`int`: a very \"important\" member of \\'this\\' instance.'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -672,14 +666,14 @@ impl MethodWithLifeTime {
|
|||
|
||||
#[test]
|
||||
fn method_with_lifetime() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let obj = PyCell::new(py, MethodWithLifeTime {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
obj,
|
||||
"assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let obj = PyCell::new(py, MethodWithLifeTime {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
obj,
|
||||
"assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -720,35 +714,35 @@ impl MethodWithPyClassArg {
|
|||
|
||||
#[test]
|
||||
fn method_with_pyclassarg() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let obj1 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap();
|
||||
let obj2 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap();
|
||||
let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py);
|
||||
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.optional_add(); assert obj.value == 20");
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"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_pyref(obj2); assert obj2.value == 30"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"obj1.optional_inplace_add(); assert obj2.value == 30"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"obj1.optional_inplace_add(obj2); assert obj2.value == 40"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let obj1 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap();
|
||||
let obj2 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap();
|
||||
let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py);
|
||||
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.optional_add(); assert obj.value == 20");
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"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_pyref(obj2); assert obj2.value == 30"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"obj1.optional_inplace_add(); assert obj2.value == 30"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"obj1.optional_inplace_add(obj2); assert obj2.value == 40"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -783,23 +777,23 @@ impl CfgStruct {
|
|||
|
||||
#[test]
|
||||
fn test_cfg_attrs() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = Py::new(py, CfgStruct {}).unwrap();
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(py, CfgStruct {}).unwrap();
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
py_assert!(py, inst, "inst.unix_method() == 'unix'");
|
||||
py_assert!(py, inst, "not hasattr(inst, 'not_unix_method')");
|
||||
}
|
||||
#[cfg(unix)]
|
||||
{
|
||||
py_assert!(py, inst, "inst.unix_method() == 'unix'");
|
||||
py_assert!(py, inst, "not hasattr(inst, 'not_unix_method')");
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
py_assert!(py, inst, "not hasattr(inst, 'unix_method')");
|
||||
py_assert!(py, inst, "inst.not_unix_method() == 'not unix'");
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
py_assert!(py, inst, "not hasattr(inst, 'unix_method')");
|
||||
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]
|
||||
|
@ -825,10 +819,10 @@ impl FromSequence {
|
|||
|
||||
#[test]
|
||||
fn test_from_sequence() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<FromSequence>();
|
||||
py_assert!(py, typeobj, "typeobj(range(0, 4)).numbers == [0, 1, 2, 3]")
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<FromSequence>();
|
||||
py_assert!(py, typeobj, "typeobj(range(0, 4)).numbers == [0, 1, 2, 3]");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
|
|
@ -67,51 +67,50 @@ fn module_with_functions(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
|||
fn test_module_with_functions() {
|
||||
use pyo3::wrap_pymodule;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = [(
|
||||
"module_with_functions",
|
||||
wrap_pymodule!(module_with_functions)(py),
|
||||
)]
|
||||
.into_py_dict(py);
|
||||
|
||||
let d = [(
|
||||
"module_with_functions",
|
||||
wrap_pymodule!(module_with_functions)(py),
|
||||
)]
|
||||
.into_py_dict(py);
|
||||
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.__doc__ == 'This module is implemented in Rust.'"
|
||||
);
|
||||
py_assert!(py, *d, "module_with_functions.no_parameters() == 42");
|
||||
py_assert!(py, *d, "module_with_functions.foo == 'bar'");
|
||||
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.LocatedClass.__module__ == 'module'"
|
||||
);
|
||||
py_assert!(py, *d, "module_with_functions.double(3) == 6");
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.double.__doc__ == 'Doubles the given value'"
|
||||
);
|
||||
py_assert!(py, *d, "module_with_functions.also_double(3) == 6");
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.also_double.__doc__ == 'Doubles the given value'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.double_value(module_with_functions.ValueClass(1)) == 2"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.with_module() == 'module_with_functions'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.__doc__ == 'This module is implemented in Rust.'"
|
||||
);
|
||||
py_assert!(py, *d, "module_with_functions.no_parameters() == 42");
|
||||
py_assert!(py, *d, "module_with_functions.foo == 'bar'");
|
||||
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.LocatedClass.__module__ == 'module'"
|
||||
);
|
||||
py_assert!(py, *d, "module_with_functions.double(3) == 6");
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.double.__doc__ == 'Doubles the given value'"
|
||||
);
|
||||
py_assert!(py, *d, "module_with_functions.also_double(3) == 6");
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.also_double.__doc__ == 'Doubles the given value'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.double_value(module_with_functions.ValueClass(1)) == 2"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
*d,
|
||||
"module_with_functions.with_module() == 'module_with_functions'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pymodule]
|
||||
|
@ -125,39 +124,37 @@ fn some_name(_: Python<'_>, m: &PyModule) -> PyResult<()> {
|
|||
fn test_module_renaming() {
|
||||
use pyo3::wrap_pymodule;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = [("different_name", wrap_pymodule!(some_name)(py))].into_py_dict(py);
|
||||
|
||||
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]
|
||||
fn test_module_from_code() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let adder_mod = PyModule::from_code(
|
||||
py,
|
||||
"def add(a,b):\n\treturn a+b",
|
||||
"adder_mod.py",
|
||||
"adder_mod",
|
||||
)
|
||||
.expect("Module code should be loaded");
|
||||
|
||||
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 add_func = adder_mod
|
||||
.getattr("add")
|
||||
.expect("Add function should be in the module")
|
||||
.to_object(py);
|
||||
|
||||
let add_func = adder_mod
|
||||
.getattr("add")
|
||||
.expect("Add function should be in the module")
|
||||
.to_object(py);
|
||||
let ret_value: i32 = add_func
|
||||
.call1(py, (1, 2))
|
||||
.expect("A value should be returned")
|
||||
.extract(py)
|
||||
.expect("The value should be able to be converted to an i32");
|
||||
|
||||
let ret_value: i32 = add_func
|
||||
.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);
|
||||
assert_eq!(ret_value, 3);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
@ -174,12 +171,11 @@ fn raw_ident_module(_py: Python<'_>, module: &PyModule) -> PyResult<()> {
|
|||
fn test_raw_idents() {
|
||||
use pyo3::wrap_pymodule;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let module = wrap_pymodule!(raw_ident_module)(py);
|
||||
|
||||
let module = wrap_pymodule!(raw_ident_module)(py);
|
||||
|
||||
py_assert!(py, module, "module.move() == 42");
|
||||
py_assert!(py, module, "module.move() == 42");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
@ -197,31 +193,30 @@ fn foobar_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
|||
|
||||
#[test]
|
||||
fn test_custom_names() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let module = pyo3::wrap_pymodule!(foobar_module)(py);
|
||||
|
||||
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]
|
||||
fn test_module_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let module = pyo3::wrap_pymodule!(foobar_module)(py);
|
||||
Python::with_gil(|py| {
|
||||
let module = pyo3::wrap_pymodule!(foobar_module)(py);
|
||||
|
||||
py_assert!(py, module, "module.yay == 'me'");
|
||||
py_assert!(py, module, "module.yay == 'me'");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_module_dunder_all() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let module = pyo3::wrap_pymodule!(foobar_module)(py);
|
||||
Python::with_gil(|py| {
|
||||
let module = pyo3::wrap_pymodule!(foobar_module)(py);
|
||||
|
||||
py_assert!(py, module, "module.__all__ == ['foobar']");
|
||||
py_assert!(py, module, "module.__all__ == ['foobar']");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
@ -261,25 +256,25 @@ fn supermodule(py: Python<'_>, module: &PyModule) -> PyResult<()> {
|
|||
fn test_module_nesting() {
|
||||
use pyo3::wrap_pymodule;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let supermodule = wrap_pymodule!(supermodule)(py);
|
||||
Python::with_gil(|py| {
|
||||
let supermodule = wrap_pymodule!(supermodule)(py);
|
||||
|
||||
py_assert!(
|
||||
py,
|
||||
supermodule,
|
||||
"supermodule.superfunction() == 'Superfunction'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
supermodule,
|
||||
"supermodule.submodule.subfunction() == 'Subfunction'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
supermodule,
|
||||
"supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
supermodule,
|
||||
"supermodule.superfunction() == 'Superfunction'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
supermodule,
|
||||
"supermodule.submodule.subfunction() == 'Subfunction'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
supermodule,
|
||||
"supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Test that argument parsing specification works for pyfunctions
|
||||
|
@ -302,15 +297,15 @@ fn vararg_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
|||
|
||||
#[test]
|
||||
fn test_vararg_module() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let m = pyo3::wrap_pymodule!(vararg_module)(py);
|
||||
Python::with_gil(|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(1, 2) == [1, (2,)]");
|
||||
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.int_vararg_fn() == [5, ()]");
|
||||
py_assert!(py, m, "m.int_vararg_fn(1, 2) == [1, (2,)]");
|
||||
py_assert!(py, m, "m.int_vararg_fn() == [5, ()]");
|
||||
py_assert!(py, m, "m.int_vararg_fn(1, 2) == [1, (2,)]");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -397,36 +392,36 @@ fn module_with_functions_with_module(_py: Python<'_>, m: &PyModule) -> PyResult<
|
|||
|
||||
#[test]
|
||||
fn test_module_functions_with_module() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let m = pyo3::wrap_pymodule!(module_with_functions_with_module)(py);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_module() == 'module_with_functions_with_module'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_module_and_py() == 'module_with_functions_with_module'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_module_and_default_arg() \
|
||||
Python::with_gil(|py| {
|
||||
let m = pyo3::wrap_pymodule!(module_with_functions_with_module)(py);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_module() == 'module_with_functions_with_module'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_module_and_py() == 'module_with_functions_with_module'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_module_and_default_arg() \
|
||||
== ('module_with_functions_with_module', 'foo')"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_module_and_args_kwargs(1, x=1, y=2) \
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_module_and_args_kwargs(1, x=1, y=2) \
|
||||
== ('module_with_functions_with_module', 1, 2)"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_pass_module_in_attribute() == 'module_with_functions_with_module'"
|
||||
);
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.pyfunction_with_pass_module_in_attribute() == 'module_with_functions_with_module'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -377,18 +377,17 @@ impl Iterator {
|
|||
|
||||
#[test]
|
||||
fn iterator() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let inst = Py::new(
|
||||
py,
|
||||
Iterator {
|
||||
iter: Box::new(5..8),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_assert!(py, inst, "iter(inst) is inst");
|
||||
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(
|
||||
py,
|
||||
Iterator {
|
||||
iter: Box::new(5..8),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_assert!(py, inst, "iter(inst) is inst");
|
||||
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -406,15 +405,14 @@ struct NotCallable;
|
|||
|
||||
#[test]
|
||||
fn callable() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let c = Py::new(py, Callable).unwrap();
|
||||
py_assert!(py, c, "callable(c)");
|
||||
py_assert!(py, c, "c(7) == 42");
|
||||
|
||||
let c = Py::new(py, Callable).unwrap();
|
||||
py_assert!(py, c, "callable(c)");
|
||||
py_assert!(py, c, "c(7) == 42");
|
||||
|
||||
let nc = Py::new(py, NotCallable).unwrap();
|
||||
py_assert!(py, nc, "not callable(nc)");
|
||||
let nc = Py::new(py, NotCallable).unwrap();
|
||||
py_assert!(py, nc, "not callable(nc)");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -434,17 +432,16 @@ impl SetItem {
|
|||
|
||||
#[test]
|
||||
fn setitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
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);
|
||||
assert_eq!(c.val, 2);
|
||||
}
|
||||
py_expect_exception!(py, c, "del c[1]", PyNotImplementedError);
|
||||
Python::with_gil(|py| {
|
||||
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);
|
||||
assert_eq!(c.val, 2);
|
||||
}
|
||||
py_expect_exception!(py, c, "del c[1]", PyNotImplementedError);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -461,16 +458,15 @@ impl DelItem {
|
|||
|
||||
#[test]
|
||||
fn delitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
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);
|
||||
}
|
||||
py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError);
|
||||
Python::with_gil(|py| {
|
||||
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);
|
||||
}
|
||||
py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -491,18 +487,17 @@ impl SetDelItem {
|
|||
|
||||
#[test]
|
||||
fn setdelitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, SetDelItem { val: None }).unwrap();
|
||||
py_run!(py, c, "c[1] = 2");
|
||||
{
|
||||
Python::with_gil(|py| {
|
||||
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();
|
||||
assert_eq!(c.val, Some(2));
|
||||
}
|
||||
py_run!(py, c, "del c[1]");
|
||||
let c = c.borrow();
|
||||
assert_eq!(c.val, None);
|
||||
assert_eq!(c.val, None);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -517,13 +512,12 @@ impl Contains {
|
|||
|
||||
#[test]
|
||||
fn contains() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Py::new(py, Contains {}).unwrap();
|
||||
py_run!(py, c, "assert 1 in c");
|
||||
py_run!(py, c, "assert -1 not in c");
|
||||
py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError);
|
||||
Python::with_gil(|py| {
|
||||
let c = Py::new(py, Contains {}).unwrap();
|
||||
py_run!(py, c, "assert 1 in c");
|
||||
py_run!(py, c, "assert -1 not in c");
|
||||
py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -548,13 +542,12 @@ impl GetItem {
|
|||
|
||||
#[test]
|
||||
fn test_getitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let ob = Py::new(py, GetItem {}).unwrap();
|
||||
|
||||
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]
|
||||
|
@ -572,11 +565,11 @@ impl ClassWithGetAttr {
|
|||
|
||||
#[test]
|
||||
fn getattr_doesnt_override_member() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(py, ClassWithGetAttr { data: 4 }).unwrap();
|
||||
py_assert!(py, inst, "inst.data == 4");
|
||||
py_assert!(py, inst, "inst.a == 8");
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(py, ClassWithGetAttr { data: 4 }).unwrap();
|
||||
py_assert!(py, inst, "inst.data == 4");
|
||||
py_assert!(py, inst, "inst.a == 8");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -594,11 +587,11 @@ impl ClassWithGetAttribute {
|
|||
|
||||
#[test]
|
||||
fn getattribute_overrides_member() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(py, ClassWithGetAttribute { data: 4 }).unwrap();
|
||||
py_assert!(py, inst, "inst.data == 8");
|
||||
py_assert!(py, inst, "inst.y == 8");
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(py, ClassWithGetAttribute { data: 4 }).unwrap();
|
||||
py_assert!(py, inst, "inst.data == 8");
|
||||
py_assert!(py, inst, "inst.y == 8");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -627,13 +620,13 @@ impl ClassWithGetAttrAndGetAttribute {
|
|||
|
||||
#[test]
|
||||
fn getattr_and_getattribute() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(py, ClassWithGetAttrAndGetAttribute).unwrap();
|
||||
py_assert!(py, inst, "inst.exists == 42");
|
||||
py_assert!(py, inst, "inst.lucky == 57");
|
||||
py_expect_exception!(py, inst, "inst.error", PyValueError);
|
||||
py_expect_exception!(py, inst, "inst.unlucky", PyAttributeError);
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(py, ClassWithGetAttrAndGetAttribute).unwrap();
|
||||
py_assert!(py, inst, "inst.exists == 42");
|
||||
py_assert!(py, inst, "inst.lucky == 57");
|
||||
py_expect_exception!(py, inst, "inst.error", PyValueError);
|
||||
py_expect_exception!(py, inst, "inst.unlucky", PyAttributeError);
|
||||
});
|
||||
}
|
||||
|
||||
/// Wraps a Python future and yield it once.
|
||||
|
@ -674,10 +667,9 @@ impl OnceFuture {
|
|||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop)
|
||||
fn test_await() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let once = py.get_type::<OnceFuture>();
|
||||
let source = r#"
|
||||
Python::with_gil(|py| {
|
||||
let once = py.get_type::<OnceFuture>();
|
||||
let source = r#"
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
|
@ -691,11 +683,12 @@ if sys.platform == "win32" and sys.version_info >= (3, 8, 0):
|
|||
|
||||
asyncio.run(main())
|
||||
"#;
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Once", once).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Once", once).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -724,10 +717,9 @@ impl AsyncIterator {
|
|||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop)
|
||||
fn test_anext_aiter() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let once = py.get_type::<OnceFuture>();
|
||||
let source = r#"
|
||||
Python::with_gil(|py| {
|
||||
let once = py.get_type::<OnceFuture>();
|
||||
let source = r#"
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
|
@ -745,14 +737,15 @@ if sys.platform == "win32" and sys.version_info >= (3, 8, 0):
|
|||
|
||||
asyncio.run(main())
|
||||
"#;
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Once", once).unwrap();
|
||||
globals
|
||||
.set_item("AsyncIterator", py.get_type::<AsyncIterator>())
|
||||
.unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Once", once).unwrap();
|
||||
globals
|
||||
.set_item("AsyncIterator", py.get_type::<AsyncIterator>())
|
||||
.unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
/// Increment the count when `__get__` is called.
|
||||
|
@ -789,11 +782,10 @@ impl DescrCounter {
|
|||
|
||||
#[test]
|
||||
fn descr_getset() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let counter = py.get_type::<DescrCounter>();
|
||||
let source = pyo3::indoc::indoc!(
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let counter = py.get_type::<DescrCounter>();
|
||||
let source = pyo3::indoc::indoc!(
|
||||
r#"
|
||||
class Class:
|
||||
counter = Counter()
|
||||
|
||||
|
@ -816,12 +808,13 @@ assert c.counter.count == 4
|
|||
del c.counter
|
||||
assert c.counter.count == 1
|
||||
"#
|
||||
);
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Counter", counter).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
);
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Counter", counter).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
|
|
@ -17,14 +17,14 @@ fn optional_bool(arg: Option<bool>) -> String {
|
|||
#[test]
|
||||
fn test_optional_bool() {
|
||||
// Regression test for issue #932
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let f = wrap_pyfunction!(optional_bool)(py).unwrap();
|
||||
Python::with_gil(|py| {
|
||||
let f = wrap_pyfunction!(optional_bool)(py).unwrap();
|
||||
|
||||
py_assert!(py, f, "f() == 'Some(true)'");
|
||||
py_assert!(py, f, "f(True) == 'Some(true)'");
|
||||
py_assert!(py, f, "f(False) == 'Some(false)'");
|
||||
py_assert!(py, f, "f(None) == 'None'");
|
||||
py_assert!(py, f, "f() == 'Some(true)'");
|
||||
py_assert!(py, f, "f(True) == 'Some(true)'");
|
||||
py_assert!(py, f, "f(False) == 'Some(false)'");
|
||||
py_assert!(py, f, "f(None) == 'None'");
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
|
@ -41,33 +41,33 @@ fn buffer_inplace_add(py: Python<'_>, x: PyBuffer<i32>, y: PyBuffer<i32>) {
|
|||
#[cfg(not(Py_LIMITED_API))]
|
||||
#[test]
|
||||
fn test_buffer_add() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let f = wrap_pyfunction!(buffer_inplace_add)(py).unwrap();
|
||||
Python::with_gil(|py| {
|
||||
let f = wrap_pyfunction!(buffer_inplace_add)(py).unwrap();
|
||||
|
||||
py_expect_exception!(
|
||||
py,
|
||||
f,
|
||||
r#"
|
||||
py_expect_exception!(
|
||||
py,
|
||||
f,
|
||||
r#"
|
||||
import array
|
||||
a = array.array("i", [0, 1, 2, 3])
|
||||
b = array.array("I", [0, 1, 2, 3])
|
||||
f(a, b)
|
||||
"#,
|
||||
PyBufferError
|
||||
);
|
||||
PyBufferError
|
||||
);
|
||||
|
||||
pyo3::py_run!(
|
||||
py,
|
||||
f,
|
||||
r#"
|
||||
pyo3::py_run!(
|
||||
py,
|
||||
f,
|
||||
r#"
|
||||
import array
|
||||
a = array.array("i", [0, 1, 2, 3])
|
||||
b = array.array("i", [2, 3, 4, 5])
|
||||
f(a, b)
|
||||
assert a, array.array("i", [2, 4, 6, 8])
|
||||
"#
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
|
@ -83,33 +83,33 @@ fn function_with_pycfunction_arg(fun: &PyCFunction) -> PyResult<&PyAny> {
|
|||
|
||||
#[test]
|
||||
fn test_functions_with_function_args() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let py_cfunc_arg = wrap_pyfunction!(function_with_pycfunction_arg)(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();
|
||||
Python::with_gil(|py| {
|
||||
let py_cfunc_arg = wrap_pyfunction!(function_with_pycfunction_arg)(py).unwrap();
|
||||
let bool_to_string = wrap_pyfunction!(optional_bool)(py).unwrap();
|
||||
|
||||
pyo3::py_run!(
|
||||
py,
|
||||
py_func_arg,
|
||||
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!(
|
||||
py,
|
||||
py_func_arg,
|
||||
r#"
|
||||
def foo(): return "bar"
|
||||
assert py_func_arg(foo) == "bar"
|
||||
"#
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
|
@ -131,38 +131,36 @@ fn function_with_custom_conversion(
|
|||
#[cfg(not(Py_LIMITED_API))]
|
||||
#[test]
|
||||
fn test_function_with_custom_conversion() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();
|
||||
|
||||
let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();
|
||||
|
||||
pyo3::py_run!(
|
||||
py,
|
||||
custom_conv_func,
|
||||
r#"
|
||||
pyo3::py_run!(
|
||||
py,
|
||||
custom_conv_func,
|
||||
r#"
|
||||
import datetime
|
||||
|
||||
dt = datetime.datetime.fromtimestamp(1612040400)
|
||||
assert custom_conv_func(dt) == 1612040400
|
||||
"#
|
||||
)
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
#[test]
|
||||
fn test_function_with_custom_conversion_error() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();
|
||||
|
||||
let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();
|
||||
|
||||
py_expect_exception!(
|
||||
py,
|
||||
custom_conv_func,
|
||||
"custom_conv_func(['a'])",
|
||||
PyTypeError,
|
||||
"argument 'timestamp': 'list' object cannot be converted to 'PyDateTime'"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
custom_conv_func,
|
||||
"custom_conv_func(['a'])",
|
||||
PyTypeError,
|
||||
"argument 'timestamp': 'list' object cannot be converted to 'PyDateTime'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -188,76 +186,75 @@ fn conversion_error(
|
|||
|
||||
#[test]
|
||||
fn test_conversion_error() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let conversion_error = wrap_pyfunction!(conversion_error)(py).unwrap();
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error(None, None, None, None, None)",
|
||||
PyTypeError,
|
||||
"argument 'str_arg': 'NoneType' object cannot be converted to 'PyString'"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error(100, None, None, None, None)",
|
||||
PyTypeError,
|
||||
"argument 'str_arg': 'int' object cannot be converted to 'PyString'"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error('string1', 'string2', None, None, None)",
|
||||
PyTypeError,
|
||||
"argument 'int_arg': 'str' object cannot be interpreted as an integer"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error('string1', -100, 'string2', None, None)",
|
||||
PyTypeError,
|
||||
"argument 'tuple_arg': 'str' object cannot be converted to 'PyTuple'"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error('string1', -100, ('string2', 10.), 'string3', None)",
|
||||
PyTypeError,
|
||||
"argument 'option_arg': 'str' object cannot be interpreted as an integer"
|
||||
);
|
||||
let exception = py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"
|
||||
Python::with_gil(|py| {
|
||||
let conversion_error = wrap_pyfunction!(conversion_error)(py).unwrap();
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error(None, None, None, None, None)",
|
||||
PyTypeError,
|
||||
"argument 'str_arg': 'NoneType' object cannot be converted to 'PyString'"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error(100, None, None, None, None)",
|
||||
PyTypeError,
|
||||
"argument 'str_arg': 'int' object cannot be converted to 'PyString'"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error('string1', 'string2', None, None, None)",
|
||||
PyTypeError,
|
||||
"argument 'int_arg': 'str' object cannot be interpreted as an integer"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error('string1', -100, 'string2', None, None)",
|
||||
PyTypeError,
|
||||
"argument 'tuple_arg': 'str' object cannot be converted to 'PyTuple'"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"conversion_error('string1', -100, ('string2', 10.), 'string3', None)",
|
||||
PyTypeError,
|
||||
"argument 'option_arg': 'str' object cannot be interpreted as an integer"
|
||||
);
|
||||
let exception = py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"
|
||||
class ValueClass:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
conversion_error('string1', -100, ('string2', 10.), None, ValueClass(\"no_expected_type\"))",
|
||||
PyTypeError
|
||||
);
|
||||
assert_eq!(
|
||||
extract_traceback(py, exception),
|
||||
"TypeError: argument 'struct_arg': failed to \
|
||||
PyTypeError
|
||||
);
|
||||
assert_eq!(
|
||||
extract_traceback(py, exception),
|
||||
"TypeError: argument 'struct_arg': failed to \
|
||||
extract field ValueClass.value: TypeError: 'str' object cannot be interpreted as an integer"
|
||||
);
|
||||
);
|
||||
|
||||
let exception = py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"
|
||||
let exception = py_expect_exception!(
|
||||
py,
|
||||
conversion_error,
|
||||
"
|
||||
class ValueClass:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
conversion_error('string1', -100, ('string2', 10.), None, ValueClass(-5))",
|
||||
PyTypeError
|
||||
);
|
||||
assert_eq!(
|
||||
extract_traceback(py, exception),
|
||||
"TypeError: argument 'struct_arg': failed to \
|
||||
PyTypeError
|
||||
);
|
||||
assert_eq!(
|
||||
extract_traceback(py, exception),
|
||||
"TypeError: argument 'struct_arg': failed to \
|
||||
extract field ValueClass.value: OverflowError: can't convert negative int to unsigned"
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Helper function that concatenates the error message from
|
||||
|
@ -277,30 +274,29 @@ fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String {
|
|||
fn test_pycfunction_new() {
|
||||
use pyo3::ffi;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
unsafe extern "C" fn c_fn(
|
||||
_self: *mut ffi::PyObject,
|
||||
_args: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject {
|
||||
ffi::PyLong_FromLong(4200)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn c_fn(
|
||||
_self: *mut ffi::PyObject,
|
||||
_args: *mut ffi::PyObject,
|
||||
) -> *mut ffi::PyObject {
|
||||
ffi::PyLong_FromLong(4200)
|
||||
}
|
||||
let py_fn = PyCFunction::new(
|
||||
c_fn,
|
||||
"py_fn",
|
||||
"py_fn for test (this is the docstring)",
|
||||
py.into(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let py_fn = PyCFunction::new(
|
||||
c_fn,
|
||||
"py_fn",
|
||||
"py_fn for test (this is the docstring)",
|
||||
py.into(),
|
||||
)
|
||||
.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)'"
|
||||
);
|
||||
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]
|
||||
|
@ -310,103 +306,107 @@ fn test_pycfunction_new_with_keywords() {
|
|||
use std::os::raw::{c_char, c_long};
|
||||
use std::ptr;
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
unsafe extern "C" fn c_fn(
|
||||
_self: *mut ffi::PyObject,
|
||||
args: *mut ffi::PyObject,
|
||||
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(
|
||||
_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;
|
||||
let foo_name = CString::new("foo").unwrap();
|
||||
let foo_name_raw: *mut c_char = foo_name.into_raw();
|
||||
let kw_bar_name = CString::new("kw_bar").unwrap();
|
||||
let kw_bar_name_raw: *mut c_char = kw_bar_name.into_raw();
|
||||
|
||||
let foo_name = CString::new("foo").unwrap();
|
||||
let foo_name_raw: *mut c_char = foo_name.into_raw();
|
||||
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 arglist_ptr: *mut *mut c_char = arglist.as_mut_ptr();
|
||||
|
||||
let mut arglist = vec![foo_name_raw, kw_bar_name_raw, ptr::null_mut()];
|
||||
let arglist_ptr: *mut *mut c_char = arglist.as_mut_ptr();
|
||||
let arg_pattern: *const c_char = CString::new("l|l").unwrap().into_raw();
|
||||
|
||||
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(
|
||||
c_fn,
|
||||
"py_fn",
|
||||
"py_fn for test (this is the docstring)",
|
||||
py.into(),
|
||||
)
|
||||
.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)'"
|
||||
);
|
||||
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]
|
||||
fn test_closure() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let f = |args: &types::PyTuple, _kwargs: Option<&types::PyDict>| -> PyResult<_> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let res: Vec<_> = args
|
||||
.iter()
|
||||
.map(|elem| {
|
||||
if let Ok(i) = elem.extract::<i64>() {
|
||||
(i + 1).into_py(py)
|
||||
} else if let Ok(f) = elem.extract::<f64>() {
|
||||
(2. * f).into_py(py)
|
||||
} else if let Ok(mut s) = elem.extract::<String>() {
|
||||
s.push_str("-py");
|
||||
s.into_py(py)
|
||||
} else {
|
||||
panic!("unexpected argument type for {:?}", elem)
|
||||
}
|
||||
Python::with_gil(|py| {
|
||||
let f = |args: &types::PyTuple, _kwargs: Option<&types::PyDict>| -> PyResult<_> {
|
||||
Python::with_gil(|py| {
|
||||
let res: Vec<_> = args
|
||||
.iter()
|
||||
.map(|elem| {
|
||||
if let Ok(i) = elem.extract::<i64>() {
|
||||
(i + 1).into_py(py)
|
||||
} else if let Ok(f) = elem.extract::<f64>() {
|
||||
(2. * f).into_py(py)
|
||||
} else if let Ok(mut s) = elem.extract::<String>() {
|
||||
s.push_str("-py");
|
||||
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, 3.14, 'foo') == [43, 6.28, 'foo-py']"
|
||||
);
|
||||
py_assert!(py, closure_py, "closure_py(42) == [43]");
|
||||
py_assert!(
|
||||
py,
|
||||
closure_py,
|
||||
"closure_py(42, 3.14, 'foo') == [43, 6.28, 'foo-py']"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_closure_counter() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let counter = std::cell::RefCell::new(0);
|
||||
let counter_fn =
|
||||
move |_args: &types::PyTuple, _kwargs: Option<&types::PyDict>| -> PyResult<i32> {
|
||||
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);
|
||||
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();
|
||||
|
||||
py_assert!(py, counter_py, "counter_py() == 1");
|
||||
py_assert!(py, counter_py, "counter_py() == 2");
|
||||
py_assert!(py, counter_py, "counter_py() == 3");
|
||||
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]
|
||||
|
|
|
@ -29,24 +29,23 @@ impl PyMappingProtocol for Len {
|
|||
|
||||
#[test]
|
||||
fn len() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(py, Len { l: 10 }).unwrap();
|
||||
py_assert!(py, inst, "len(inst) == 10");
|
||||
unsafe {
|
||||
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();
|
||||
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: (isize::MAX as usize) + 1,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_expect_exception!(py, inst, "len(inst)", PyOverflowError);
|
||||
let inst = Py::new(
|
||||
py,
|
||||
Len {
|
||||
l: (isize::MAX as usize) + 1,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_expect_exception!(py, inst, "len(inst)", PyOverflowError);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -67,18 +66,17 @@ impl PyIterProtocol for Iterator {
|
|||
|
||||
#[test]
|
||||
fn iterator() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let inst = Py::new(
|
||||
py,
|
||||
Iterator {
|
||||
iter: Box::new(5..8),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_assert!(py, inst, "iter(inst) is inst");
|
||||
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(
|
||||
py,
|
||||
Iterator {
|
||||
iter: Box::new(5..8),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
py_assert!(py, inst, "iter(inst) is inst");
|
||||
py_assert!(py, inst, "list(inst) == [5, 6, 7]");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -97,12 +95,11 @@ impl PyObjectProtocol for StringMethods {
|
|||
|
||||
#[test]
|
||||
fn string_methods() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let obj = Py::new(py, StringMethods {}).unwrap();
|
||||
py_assert!(py, obj, "str(obj) == 'str'");
|
||||
py_assert!(py, obj, "repr(obj) == 'repr'");
|
||||
Python::with_gil(|py| {
|
||||
let obj = Py::new(py, StringMethods {}).unwrap();
|
||||
py_assert!(py, obj, "str(obj) == 'str'");
|
||||
py_assert!(py, obj, "repr(obj) == 'repr'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -122,19 +119,18 @@ impl PyObjectProtocol for Comparisons {
|
|||
|
||||
#[test]
|
||||
fn comparisons() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let zero = Py::new(py, Comparisons { val: 0 }).unwrap();
|
||||
let one = Py::new(py, Comparisons { val: 1 }).unwrap();
|
||||
let ten = Py::new(py, Comparisons { val: 10 }).unwrap();
|
||||
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();
|
||||
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");
|
||||
|
||||
py_assert!(py, one, "bool(one) is True");
|
||||
py_assert!(py, zero, "not zero");
|
||||
py_assert!(py, one, "bool(one) is True");
|
||||
py_assert!(py, zero, "not zero");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -181,21 +177,20 @@ impl PySequenceProtocol for Sequence {
|
|||
|
||||
#[test]
|
||||
fn sequence() {
|
||||
let gil = Python::acquire_gil();
|
||||
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']");
|
||||
py_assert!(py, c, "c[-1] == 'G'");
|
||||
py_run!(
|
||||
py,
|
||||
c,
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let c = Py::new(py, Sequence::default()).unwrap();
|
||||
py_assert!(py, c, "list(c) == ['A', 'B', 'C', 'D', 'E', 'F', 'G']");
|
||||
py_assert!(py, c, "c[-1] == 'G'");
|
||||
py_run!(
|
||||
py,
|
||||
c,
|
||||
r#"
|
||||
c[0] = 'H'
|
||||
assert c[0] == 'H'
|
||||
"#
|
||||
);
|
||||
py_expect_exception!(py, c, "c['abc']", PyTypeError);
|
||||
);
|
||||
py_expect_exception!(py, c, "c['abc']", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -215,17 +210,16 @@ impl PyMappingProtocol for SetItem {
|
|||
|
||||
#[test]
|
||||
fn setitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
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);
|
||||
assert_eq!(c.val, 2);
|
||||
}
|
||||
py_expect_exception!(py, c, "del c[1]", PyNotImplementedError);
|
||||
Python::with_gil(|py| {
|
||||
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);
|
||||
assert_eq!(c.val, 2);
|
||||
}
|
||||
py_expect_exception!(py, c, "del c[1]", PyNotImplementedError);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -242,16 +236,15 @@ impl PyMappingProtocol<'a> for DelItem {
|
|||
|
||||
#[test]
|
||||
fn delitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
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);
|
||||
}
|
||||
py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError);
|
||||
Python::with_gil(|py| {
|
||||
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);
|
||||
}
|
||||
py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -272,18 +265,17 @@ impl PyMappingProtocol for SetDelItem {
|
|||
|
||||
#[test]
|
||||
fn setdelitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = PyCell::new(py, SetDelItem { val: None }).unwrap();
|
||||
py_run!(py, c, "c[1] = 2");
|
||||
{
|
||||
Python::with_gil(|py| {
|
||||
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();
|
||||
assert_eq!(c.val, Some(2));
|
||||
}
|
||||
py_run!(py, c, "del c[1]");
|
||||
let c = c.borrow();
|
||||
assert_eq!(c.val, None);
|
||||
assert_eq!(c.val, None);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -298,26 +290,24 @@ impl PySequenceProtocol for Contains {
|
|||
|
||||
#[test]
|
||||
fn contains() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let c = Py::new(py, Contains {}).unwrap();
|
||||
py_run!(py, c, "assert 1 in c");
|
||||
py_run!(py, c, "assert -1 not in c");
|
||||
py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError);
|
||||
Python::with_gil(|py| {
|
||||
let c = Py::new(py, Contains {}).unwrap();
|
||||
py_run!(py, c, "assert 1 in c");
|
||||
py_run!(py, c, "assert -1 not in c");
|
||||
py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basics() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let v = PySlice::new(py, 1, 10, 2);
|
||||
let indices = v.indices(100).unwrap();
|
||||
assert_eq!(1, indices.start);
|
||||
assert_eq!(10, indices.stop);
|
||||
assert_eq!(2, indices.step);
|
||||
assert_eq!(5, indices.slicelength);
|
||||
Python::with_gil(|py| {
|
||||
let v = PySlice::new(py, 1, 10, 2);
|
||||
let indices = v.indices(100).unwrap();
|
||||
assert_eq!(1, indices.start);
|
||||
assert_eq!(10, indices.stop);
|
||||
assert_eq!(2, indices.step);
|
||||
assert_eq!(5, indices.slicelength);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -342,13 +332,12 @@ impl<'p> PyMappingProtocol<'p> for Test {
|
|||
|
||||
#[test]
|
||||
fn test_cls_impl() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let ob = Py::new(py, Test {}).unwrap();
|
||||
|
||||
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]
|
||||
|
@ -366,11 +355,11 @@ impl PyObjectProtocol for ClassWithGetAttr {
|
|||
|
||||
#[test]
|
||||
fn getattr_doesnt_override_member() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = PyCell::new(py, ClassWithGetAttr { data: 4 }).unwrap();
|
||||
py_assert!(py, inst, "inst.data == 4");
|
||||
py_assert!(py, inst, "inst.a == 8");
|
||||
Python::with_gil(|py| {
|
||||
let inst = PyCell::new(py, ClassWithGetAttr { data: 4 }).unwrap();
|
||||
py_assert!(py, inst, "inst.data == 4");
|
||||
py_assert!(py, inst, "inst.a == 8");
|
||||
});
|
||||
}
|
||||
|
||||
/// Wraps a Python future and yield it once.
|
||||
|
@ -415,11 +404,10 @@ impl PyIterProtocol for OnceFuture {
|
|||
|
||||
#[test]
|
||||
fn test_await() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let once = py.get_type::<OnceFuture>();
|
||||
let source = pyo3::indoc::indoc!(
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let once = py.get_type::<OnceFuture>();
|
||||
let source = pyo3::indoc::indoc!(
|
||||
r#"
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
|
@ -435,12 +423,13 @@ asyncio.set_event_loop(loop)
|
|||
assert loop.run_until_complete(main()) is None
|
||||
loop.close()
|
||||
"#
|
||||
);
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Once", once).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
);
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Once", once).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
/// Increment the count when `__get__` is called.
|
||||
|
@ -475,11 +464,10 @@ impl PyDescrProtocol for DescrCounter {
|
|||
|
||||
#[test]
|
||||
fn descr_getset() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let counter = py.get_type::<DescrCounter>();
|
||||
let source = pyo3::indoc::indoc!(
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let counter = py.get_type::<DescrCounter>();
|
||||
let source = pyo3::indoc::indoc!(
|
||||
r#"
|
||||
class Class:
|
||||
counter = Counter()
|
||||
c = Class()
|
||||
|
@ -488,10 +476,11 @@ assert c.counter.count == 2
|
|||
c.counter = Counter()
|
||||
assert c.counter.count == 3
|
||||
"#
|
||||
);
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Counter", counter).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
);
|
||||
let globals = PyModule::import(py, "__main__").unwrap().dict();
|
||||
globals.set_item("Counter", counter).unwrap();
|
||||
py.run(source, Some(globals), None)
|
||||
.map_err(|e| e.print(py))
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -89,35 +89,35 @@ fn reader() -> Reader {
|
|||
|
||||
#[test]
|
||||
fn test_nested_iter() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let reader: PyObject = reader().into_py(py);
|
||||
py_assert!(
|
||||
py,
|
||||
reader,
|
||||
"list(reader.get_iter(bytes([3, 5, 2]))) == ['c', 'e', 'b']"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let reader: PyObject = reader().into_py(py);
|
||||
py_assert!(
|
||||
py,
|
||||
reader,
|
||||
"list(reader.get_iter(bytes([3, 5, 2]))) == ['c', 'e', 'b']"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_ref() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let reader: PyObject = reader().into_py(py);
|
||||
py_assert!(py, reader, "reader == reader.clone_ref()");
|
||||
py_assert!(py, reader, "reader == reader.clone_ref_with_py()");
|
||||
Python::with_gil(|py| {
|
||||
let reader: PyObject = reader().into_py(py);
|
||||
py_assert!(py, reader, "reader == reader.clone_ref()");
|
||||
py_assert!(py, reader, "reader == reader.clone_ref_with_py()");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_iter_reset() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let reader = PyCell::new(py, reader()).unwrap();
|
||||
py_assert!(
|
||||
py,
|
||||
reader,
|
||||
"list(reader.get_iter_and_reset(bytes([3, 5, 2]))) == ['c', 'e', 'b']"
|
||||
);
|
||||
let reader_ref = reader.borrow();
|
||||
assert!(reader_ref.inner.is_empty());
|
||||
Python::with_gil(|py| {
|
||||
let reader = PyCell::new(py, reader()).unwrap();
|
||||
py_assert!(
|
||||
py,
|
||||
reader,
|
||||
"list(reader.get_iter_and_reset(bytes([3, 5, 2]))) == ['c', 'e', 'b']"
|
||||
);
|
||||
let reader_ref = reader.borrow();
|
||||
assert!(reader_ref.inner.is_empty());
|
||||
});
|
||||
}
|
||||
|
|
|
@ -113,141 +113,135 @@ fn seq_dict(py: Python<'_>) -> &pyo3::types::PyDict {
|
|||
|
||||
#[test]
|
||||
fn test_getitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let d = seq_dict(py);
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_assert!(py, *d, "s[0] == 1");
|
||||
py_assert!(py, *d, "s[1] == 2");
|
||||
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_assert!(py, *d, "s[0] == 1");
|
||||
py_assert!(py, *d, "s[1] == 2");
|
||||
py_assert!(py, *d, "s[2] == 3");
|
||||
py_expect_exception!(py, *d, "print(s[-4])", PyIndexError);
|
||||
py_expect_exception!(py, *d, "print(s[4])", PyIndexError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_setitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let d = seq_dict(py);
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]");
|
||||
py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError);
|
||||
py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]");
|
||||
py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
|
||||
|
||||
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))",
|
||||
PyIndexError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[4]",
|
||||
PyIndexError
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))",
|
||||
PyIndexError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[4]",
|
||||
PyIndexError
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_assert!(py, *d, "1 in s");
|
||||
py_assert!(py, *d, "2 in s");
|
||||
py_assert!(py, *d, "3 in s");
|
||||
py_assert!(py, *d, "4 not in s");
|
||||
py_assert!(py, *d, "'hello' not in s");
|
||||
py_assert!(py, *d, "1 in s");
|
||||
py_assert!(py, *d, "2 in s");
|
||||
py_assert!(py, *d, "3 in s");
|
||||
py_assert!(py, *d, "4 not in s");
|
||||
py_assert!(py, *d, "'hello' not in s");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_concat() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_run!(
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2",
|
||||
PyTypeError
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inplace_concat() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]"
|
||||
);
|
||||
py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]"
|
||||
);
|
||||
py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeat() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
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]
|
||||
fn test_inplace_repeat() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
|
||||
|
||||
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
*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_run!(
|
||||
py,
|
||||
*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);
|
||||
});
|
||||
}
|
||||
|
||||
// Check that #[pyo3(get, set)] works correctly for Vec<PyObject>
|
||||
|
@ -260,31 +254,29 @@ struct GenericList {
|
|||
|
||||
#[test]
|
||||
fn test_generic_list_get() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let list: PyObject = GenericList {
|
||||
items: [1, 2, 3].iter().map(|i| i.to_object(py)).collect(),
|
||||
}
|
||||
.into_py(py);
|
||||
|
||||
let list: PyObject = GenericList {
|
||||
items: [1, 2, 3].iter().map(|i| i.to_object(py)).collect(),
|
||||
}
|
||||
.into_py(py);
|
||||
|
||||
py_assert!(py, list, "list.items == [1, 2, 3]");
|
||||
py_assert!(py, list, "list.items == [1, 2, 3]");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generic_list_set() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let list = PyCell::new(py, GenericList { items: vec![] }).unwrap();
|
||||
|
||||
let list = PyCell::new(py, GenericList { items: vec![] }).unwrap();
|
||||
|
||||
py_run!(py, list, "list.items = [1, 2, 3]");
|
||||
assert!(list
|
||||
.borrow()
|
||||
.items
|
||||
.iter()
|
||||
.zip(&[1u32, 2, 3])
|
||||
.all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
|
||||
py_run!(py, list, "list.items = [1, 2, 3]");
|
||||
assert!(list
|
||||
.borrow()
|
||||
.items
|
||||
.iter()
|
||||
.zip(&[1u32, 2, 3])
|
||||
.all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -306,18 +298,17 @@ impl OptionList {
|
|||
#[test]
|
||||
fn test_option_list_get() {
|
||||
// Regression test for #798
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let list = PyCell::new(
|
||||
py,
|
||||
OptionList {
|
||||
items: vec![Some(1), None],
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let list = PyCell::new(
|
||||
py,
|
||||
OptionList {
|
||||
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);
|
||||
py_assert!(py, list, "list[0] == 1");
|
||||
py_assert!(py, list, "list[1] == None");
|
||||
py_expect_exception!(py, list, "list[2]", PyIndexError);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -97,141 +97,135 @@ fn seq_dict(py: Python<'_>) -> &pyo3::types::PyDict {
|
|||
|
||||
#[test]
|
||||
fn test_getitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let d = seq_dict(py);
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_assert!(py, *d, "s[0] == 1");
|
||||
py_assert!(py, *d, "s[1] == 2");
|
||||
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_assert!(py, *d, "s[0] == 1");
|
||||
py_assert!(py, *d, "s[1] == 2");
|
||||
py_assert!(py, *d, "s[2] == 3");
|
||||
py_expect_exception!(py, *d, "print(s[-4])", PyIndexError);
|
||||
py_expect_exception!(py, *d, "print(s[4])", PyIndexError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_setitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let d = seq_dict(py);
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]");
|
||||
py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError);
|
||||
py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]");
|
||||
py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delitem() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
|
||||
|
||||
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))",
|
||||
PyIndexError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[4]",
|
||||
PyIndexError
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]"
|
||||
);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))",
|
||||
PyIndexError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s = ByteSequence([1, 2, 3]); del s[4]",
|
||||
PyIndexError
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_assert!(py, *d, "1 in s");
|
||||
py_assert!(py, *d, "2 in s");
|
||||
py_assert!(py, *d, "3 in s");
|
||||
py_assert!(py, *d, "4 not in s");
|
||||
py_assert!(py, *d, "'hello' not in s");
|
||||
py_assert!(py, *d, "1 in s");
|
||||
py_assert!(py, *d, "2 in s");
|
||||
py_assert!(py, *d, "3 in s");
|
||||
py_assert!(py, *d, "4 not in s");
|
||||
py_assert!(py, *d, "'hello' not in s");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_concat() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_run!(
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]"
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2",
|
||||
PyTypeError
|
||||
);
|
||||
py_expect_exception!(
|
||||
py,
|
||||
*d,
|
||||
"s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2",
|
||||
PyTypeError
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inplace_concat() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
let d = seq_dict(py);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]"
|
||||
);
|
||||
py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
|
||||
py_run!(
|
||||
py,
|
||||
*d,
|
||||
"s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]"
|
||||
);
|
||||
py_expect_exception!(py, *d, "s += 'hello'", PyTypeError);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repeat() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = seq_dict(py);
|
||||
|
||||
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]
|
||||
fn test_inplace_repeat() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
|
||||
|
||||
let d = [("ByteSequence", py.get_type::<ByteSequence>())].into_py_dict(py);
|
||||
|
||||
py_run!(
|
||||
py,
|
||||
*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_run!(
|
||||
py,
|
||||
*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);
|
||||
});
|
||||
}
|
||||
|
||||
// Check that #[pyo3(get, set)] works correctly for Vec<PyObject>
|
||||
|
@ -244,31 +238,29 @@ struct GenericList {
|
|||
|
||||
#[test]
|
||||
fn test_generic_list_get() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let list: PyObject = GenericList {
|
||||
items: [1, 2, 3].iter().map(|i| i.to_object(py)).collect(),
|
||||
}
|
||||
.into_py(py);
|
||||
|
||||
let list: PyObject = GenericList {
|
||||
items: [1, 2, 3].iter().map(|i| i.to_object(py)).collect(),
|
||||
}
|
||||
.into_py(py);
|
||||
|
||||
py_assert!(py, list, "list.items == [1, 2, 3]");
|
||||
py_assert!(py, list, "list.items == [1, 2, 3]");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generic_list_set() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let list = PyCell::new(py, GenericList { items: vec![] }).unwrap();
|
||||
|
||||
let list = PyCell::new(py, GenericList { items: vec![] }).unwrap();
|
||||
|
||||
py_run!(py, list, "list.items = [1, 2, 3]");
|
||||
assert!(list
|
||||
.borrow()
|
||||
.items
|
||||
.iter()
|
||||
.zip(&[1u32, 2, 3])
|
||||
.all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
|
||||
py_run!(py, list, "list.items = [1, 2, 3]");
|
||||
assert!(list
|
||||
.borrow()
|
||||
.items
|
||||
.iter()
|
||||
.zip(&[1u32, 2, 3])
|
||||
.all(|(a, b)| a.as_ref(py).eq(&b.into_py(py)).unwrap()));
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -290,18 +282,17 @@ impl PySequenceProtocol for OptionList {
|
|||
#[test]
|
||||
fn test_option_list_get() {
|
||||
// Regression test for #798
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
let list = PyCell::new(
|
||||
py,
|
||||
OptionList {
|
||||
items: vec![Some(1), None],
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let list = PyCell::new(
|
||||
py,
|
||||
OptionList {
|
||||
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);
|
||||
py_assert!(py, list, "list[0] == 1");
|
||||
py_assert!(py, list, "list[1] == None");
|
||||
py_expect_exception!(py, list, "list[2]", PyIndexError);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,15 +9,14 @@ fn take_str(_s: &str) {}
|
|||
|
||||
#[test]
|
||||
fn test_unicode_encode_error() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let take_str = wrap_pyfunction!(take_str)(py).unwrap();
|
||||
py_expect_exception!(
|
||||
py,
|
||||
take_str,
|
||||
"take_str('\\ud800')",
|
||||
PyUnicodeEncodeError,
|
||||
"'utf-8' codec can't encode character '\\ud800' in position 0: surrogates not allowed"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let take_str = wrap_pyfunction!(take_str)(py).unwrap();
|
||||
py_expect_exception!(
|
||||
py,
|
||||
take_str,
|
||||
"take_str('\\ud800')",
|
||||
PyUnicodeEncodeError,
|
||||
"'utf-8' codec can't encode character '\\ud800' in position 0: surrogates not allowed"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,12 +10,12 @@ fn class_without_docs_or_signature() {
|
|||
#[pyclass]
|
||||
struct MyClass {}
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
|
||||
py_assert!(py, typeobj, "typeobj.__doc__ is None");
|
||||
py_assert!(py, typeobj, "typeobj.__text_signature__ is None");
|
||||
py_assert!(py, typeobj, "typeobj.__doc__ is None");
|
||||
py_assert!(py, typeobj, "typeobj.__text_signature__ is None");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -25,12 +25,12 @@ fn class_with_docs() {
|
|||
/// docs line2
|
||||
struct MyClass {}
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
|
||||
py_assert!(py, typeobj, "typeobj.__doc__ == 'docs line1\\ndocs line2'");
|
||||
py_assert!(py, typeobj, "typeobj.__text_signature__ is None");
|
||||
py_assert!(py, typeobj, "typeobj.__doc__ == 'docs line1\\ndocs line2'");
|
||||
py_assert!(py, typeobj, "typeobj.__text_signature__ is None");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -53,20 +53,20 @@ fn class_with_docs_and_signature() {
|
|||
}
|
||||
}
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.__doc__ == 'docs line1\\ndocs line2\\ndocs line3'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.__text_signature__ == '(a, b=None, *, c=42)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.__doc__ == 'docs line1\\ndocs line2\\ndocs line3'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.__text_signature__ == '(a, b=None, *, c=42)'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -86,20 +86,20 @@ fn class_with_signature() {
|
|||
}
|
||||
}
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.__doc__ is None or typeobj.__doc__ == ''"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.__text_signature__ == '(a, b=None, *, c=42)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.__doc__ is None or typeobj.__doc__ == ''"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.__text_signature__ == '(a, b=None, *, c=42)'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -110,11 +110,11 @@ fn test_function() {
|
|||
let _ = (a, b, c);
|
||||
}
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let f = wrap_pyfunction!(my_function)(py).unwrap();
|
||||
Python::with_gil(|py| {
|
||||
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]
|
||||
|
@ -129,15 +129,15 @@ fn test_pyfn() {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let m = wrap_pymodule!(my_module)(py);
|
||||
Python::with_gil(|py| {
|
||||
let m = wrap_pymodule!(my_module)(py);
|
||||
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.my_function.__text_signature__ == '(a, b=None, *, c=42)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
m,
|
||||
"m.my_function.__text_signature__ == '(a, b=None, *, c=42)'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -167,30 +167,30 @@ fn test_methods() {
|
|||
}
|
||||
}
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
Python::with_gil(|py| {
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.method.__text_signature__ == '($self, a)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.pyself_method.__text_signature__ == '($self, b)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.class_method.__text_signature__ == '($cls, c)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.static_method.__text_signature__ == '(d)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.method.__text_signature__ == '($self, a)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.pyself_method.__text_signature__ == '($self, b)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.class_method.__text_signature__ == '($cls, c)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.static_method.__text_signature__ == '(d)'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -210,15 +210,15 @@ fn test_raw_identifiers() {
|
|||
fn r#method(&self) {}
|
||||
}
|
||||
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<MyClass>();
|
||||
Python::with_gil(|py| {
|
||||
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,
|
||||
typeobj,
|
||||
"typeobj.method.__text_signature__ == '($self)'"
|
||||
);
|
||||
py_assert!(
|
||||
py,
|
||||
typeobj,
|
||||
"typeobj.method.__text_signature__ == '($self)'"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@ impl UnsendableDictClass {
|
|||
#[test]
|
||||
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]
|
||||
fn test_unsendable_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = Py::new(py, UnsendableDictClass {}).unwrap();
|
||||
py_run!(py, inst, "assert inst.__dict__ == {}");
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(py, UnsendableDictClass {}).unwrap();
|
||||
py_run!(py, inst, "assert inst.__dict__ == {}");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(dict, unsendable, weakref)]
|
||||
|
@ -37,13 +37,13 @@ impl UnsendableDictClassWithWeakRef {
|
|||
#[test]
|
||||
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]
|
||||
fn test_unsendable_dict_with_weakref() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst = Py::new(py, UnsendableDictClassWithWeakRef {}).unwrap();
|
||||
py_run!(py, inst, "assert inst.__dict__ == {}");
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let inst = Py::new(py, UnsendableDictClassWithWeakRef {}).unwrap();
|
||||
py_run!(py, inst, "assert inst.__dict__ == {}");
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
"import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,24 +25,24 @@ impl MyClass {
|
|||
|
||||
#[test]
|
||||
fn variable_args() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let my_obj = py.get_type::<MyClass>();
|
||||
py_assert!(py, my_obj, "my_obj.test_args() == ()");
|
||||
py_assert!(py, my_obj, "my_obj.test_args(1) == (1,)");
|
||||
py_assert!(py, my_obj, "my_obj.test_args(1, 2) == (1, 2)");
|
||||
Python::with_gil(|py| {
|
||||
let my_obj = py.get_type::<MyClass>();
|
||||
py_assert!(py, my_obj, "my_obj.test_args() == ()");
|
||||
py_assert!(py, my_obj, "my_obj.test_args(1) == (1,)");
|
||||
py_assert!(py, my_obj, "my_obj.test_args(1, 2) == (1, 2)");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variable_kwargs() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let my_obj = py.get_type::<MyClass>();
|
||||
py_assert!(py, my_obj, "my_obj.test_kwargs() == None");
|
||||
py_assert!(py, my_obj, "my_obj.test_kwargs(test=1) == {'test': 1}");
|
||||
py_assert!(
|
||||
py,
|
||||
my_obj,
|
||||
"my_obj.test_kwargs(test1=1, test2=2) == {'test1':1, 'test2':2}"
|
||||
);
|
||||
Python::with_gil(|py| {
|
||||
let my_obj = py.get_type::<MyClass>();
|
||||
py_assert!(py, my_obj, "my_obj.test_kwargs() == None");
|
||||
py_assert!(py, my_obj, "my_obj.test_kwargs(test=1) == {'test': 1}");
|
||||
py_assert!(
|
||||
py,
|
||||
my_obj,
|
||||
"my_obj.test_kwargs(test1=1, test2=2) == {'test1':1, 'test2':2}"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,14 +25,14 @@ impl MutRefArg {
|
|||
|
||||
#[test]
|
||||
fn mut_ref_arg() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let inst1 = Py::new(py, MutRefArg { n: 0 }).unwrap();
|
||||
let inst2 = Py::new(py, MutRefArg { n: 0 }).unwrap();
|
||||
Python::with_gil(|py| {
|
||||
let inst1 = Py::new(py, MutRefArg { n: 0 }).unwrap();
|
||||
let inst2 = Py::new(py, MutRefArg { n: 0 }).unwrap();
|
||||
|
||||
py_run!(py, inst1 inst2, "inst1.set_other(inst2)");
|
||||
let inst2 = inst2.as_ref(py).borrow();
|
||||
assert_eq!(inst2.n, 100);
|
||||
py_run!(py, inst1 inst2, "inst1.set_other(inst2)");
|
||||
let inst2 = inst2.as_ref(py).borrow();
|
||||
assert_eq!(inst2.n, 100);
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -50,27 +50,25 @@ fn get_zero() -> PyUsize {
|
|||
/// Checks that we can use return a custom class in arbitrary function and use those functions
|
||||
/// both in rust and python
|
||||
fn return_custom_class() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
Python::with_gil(|py| {
|
||||
// Using from rust
|
||||
assert_eq!(get_zero().value, 0);
|
||||
|
||||
// Using from rust
|
||||
assert_eq!(get_zero().value, 0);
|
||||
|
||||
// Using from python
|
||||
let get_zero = wrap_pyfunction!(get_zero)(py).unwrap();
|
||||
py_assert!(py, get_zero, "get_zero().value == 0");
|
||||
// Using from python
|
||||
let get_zero = wrap_pyfunction!(get_zero)(py).unwrap();
|
||||
py_assert!(py, get_zero, "get_zero().value == 0");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn intopytuple_primitive() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let tup = (1, 2, "foo");
|
||||
py_assert!(py, tup, "tup == (1, 2, 'foo')");
|
||||
py_assert!(py, tup, "tup[0] == 1");
|
||||
py_assert!(py, tup, "tup[1] == 2");
|
||||
py_assert!(py, tup, "tup[2] == 'foo'");
|
||||
Python::with_gil(|py| {
|
||||
let tup = (1, 2, "foo");
|
||||
py_assert!(py, tup, "tup == (1, 2, 'foo')");
|
||||
py_assert!(py, tup, "tup[0] == 1");
|
||||
py_assert!(py, tup, "tup[1] == 2");
|
||||
py_assert!(py, tup, "tup[2] == 'foo'");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
@ -78,43 +76,40 @@ struct SimplePyClass {}
|
|||
|
||||
#[test]
|
||||
fn intopytuple_pyclass() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let tup = (
|
||||
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, "tup[0] != tup[1]");
|
||||
Python::with_gil(|py| {
|
||||
let tup = (
|
||||
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, "tup[0] != tup[1]");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pytuple_primitive_iter() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let tup = PyTuple::new(py, [1u32, 2, 3].iter());
|
||||
py_assert!(py, tup, "tup == (1, 2, 3)");
|
||||
Python::with_gil(|py| {
|
||||
let tup = PyTuple::new(py, [1u32, 2, 3].iter());
|
||||
py_assert!(py, tup, "tup == (1, 2, 3)");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pytuple_pyclass_iter() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let tup = PyTuple::new(
|
||||
py,
|
||||
[
|
||||
PyCell::new(py, SimplePyClass {}).unwrap(),
|
||||
PyCell::new(py, SimplePyClass {}).unwrap(),
|
||||
]
|
||||
.iter(),
|
||||
);
|
||||
py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'");
|
||||
py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[0]).__name__");
|
||||
py_assert!(py, tup, "tup[0] != tup[1]");
|
||||
Python::with_gil(|py| {
|
||||
let tup = PyTuple::new(
|
||||
py,
|
||||
[
|
||||
PyCell::new(py, SimplePyClass {}).unwrap(),
|
||||
PyCell::new(py, SimplePyClass {}).unwrap(),
|
||||
]
|
||||
.iter(),
|
||||
);
|
||||
py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'");
|
||||
py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[0]).__name__");
|
||||
py_assert!(py, tup, "tup[0] != tup[1]");
|
||||
});
|
||||
}
|
||||
|
||||
#[pyclass(dict, module = "test_module")]
|
||||
|
@ -149,16 +144,15 @@ fn add_module(py: Python<'_>, module: &PyModule) -> PyResult<()> {
|
|||
#[test]
|
||||
#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]
|
||||
fn test_pickle() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let module = PyModule::new(py, "test_module").unwrap();
|
||||
module.add_class::<PickleSupport>().unwrap();
|
||||
add_module(py, module).unwrap();
|
||||
let inst = PyCell::new(py, PickleSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
r#"
|
||||
Python::with_gil(|py| {
|
||||
let module = PyModule::new(py, "test_module").unwrap();
|
||||
module.add_class::<PickleSupport>().unwrap();
|
||||
add_module(py, module).unwrap();
|
||||
let inst = PyCell::new(py, PickleSupport {}).unwrap();
|
||||
py_run!(
|
||||
py,
|
||||
inst,
|
||||
r#"
|
||||
inst.a = 1
|
||||
assert inst.__dict__ == {'a': 1}
|
||||
|
||||
|
@ -167,7 +161,8 @@ fn test_pickle() {
|
|||
|
||||
assert inst2.__dict__ == {'a': 1}
|
||||
"#
|
||||
);
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// Testing https://github.com/PyO3/pyo3/issues/1106. A result type that
|
||||
|
@ -203,7 +198,7 @@ fn result_conversion_function() -> Result<(), MyError> {
|
|||
|
||||
#[test]
|
||||
fn test_result_conversion() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
wrap_pyfunction!(result_conversion_function)(py).unwrap();
|
||||
Python::with_gil(|py| {
|
||||
wrap_pyfunction!(result_conversion_function)(py).unwrap();
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue