deprecate `PyDict::new` constructor (#3823)
* deprecate `PyDict::new` * update benchmarks * convert `test_frompyobject`
This commit is contained in:
parent
c983dc9773
commit
c359f5ca1d
|
@ -86,7 +86,7 @@ struct RustyStruct {
|
||||||
# use pyo3::types::PyDict;
|
# use pyo3::types::PyDict;
|
||||||
# fn main() -> PyResult<()> {
|
# fn main() -> PyResult<()> {
|
||||||
# Python::with_gil(|py| -> PyResult<()> {
|
# Python::with_gil(|py| -> PyResult<()> {
|
||||||
# let dict = PyDict::new(py);
|
# let dict = PyDict::new_bound(py);
|
||||||
# dict.set_item("my_string", "test")?;
|
# dict.set_item("my_string", "test")?;
|
||||||
#
|
#
|
||||||
# let rustystruct: RustyStruct = dict.extract()?;
|
# let rustystruct: RustyStruct = dict.extract()?;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};
|
use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};
|
||||||
|
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
|
prelude::*,
|
||||||
types::{
|
types::{
|
||||||
PyBool, PyByteArray, PyBytes, PyDict, PyFloat, PyFrozenSet, PyInt, PyList, PyMapping,
|
PyBool, PyByteArray, PyBytes, PyDict, PyFloat, PyFrozenSet, PyInt, PyList, PyMapping,
|
||||||
PySequence, PySet, PyString, PyTuple,
|
PySequence, PySet, PyString, PyTuple,
|
||||||
},
|
},
|
||||||
PyAny, PyResult, Python,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
|
@ -27,7 +27,7 @@ enum ObjectType {
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_object_type(obj: &PyAny) -> ObjectType {
|
fn find_object_type(obj: &Bound<'_, PyAny>) -> ObjectType {
|
||||||
if obj.is_none() {
|
if obj.is_none() {
|
||||||
ObjectType::None
|
ObjectType::None
|
||||||
} else if obj.is_instance_of::<PyBool>() {
|
} else if obj.is_instance_of::<PyBool>() {
|
||||||
|
@ -63,17 +63,17 @@ fn find_object_type(obj: &PyAny) -> ObjectType {
|
||||||
|
|
||||||
fn bench_identify_object_type(b: &mut Bencher<'_>) {
|
fn bench_identify_object_type(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let obj = py.eval("object()", None, None).unwrap();
|
let obj = py.eval_bound("object()", None, None).unwrap();
|
||||||
|
|
||||||
b.iter(|| find_object_type(obj));
|
b.iter(|| find_object_type(&obj));
|
||||||
|
|
||||||
assert_eq!(find_object_type(obj), ObjectType::Unknown);
|
assert_eq!(find_object_type(&obj), ObjectType::Unknown);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench_collect_generic_iterator(b: &mut Bencher<'_>) {
|
fn bench_collect_generic_iterator(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let collection = py.eval("list(range(1 << 20))", None, None).unwrap();
|
let collection = py.eval_bound("list(range(1 << 20))", None, None).unwrap();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
collection
|
collection
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
use codspeed_criterion_compat::{black_box, criterion_group, criterion_main, Bencher, Criterion};
|
use codspeed_criterion_compat::{black_box, criterion_group, criterion_main, Bencher, Criterion};
|
||||||
|
|
||||||
use pyo3::{types::PyDict, PyAny, Python};
|
use pyo3::prelude::*;
|
||||||
|
use pyo3::types::PyDict;
|
||||||
|
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
|
|
||||||
fn extract_bigint_extract_fail(bench: &mut Bencher<'_>) {
|
fn extract_bigint_extract_fail(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let d = PyDict::new(py) as &PyAny;
|
let d = PyDict::new_bound(py).into_any();
|
||||||
|
|
||||||
bench.iter(|| match black_box(d).extract::<BigInt>() {
|
bench.iter(|| match black_box(&d).extract::<BigInt>() {
|
||||||
Ok(v) => panic!("should err {}", v),
|
Ok(v) => panic!("should err {}", v),
|
||||||
Err(e) => black_box(e),
|
Err(e) => black_box(e),
|
||||||
});
|
});
|
||||||
|
@ -17,10 +18,10 @@ fn extract_bigint_extract_fail(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_bigint_small(bench: &mut Bencher<'_>) {
|
fn extract_bigint_small(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let int = py.eval("-42", None, None).unwrap();
|
let int = py.eval_bound("-42", None, None).unwrap();
|
||||||
|
|
||||||
bench.iter(|| {
|
bench.iter(|| {
|
||||||
let v = black_box(int).extract::<BigInt>().unwrap();
|
let v = black_box(&int).extract::<BigInt>().unwrap();
|
||||||
black_box(v);
|
black_box(v);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -28,10 +29,10 @@ fn extract_bigint_small(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_bigint_big_negative(bench: &mut Bencher<'_>) {
|
fn extract_bigint_big_negative(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let int = py.eval("-10**300", None, None).unwrap();
|
let int = py.eval_bound("-10**300", None, None).unwrap();
|
||||||
|
|
||||||
bench.iter(|| {
|
bench.iter(|| {
|
||||||
let v = black_box(int).extract::<BigInt>().unwrap();
|
let v = black_box(&int).extract::<BigInt>().unwrap();
|
||||||
black_box(v);
|
black_box(v);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -39,10 +40,10 @@ fn extract_bigint_big_negative(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_bigint_big_positive(bench: &mut Bencher<'_>) {
|
fn extract_bigint_big_positive(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let int = py.eval("10**300", None, None).unwrap();
|
let int = py.eval_bound("10**300", None, None).unwrap();
|
||||||
|
|
||||||
bench.iter(|| {
|
bench.iter(|| {
|
||||||
let v = black_box(int).extract::<BigInt>().unwrap();
|
let v = black_box(&int).extract::<BigInt>().unwrap();
|
||||||
black_box(v);
|
black_box(v);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -50,10 +51,10 @@ fn extract_bigint_big_positive(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_bigint_huge_negative(bench: &mut Bencher<'_>) {
|
fn extract_bigint_huge_negative(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let int = py.eval("-10**3000", None, None).unwrap();
|
let int = py.eval_bound("-10**3000", None, None).unwrap();
|
||||||
|
|
||||||
bench.iter(|| {
|
bench.iter(|| {
|
||||||
let v = black_box(int).extract::<BigInt>().unwrap();
|
let v = black_box(&int).extract::<BigInt>().unwrap();
|
||||||
black_box(v);
|
black_box(v);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -61,10 +62,10 @@ fn extract_bigint_huge_negative(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_bigint_huge_positive(bench: &mut Bencher<'_>) {
|
fn extract_bigint_huge_positive(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let int = py.eval("10**3000", None, None).unwrap();
|
let int = py.eval_bound("10**3000", None, None).unwrap();
|
||||||
|
|
||||||
bench.iter(|| {
|
bench.iter(|| {
|
||||||
let v = black_box(int).extract::<BigInt>().unwrap();
|
let v = black_box(&int).extract::<BigInt>().unwrap();
|
||||||
black_box(v);
|
black_box(v);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,20 +6,20 @@ use rust_decimal::Decimal;
|
||||||
|
|
||||||
fn decimal_via_extract(b: &mut Bencher<'_>) {
|
fn decimal_via_extract(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = PyDict::new(py);
|
let locals = PyDict::new_bound(py);
|
||||||
py.run(
|
py.run_bound(
|
||||||
r#"
|
r#"
|
||||||
import decimal
|
import decimal
|
||||||
py_dec = decimal.Decimal("0.0")
|
py_dec = decimal.Decimal("0.0")
|
||||||
"#,
|
"#,
|
||||||
None,
|
None,
|
||||||
Some(locals),
|
Some(&locals),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let py_dec = locals.get_item("py_dec").unwrap().unwrap();
|
let py_dec = locals.get_item("py_dec").unwrap().unwrap();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let _: Decimal = black_box(py_dec).extract().unwrap();
|
let _: Decimal = black_box(&py_dec).extract().unwrap();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ use std::hint::black_box;
|
||||||
fn iter_dict(b: &mut Bencher<'_>) {
|
fn iter_dict(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
const LEN: usize = 100_000;
|
const LEN: usize = 100_000;
|
||||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py);
|
||||||
let mut sum = 0;
|
let mut sum = 0;
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
for (k, _v) in dict {
|
for (k, _v) in dict.iter() {
|
||||||
let i: u64 = k.extract().unwrap();
|
let i: u64 = k.extract().unwrap();
|
||||||
sum += i;
|
sum += i;
|
||||||
}
|
}
|
||||||
|
@ -22,14 +22,14 @@ fn iter_dict(b: &mut Bencher<'_>) {
|
||||||
fn dict_new(b: &mut Bencher<'_>) {
|
fn dict_new(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
const LEN: usize = 50_000;
|
const LEN: usize = 50_000;
|
||||||
b.iter(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py));
|
b.iter_with_large_drop(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dict_get_item(b: &mut Bencher<'_>) {
|
fn dict_get_item(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
const LEN: usize = 50_000;
|
const LEN: usize = 50_000;
|
||||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py);
|
||||||
let mut sum = 0;
|
let mut sum = 0;
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
for i in 0..LEN {
|
for i in 0..LEN {
|
||||||
|
@ -47,16 +47,16 @@ fn dict_get_item(b: &mut Bencher<'_>) {
|
||||||
fn extract_hashmap(b: &mut Bencher<'_>) {
|
fn extract_hashmap(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
const LEN: usize = 100_000;
|
const LEN: usize = 100_000;
|
||||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py);
|
||||||
b.iter(|| HashMap::<u64, u64>::extract(dict));
|
b.iter(|| HashMap::<u64, u64>::extract_bound(&dict));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_btreemap(b: &mut Bencher<'_>) {
|
fn extract_btreemap(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
const LEN: usize = 100_000;
|
const LEN: usize = 100_000;
|
||||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py);
|
||||||
b.iter(|| BTreeMap::<u64, u64>::extract(dict));
|
b.iter(|| BTreeMap::<u64, u64>::extract_bound(&dict));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,19 +64,15 @@ fn extract_btreemap(b: &mut Bencher<'_>) {
|
||||||
fn extract_hashbrown_map(b: &mut Bencher<'_>) {
|
fn extract_hashbrown_map(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
const LEN: usize = 100_000;
|
const LEN: usize = 100_000;
|
||||||
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
|
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py);
|
||||||
b.iter(|| hashbrown::HashMap::<u64, u64>::extract(dict));
|
b.iter(|| hashbrown::HashMap::<u64, u64>::extract_bound(&dict));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mapping_from_dict(b: &mut Bencher<'_>) {
|
fn mapping_from_dict(b: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
const LEN: usize = 100_000;
|
const LEN: usize = 100_000;
|
||||||
let dict = &(0..LEN as u64)
|
let dict = &(0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py);
|
||||||
.map(|i| (i, i * 2))
|
|
||||||
.into_py_dict(py)
|
|
||||||
.to_object(py)
|
|
||||||
.into_bound(py);
|
|
||||||
b.iter(|| black_box(dict).downcast::<PyMapping>().unwrap());
|
b.iter(|| black_box(dict).downcast::<PyMapping>().unwrap());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ use codspeed_criterion_compat::{black_box, criterion_group, criterion_main, Benc
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
types::{PyDict, PyFloat, PyInt, PyString},
|
types::{PyDict, PyFloat, PyInt, PyString},
|
||||||
IntoPy, PyAny, PyObject, Python,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn extract_str_extract_success(bench: &mut Bencher<'_>) {
|
fn extract_str_extract_success(bench: &mut Bencher<'_>) {
|
||||||
|
@ -16,9 +15,9 @@ fn extract_str_extract_success(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_str_extract_fail(bench: &mut Bencher<'_>) {
|
fn extract_str_extract_fail(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let d = PyDict::new(py) as &PyAny;
|
let d = PyDict::new_bound(py).into_any();
|
||||||
|
|
||||||
bench.iter(|| match black_box(d).extract::<&str>() {
|
bench.iter(|| match black_box(&d).extract::<&str>() {
|
||||||
Ok(v) => panic!("should err {}", v),
|
Ok(v) => panic!("should err {}", v),
|
||||||
Err(e) => black_box(e),
|
Err(e) => black_box(e),
|
||||||
});
|
});
|
||||||
|
@ -39,9 +38,9 @@ fn extract_str_downcast_success(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_str_downcast_fail(bench: &mut Bencher<'_>) {
|
fn extract_str_downcast_fail(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let d = PyDict::new(py) as &PyAny;
|
let d = PyDict::new_bound(py).into_any();
|
||||||
|
|
||||||
bench.iter(|| match black_box(d).downcast::<PyString>() {
|
bench.iter(|| match black_box(&d).downcast::<PyString>() {
|
||||||
Ok(v) => panic!("should err {}", v),
|
Ok(v) => panic!("should err {}", v),
|
||||||
Err(e) => black_box(e),
|
Err(e) => black_box(e),
|
||||||
});
|
});
|
||||||
|
@ -62,9 +61,9 @@ fn extract_int_extract_success(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_int_extract_fail(bench: &mut Bencher<'_>) {
|
fn extract_int_extract_fail(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let d = PyDict::new(py) as &PyAny;
|
let d = PyDict::new_bound(py).into_any();
|
||||||
|
|
||||||
bench.iter(|| match black_box(d).extract::<i64>() {
|
bench.iter(|| match black_box(&d).extract::<i64>() {
|
||||||
Ok(v) => panic!("should err {}", v),
|
Ok(v) => panic!("should err {}", v),
|
||||||
Err(e) => black_box(e),
|
Err(e) => black_box(e),
|
||||||
});
|
});
|
||||||
|
@ -86,9 +85,9 @@ fn extract_int_downcast_success(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_int_downcast_fail(bench: &mut Bencher<'_>) {
|
fn extract_int_downcast_fail(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let d = PyDict::new(py) as &PyAny;
|
let d = PyDict::new_bound(py).into_any();
|
||||||
|
|
||||||
bench.iter(|| match black_box(d).downcast::<PyInt>() {
|
bench.iter(|| match black_box(&d).downcast::<PyInt>() {
|
||||||
Ok(v) => panic!("should err {}", v),
|
Ok(v) => panic!("should err {}", v),
|
||||||
Err(e) => black_box(e),
|
Err(e) => black_box(e),
|
||||||
});
|
});
|
||||||
|
@ -109,9 +108,9 @@ fn extract_float_extract_success(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_float_extract_fail(bench: &mut Bencher<'_>) {
|
fn extract_float_extract_fail(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let d = PyDict::new(py) as &PyAny;
|
let d = PyDict::new_bound(py).into_any();
|
||||||
|
|
||||||
bench.iter(|| match black_box(d).extract::<f64>() {
|
bench.iter(|| match black_box(&d).extract::<f64>() {
|
||||||
Ok(v) => panic!("should err {}", v),
|
Ok(v) => panic!("should err {}", v),
|
||||||
Err(e) => black_box(e),
|
Err(e) => black_box(e),
|
||||||
});
|
});
|
||||||
|
@ -133,9 +132,9 @@ fn extract_float_downcast_success(bench: &mut Bencher<'_>) {
|
||||||
|
|
||||||
fn extract_float_downcast_fail(bench: &mut Bencher<'_>) {
|
fn extract_float_downcast_fail(bench: &mut Bencher<'_>) {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let d = PyDict::new(py) as &PyAny;
|
let d = PyDict::new_bound(py).into_any();
|
||||||
|
|
||||||
bench.iter(|| match black_box(d).downcast::<PyFloat>() {
|
bench.iter(|| match black_box(&d).downcast::<PyFloat>() {
|
||||||
Ok(v) => panic!("should err {}", v),
|
Ok(v) => panic!("should err {}", v),
|
||||||
Err(e) => black_box(e),
|
Err(e) => black_box(e),
|
||||||
});
|
});
|
||||||
|
|
|
@ -85,14 +85,18 @@ macro_rules! bigint_conversion {
|
||||||
let bytes = $to_bytes(self);
|
let bytes = $to_bytes(self);
|
||||||
let bytes_obj = PyBytes::new_bound(py, &bytes);
|
let bytes_obj = PyBytes::new_bound(py, &bytes);
|
||||||
let kwargs = if $is_signed > 0 {
|
let kwargs = if $is_signed > 0 {
|
||||||
let kwargs = PyDict::new(py);
|
let kwargs = PyDict::new_bound(py);
|
||||||
kwargs.set_item(crate::intern!(py, "signed"), true).unwrap();
|
kwargs.set_item(crate::intern!(py, "signed"), true).unwrap();
|
||||||
Some(kwargs)
|
Some(kwargs)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
py.get_type::<PyLong>()
|
py.get_type::<PyLong>()
|
||||||
.call_method("from_bytes", (bytes_obj, "little"), kwargs)
|
.call_method(
|
||||||
|
"from_bytes",
|
||||||
|
(bytes_obj, "little"),
|
||||||
|
kwargs.as_ref().map(crate::Bound::as_gil_ref),
|
||||||
|
)
|
||||||
.expect("int.from_bytes() failed during to_object()") // FIXME: #1813 or similar
|
.expect("int.from_bytes() failed during to_object()") // FIXME: #1813 or similar
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_smallvec_from_py_object_fails() {
|
fn test_smallvec_from_py_object_fails() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new_bound(py);
|
||||||
let sv: PyResult<SmallVec<[u64; 8]>> = dict.extract();
|
let sv: PyResult<SmallVec<[u64; 8]>> = dict.extract();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sv.unwrap_err().to_string(),
|
sv.unwrap_err().to_string(),
|
||||||
|
|
|
@ -337,9 +337,11 @@ mod tests {
|
||||||
|
|
||||||
fn max_datetime(py: Python<'_>) -> &PyAny {
|
fn max_datetime(py: Python<'_>) -> &PyAny {
|
||||||
let naive_max = datetime_class(py).getattr("max").unwrap();
|
let naive_max = datetime_class(py).getattr("max").unwrap();
|
||||||
let kargs = PyDict::new(py);
|
let kargs = PyDict::new_bound(py);
|
||||||
kargs.set_item("tzinfo", tz_utc(py)).unwrap();
|
kargs.set_item("tzinfo", tz_utc(py)).unwrap();
|
||||||
naive_max.call_method("replace", (), Some(kargs)).unwrap()
|
naive_max
|
||||||
|
.call_method("replace", (), Some(kargs.as_gil_ref()))
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -681,7 +681,7 @@ impl<'py> VarkeywordsHandler<'py> for DictVarkeywords {
|
||||||
_function_description: &FunctionDescription,
|
_function_description: &FunctionDescription,
|
||||||
) -> PyResult<()> {
|
) -> PyResult<()> {
|
||||||
varkeywords
|
varkeywords
|
||||||
.get_or_insert_with(|| PyDict::new(name.py()))
|
.get_or_insert_with(|| PyDict::new_bound(name.py()).into_gil_ref())
|
||||||
.set_item(name, value)
|
.set_item(name, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -634,7 +634,7 @@ impl<T> IntoPy<PyObject> for Borrowed<'_, '_, T> {
|
||||||
/// #[new]
|
/// #[new]
|
||||||
/// fn __new__() -> Foo {
|
/// fn __new__() -> Foo {
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let dict: Py<PyDict> = PyDict::new(py).into();
|
/// let dict: Py<PyDict> = PyDict::new_bound(py).unbind();
|
||||||
/// Foo { inner: dict }
|
/// Foo { inner: dict }
|
||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
|
@ -706,7 +706,7 @@ impl<T> IntoPy<PyObject> for Borrowed<'_, '_, T> {
|
||||||
///
|
///
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let first: Py<PyDict> = PyDict::new(py).into();
|
/// let first: Py<PyDict> = PyDict::new_bound(py).unbind();
|
||||||
///
|
///
|
||||||
/// // All of these are valid syntax
|
/// // All of these are valid syntax
|
||||||
/// let second = Py::clone_ref(&first, py);
|
/// let second = Py::clone_ref(&first, py);
|
||||||
|
@ -1130,7 +1130,7 @@ impl<T> Py<T> {
|
||||||
///
|
///
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let first: Py<PyDict> = PyDict::new(py).into();
|
/// let first: Py<PyDict> = PyDict::new_bound(py).unbind();
|
||||||
/// let second = Py::clone_ref(&first, py);
|
/// let second = Py::clone_ref(&first, py);
|
||||||
///
|
///
|
||||||
/// // Both point to the same object
|
/// // Both point to the same object
|
||||||
|
@ -1683,7 +1683,7 @@ impl PyObject {
|
||||||
/// use pyo3::types::{PyDict, PyList};
|
/// use pyo3::types::{PyDict, PyList};
|
||||||
///
|
///
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let any: PyObject = PyDict::new(py).into();
|
/// let any: PyObject = PyDict::new_bound(py).into();
|
||||||
///
|
///
|
||||||
/// assert!(any.downcast::<PyDict>(py).is_ok());
|
/// assert!(any.downcast::<PyDict>(py).is_ok());
|
||||||
/// assert!(any.downcast::<PyList>(py).is_err());
|
/// assert!(any.downcast::<PyList>(py).is_err());
|
||||||
|
|
|
@ -38,14 +38,14 @@ pub fn dumps<'py>(
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// # use pyo3::{marshal, types::PyDict};
|
/// # use pyo3::{marshal, types::PyDict, prelude::PyDictMethods};
|
||||||
/// # pyo3::Python::with_gil(|py| {
|
/// # pyo3::Python::with_gil(|py| {
|
||||||
/// let dict = PyDict::new(py);
|
/// let dict = PyDict::new_bound(py);
|
||||||
/// dict.set_item("aap", "noot").unwrap();
|
/// dict.set_item("aap", "noot").unwrap();
|
||||||
/// dict.set_item("mies", "wim").unwrap();
|
/// dict.set_item("mies", "wim").unwrap();
|
||||||
/// dict.set_item("zus", "jet").unwrap();
|
/// dict.set_item("zus", "jet").unwrap();
|
||||||
///
|
///
|
||||||
/// let bytes = marshal::dumps_bound(py, dict, marshal::VERSION);
|
/// let bytes = marshal::dumps_bound(py, &dict, marshal::VERSION);
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn dumps_bound<'py>(
|
pub fn dumps_bound<'py>(
|
||||||
|
@ -90,20 +90,20 @@ where
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::types::{bytes::PyBytesMethods, PyDict};
|
use crate::types::{bytes::PyBytesMethods, dict::PyDictMethods, PyDict};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn marshal_roundtrip() {
|
fn marshal_roundtrip() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new_bound(py);
|
||||||
dict.set_item("aap", "noot").unwrap();
|
dict.set_item("aap", "noot").unwrap();
|
||||||
dict.set_item("mies", "wim").unwrap();
|
dict.set_item("mies", "wim").unwrap();
|
||||||
dict.set_item("zus", "jet").unwrap();
|
dict.set_item("zus", "jet").unwrap();
|
||||||
|
|
||||||
let pybytes = dumps_bound(py, dict, VERSION).expect("marshalling failed");
|
let pybytes = dumps_bound(py, &dict, VERSION).expect("marshalling failed");
|
||||||
let deserialized = loads_bound(py, pybytes.as_bytes()).expect("unmarshalling failed");
|
let deserialized = loads_bound(py, pybytes.as_bytes()).expect("unmarshalling failed");
|
||||||
|
|
||||||
assert!(equal(py, dict, &deserialized));
|
assert!(equal(py, &dict, &deserialized));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/sync.rs
14
src/sync.rs
|
@ -210,11 +210,11 @@ impl GILOnceCell<Py<PyType>> {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use pyo3::intern;
|
/// use pyo3::intern;
|
||||||
/// # use pyo3::{pyfunction, types::PyDict, wrap_pyfunction, PyResult, Python};
|
/// # use pyo3::{pyfunction, types::PyDict, wrap_pyfunction, PyResult, Python, prelude::PyDictMethods, Bound};
|
||||||
///
|
///
|
||||||
/// #[pyfunction]
|
/// #[pyfunction]
|
||||||
/// fn create_dict(py: Python<'_>) -> PyResult<&PyDict> {
|
/// fn create_dict(py: Python<'_>) -> PyResult<Bound<'_, PyDict>> {
|
||||||
/// let dict = PyDict::new(py);
|
/// let dict = PyDict::new_bound(py);
|
||||||
/// // 👇 A new `PyString` is created
|
/// // 👇 A new `PyString` is created
|
||||||
/// // for every call of this function.
|
/// // for every call of this function.
|
||||||
/// dict.set_item("foo", 42)?;
|
/// dict.set_item("foo", 42)?;
|
||||||
|
@ -222,8 +222,8 @@ impl GILOnceCell<Py<PyType>> {
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// #[pyfunction]
|
/// #[pyfunction]
|
||||||
/// fn create_dict_faster(py: Python<'_>) -> PyResult<&PyDict> {
|
/// fn create_dict_faster(py: Python<'_>) -> PyResult<Bound<'_, PyDict>> {
|
||||||
/// let dict = PyDict::new(py);
|
/// let dict = PyDict::new_bound(py);
|
||||||
/// // 👇 A `PyString` is created once and reused
|
/// // 👇 A `PyString` is created once and reused
|
||||||
/// // for the lifetime of the program.
|
/// // for the lifetime of the program.
|
||||||
/// dict.set_item(intern!(py, "foo"), 42)?;
|
/// dict.set_item(intern!(py, "foo"), 42)?;
|
||||||
|
@ -270,7 +270,7 @@ impl Interned {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::types::PyDict;
|
use crate::types::{any::PyAnyMethods, dict::PyDictMethods, PyDict};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_intern() {
|
fn test_intern() {
|
||||||
|
@ -279,7 +279,7 @@ mod tests {
|
||||||
let foo2 = intern!(py, "foo");
|
let foo2 = intern!(py, "foo");
|
||||||
let foo3 = intern!(py, stringify!(foo));
|
let foo3 = intern!(py, stringify!(foo));
|
||||||
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new_bound(py);
|
||||||
dict.set_item(foo1, 42_usize).unwrap();
|
dict.set_item(foo1, 42_usize).unwrap();
|
||||||
assert!(dict.contains(foo2).unwrap());
|
assert!(dict.contains(foo2).unwrap());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -388,9 +388,9 @@ impl PyAny {
|
||||||
/// let module = PyModule::from_code(py, CODE, "", "")?;
|
/// let module = PyModule::from_code(py, CODE, "", "")?;
|
||||||
/// let fun = module.getattr("function")?;
|
/// let fun = module.getattr("function")?;
|
||||||
/// let args = ("hello",);
|
/// let args = ("hello",);
|
||||||
/// let kwargs = PyDict::new(py);
|
/// let kwargs = PyDict::new_bound(py);
|
||||||
/// kwargs.set_item("cruel", "world")?;
|
/// kwargs.set_item("cruel", "world")?;
|
||||||
/// let result = fun.call(args, Some(kwargs))?;
|
/// let result = fun.call(args, Some(kwargs.as_gil_ref()))?;
|
||||||
/// assert_eq!(result.extract::<&str>()?, "called with args and kwargs");
|
/// assert_eq!(result.extract::<&str>()?, "called with args and kwargs");
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// })
|
/// })
|
||||||
|
@ -488,9 +488,9 @@ impl PyAny {
|
||||||
/// let module = PyModule::from_code(py, CODE, "", "")?;
|
/// let module = PyModule::from_code(py, CODE, "", "")?;
|
||||||
/// let instance = module.getattr("a")?;
|
/// let instance = module.getattr("a")?;
|
||||||
/// let args = ("hello",);
|
/// let args = ("hello",);
|
||||||
/// let kwargs = PyDict::new(py);
|
/// let kwargs = PyDict::new_bound(py);
|
||||||
/// kwargs.set_item("cruel", "world")?;
|
/// kwargs.set_item("cruel", "world")?;
|
||||||
/// let result = instance.call_method("method", args, Some(kwargs))?;
|
/// let result = instance.call_method("method", args, Some(kwargs.as_gil_ref()))?;
|
||||||
/// assert_eq!(result.extract::<&str>()?, "called with args and kwargs");
|
/// assert_eq!(result.extract::<&str>()?, "called with args and kwargs");
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// })
|
/// })
|
||||||
|
@ -691,9 +691,9 @@ impl PyAny {
|
||||||
/// use pyo3::types::{PyDict, PyList};
|
/// use pyo3::types::{PyDict, PyList};
|
||||||
///
|
///
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let dict = PyDict::new(py);
|
/// let dict = PyDict::new_bound(py);
|
||||||
/// assert!(dict.is_instance_of::<PyAny>());
|
/// assert!(dict.is_instance_of::<PyAny>());
|
||||||
/// let any: &PyAny = dict.as_ref();
|
/// let any = dict.as_any();
|
||||||
///
|
///
|
||||||
/// assert!(any.downcast::<PyDict>().is_ok());
|
/// assert!(any.downcast::<PyDict>().is_ok());
|
||||||
/// assert!(any.downcast::<PyList>().is_err());
|
/// assert!(any.downcast::<PyList>().is_err());
|
||||||
|
@ -1268,9 +1268,9 @@ pub trait PyAnyMethods<'py> {
|
||||||
/// let module = PyModule::from_code(py, CODE, "", "")?;
|
/// let module = PyModule::from_code(py, CODE, "", "")?;
|
||||||
/// let fun = module.getattr("function")?;
|
/// let fun = module.getattr("function")?;
|
||||||
/// let args = ("hello",);
|
/// let args = ("hello",);
|
||||||
/// let kwargs = PyDict::new(py);
|
/// let kwargs = PyDict::new_bound(py);
|
||||||
/// kwargs.set_item("cruel", "world")?;
|
/// kwargs.set_item("cruel", "world")?;
|
||||||
/// let result = fun.call(args, Some(kwargs))?;
|
/// let result = fun.call(args, Some(kwargs.as_gil_ref()))?;
|
||||||
/// assert_eq!(result.extract::<&str>()?, "called with args and kwargs");
|
/// assert_eq!(result.extract::<&str>()?, "called with args and kwargs");
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// })
|
/// })
|
||||||
|
@ -1360,9 +1360,9 @@ pub trait PyAnyMethods<'py> {
|
||||||
/// let module = PyModule::from_code(py, CODE, "", "")?;
|
/// let module = PyModule::from_code(py, CODE, "", "")?;
|
||||||
/// let instance = module.getattr("a")?;
|
/// let instance = module.getattr("a")?;
|
||||||
/// let args = ("hello",);
|
/// let args = ("hello",);
|
||||||
/// let kwargs = PyDict::new(py);
|
/// let kwargs = PyDict::new_bound(py);
|
||||||
/// kwargs.set_item("cruel", "world")?;
|
/// kwargs.set_item("cruel", "world")?;
|
||||||
/// let result = instance.call_method("method", args, Some(kwargs))?;
|
/// let result = instance.call_method("method", args, Some(kwargs.as_gil_ref()))?;
|
||||||
/// assert_eq!(result.extract::<&str>()?, "called with args and kwargs");
|
/// assert_eq!(result.extract::<&str>()?, "called with args and kwargs");
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// })
|
/// })
|
||||||
|
@ -1519,9 +1519,9 @@ pub trait PyAnyMethods<'py> {
|
||||||
/// use pyo3::types::{PyDict, PyList};
|
/// use pyo3::types::{PyDict, PyList};
|
||||||
///
|
///
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let dict = PyDict::new(py);
|
/// let dict = PyDict::new_bound(py);
|
||||||
/// assert!(dict.is_instance_of::<PyAny>());
|
/// assert!(dict.is_instance_of::<PyAny>());
|
||||||
/// let any: &PyAny = dict.as_ref();
|
/// let any = dict.as_any();
|
||||||
///
|
///
|
||||||
/// assert!(any.downcast::<PyDict>().is_ok());
|
/// assert!(any.downcast::<PyDict>().is_ok());
|
||||||
/// assert!(any.downcast::<PyList>().is_err());
|
/// assert!(any.downcast::<PyList>().is_err());
|
||||||
|
|
|
@ -57,6 +57,13 @@ pyobject_native_type_core!(
|
||||||
|
|
||||||
impl PyDict {
|
impl PyDict {
|
||||||
/// Deprecated form of [`new_bound`][PyDict::new_bound].
|
/// Deprecated form of [`new_bound`][PyDict::new_bound].
|
||||||
|
#[cfg_attr(
|
||||||
|
not(feature = "gil-refs"),
|
||||||
|
deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "`PyDict::new` will be replaced by `PyDict::new_bound` in a future PyO3 version"
|
||||||
|
)
|
||||||
|
)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(py: Python<'_>) -> &PyDict {
|
pub fn new(py: Python<'_>) -> &PyDict {
|
||||||
Self::new_bound(py).into_gil_ref()
|
Self::new_bound(py).into_gil_ref()
|
||||||
|
|
|
@ -78,7 +78,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dict_is_not_ellipsis() {
|
fn test_dict_is_not_ellipsis() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
assert!(PyDict::new(py).downcast::<PyEllipsis>().is_err());
|
assert!(PyDict::new_bound(py).downcast::<PyEllipsis>().is_err());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dict_is_not_none() {
|
fn test_dict_is_not_none() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
assert!(PyDict::new(py).downcast::<PyNone>().is_err());
|
assert!(PyDict::new_bound(py).downcast::<PyNone>().is_err());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dict_is_not_notimplemented() {
|
fn test_dict_is_not_notimplemented() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
assert!(PyDict::new(py).downcast::<PyNotImplemented>().is_err());
|
assert!(PyDict::new_bound(py)
|
||||||
|
.downcast::<PyNotImplemented>()
|
||||||
|
.is_err());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,13 @@ fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, FromPyObject)]
|
#[derive(Debug, FromPyObject)]
|
||||||
pub struct A<'a> {
|
pub struct A<'py> {
|
||||||
#[pyo3(attribute)]
|
#[pyo3(attribute)]
|
||||||
s: String,
|
s: String,
|
||||||
#[pyo3(item)]
|
#[pyo3(item)]
|
||||||
t: &'a PyString,
|
t: Bound<'py, PyString>,
|
||||||
#[pyo3(attribute("foo"))]
|
#[pyo3(attribute("foo"))]
|
||||||
p: &'a PyAny,
|
p: Bound<'py, PyAny>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
@ -58,8 +58,9 @@ fn test_named_fields_struct() {
|
||||||
foo: None,
|
foo: None,
|
||||||
};
|
};
|
||||||
let py_c = Py::new(py, pya).unwrap();
|
let py_c = Py::new(py, pya).unwrap();
|
||||||
let a: A<'_> =
|
let a = py_c
|
||||||
FromPyObject::extract(py_c.as_ref(py)).expect("Failed to extract A from PyA");
|
.extract::<A<'_>>(py)
|
||||||
|
.expect("Failed to extract A from PyA");
|
||||||
assert_eq!(a.s, "foo");
|
assert_eq!(a.s, "foo");
|
||||||
assert_eq!(a.t.to_string_lossy(), "bar");
|
assert_eq!(a.t.to_string_lossy(), "bar");
|
||||||
assert!(a.p.is_none());
|
assert!(a.p.is_none());
|
||||||
|
@ -76,10 +77,12 @@ pub struct B {
|
||||||
fn test_transparent_named_field_struct() {
|
fn test_transparent_named_field_struct() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let test: PyObject = "test".into_py(py);
|
let test: PyObject = "test".into_py(py);
|
||||||
let b: B = FromPyObject::extract(test.as_ref(py)).expect("Failed to extract B from String");
|
let b = test
|
||||||
|
.extract::<B>(py)
|
||||||
|
.expect("Failed to extract B from String");
|
||||||
assert_eq!(b.test, "test");
|
assert_eq!(b.test, "test");
|
||||||
let test: PyObject = 1.into_py(py);
|
let test: PyObject = 1.into_py(py);
|
||||||
let b = B::extract(test.as_ref(py));
|
let b = test.extract::<B>(py);
|
||||||
assert!(b.is_err());
|
assert!(b.is_err());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -94,12 +97,14 @@ pub struct D<T> {
|
||||||
fn test_generic_transparent_named_field_struct() {
|
fn test_generic_transparent_named_field_struct() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let test: PyObject = "test".into_py(py);
|
let test: PyObject = "test".into_py(py);
|
||||||
let d: D<String> =
|
let d = test
|
||||||
D::extract(test.as_ref(py)).expect("Failed to extract D<String> from String");
|
.extract::<D<String>>(py)
|
||||||
|
.expect("Failed to extract D<String> from String");
|
||||||
assert_eq!(d.test, "test");
|
assert_eq!(d.test, "test");
|
||||||
let test = 1usize.into_py(py);
|
let test = 1usize.into_py(py);
|
||||||
let d: D<usize> =
|
let d = test
|
||||||
D::extract(test.as_ref(py)).expect("Failed to extract D<usize> from String");
|
.extract::<D<usize>>(py)
|
||||||
|
.expect("Failed to extract D<usize> from String");
|
||||||
assert_eq!(d.test, 1);
|
assert_eq!(d.test, 1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -128,11 +133,12 @@ fn test_generic_named_fields_struct() {
|
||||||
}
|
}
|
||||||
.into_py(py);
|
.into_py(py);
|
||||||
|
|
||||||
let e: E<String, usize> =
|
let e = pye
|
||||||
E::extract(pye.as_ref(py)).expect("Failed to extract E<String, usize> from PyE");
|
.extract::<E<String, usize>>(py)
|
||||||
|
.expect("Failed to extract E<String, usize> from PyE");
|
||||||
assert_eq!(e.test, "test");
|
assert_eq!(e.test, "test");
|
||||||
assert_eq!(e.test2, 2);
|
assert_eq!(e.test2, 2);
|
||||||
let e = E::<usize, usize>::extract(pye.as_ref(py));
|
let e = pye.extract::<E<usize, usize>>(py);
|
||||||
assert!(e.is_err());
|
assert!(e.is_err());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -151,7 +157,7 @@ fn test_named_field_with_ext_fn() {
|
||||||
test2: 0,
|
test2: 0,
|
||||||
}
|
}
|
||||||
.into_py(py);
|
.into_py(py);
|
||||||
let c = C::extract(pyc.as_ref(py)).expect("Failed to extract C from PyE");
|
let c = pyc.extract::<C>(py).expect("Failed to extract C from PyE");
|
||||||
assert_eq!(c.test, "foo");
|
assert_eq!(c.test, "foo");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -163,10 +169,12 @@ pub struct Tuple(String, usize);
|
||||||
fn test_tuple_struct() {
|
fn test_tuple_struct() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let tup = PyTuple::new_bound(py, &[1.into_py(py), "test".into_py(py)]);
|
let tup = PyTuple::new_bound(py, &[1.into_py(py), "test".into_py(py)]);
|
||||||
let tup = Tuple::extract(tup.as_gil_ref());
|
let tup = tup.extract::<Tuple>();
|
||||||
assert!(tup.is_err());
|
assert!(tup.is_err());
|
||||||
let tup = PyTuple::new_bound(py, &["test".into_py(py), 1.into_py(py)]);
|
let tup = PyTuple::new_bound(py, &["test".into_py(py), 1.into_py(py)]);
|
||||||
let tup = Tuple::extract(tup.as_gil_ref()).expect("Failed to extract Tuple from PyTuple");
|
let tup = tup
|
||||||
|
.extract::<Tuple>()
|
||||||
|
.expect("Failed to extract Tuple from PyTuple");
|
||||||
assert_eq!(tup.0, "test");
|
assert_eq!(tup.0, "test");
|
||||||
assert_eq!(tup.1, 1);
|
assert_eq!(tup.1, 1);
|
||||||
});
|
});
|
||||||
|
@ -179,10 +187,11 @@ pub struct TransparentTuple(String);
|
||||||
fn test_transparent_tuple_struct() {
|
fn test_transparent_tuple_struct() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let tup: PyObject = 1.into_py(py);
|
let tup: PyObject = 1.into_py(py);
|
||||||
let tup = TransparentTuple::extract(tup.as_ref(py));
|
let tup = tup.extract::<TransparentTuple>(py);
|
||||||
assert!(tup.is_err());
|
assert!(tup.is_err());
|
||||||
let test: PyObject = "test".into_py(py);
|
let test: PyObject = "test".into_py(py);
|
||||||
let tup = TransparentTuple::extract(test.as_ref(py))
|
let tup = test
|
||||||
|
.extract::<TransparentTuple>(py)
|
||||||
.expect("Failed to extract TransparentTuple from PyTuple");
|
.expect("Failed to extract TransparentTuple from PyTuple");
|
||||||
assert_eq!(tup.0, "test");
|
assert_eq!(tup.0, "test");
|
||||||
});
|
});
|
||||||
|
@ -215,7 +224,7 @@ fn test_struct_nested_type_errors() {
|
||||||
}
|
}
|
||||||
.into_py(py);
|
.into_py(py);
|
||||||
|
|
||||||
let test: PyResult<Baz<String, usize>> = FromPyObject::extract(pybaz.as_ref(py));
|
let test = pybaz.extract::<Baz<String, usize>>(py);
|
||||||
assert!(test.is_err());
|
assert!(test.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extract_traceback(py,test.unwrap_err()),
|
extract_traceback(py,test.unwrap_err()),
|
||||||
|
@ -237,7 +246,7 @@ fn test_struct_nested_type_errors_with_generics() {
|
||||||
}
|
}
|
||||||
.into_py(py);
|
.into_py(py);
|
||||||
|
|
||||||
let test: PyResult<Baz<usize, String>> = FromPyObject::extract(pybaz.as_ref(py));
|
let test = pybaz.extract::<Baz<usize, usize>>(py);
|
||||||
assert!(test.is_err());
|
assert!(test.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extract_traceback(py, test.unwrap_err()),
|
extract_traceback(py, test.unwrap_err()),
|
||||||
|
@ -251,7 +260,7 @@ fn test_struct_nested_type_errors_with_generics() {
|
||||||
fn test_transparent_struct_error_message() {
|
fn test_transparent_struct_error_message() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let tup: PyObject = 1.into_py(py);
|
let tup: PyObject = 1.into_py(py);
|
||||||
let tup = B::extract(tup.as_ref(py));
|
let tup = tup.extract::<B>(py);
|
||||||
assert!(tup.is_err());
|
assert!(tup.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extract_traceback(py,tup.unwrap_err()),
|
extract_traceback(py,tup.unwrap_err()),
|
||||||
|
@ -265,7 +274,7 @@ fn test_transparent_struct_error_message() {
|
||||||
fn test_tuple_struct_error_message() {
|
fn test_tuple_struct_error_message() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let tup: PyObject = (1, "test").into_py(py);
|
let tup: PyObject = (1, "test").into_py(py);
|
||||||
let tup = Tuple::extract(tup.as_ref(py));
|
let tup = tup.extract::<Tuple>(py);
|
||||||
assert!(tup.is_err());
|
assert!(tup.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extract_traceback(py, tup.unwrap_err()),
|
extract_traceback(py, tup.unwrap_err()),
|
||||||
|
@ -279,7 +288,7 @@ fn test_tuple_struct_error_message() {
|
||||||
fn test_transparent_tuple_error_message() {
|
fn test_transparent_tuple_error_message() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let tup: PyObject = 1.into_py(py);
|
let tup: PyObject = 1.into_py(py);
|
||||||
let tup = TransparentTuple::extract(tup.as_ref(py));
|
let tup = tup.extract::<TransparentTuple>(py);
|
||||||
assert!(tup.is_err());
|
assert!(tup.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extract_traceback(py, tup.unwrap_err()),
|
extract_traceback(py, tup.unwrap_err()),
|
||||||
|
@ -290,10 +299,10 @@ fn test_transparent_tuple_error_message() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, FromPyObject)]
|
#[derive(Debug, FromPyObject)]
|
||||||
pub enum Foo<'a> {
|
pub enum Foo<'py> {
|
||||||
TupleVar(usize, String),
|
TupleVar(usize, String),
|
||||||
StructVar {
|
StructVar {
|
||||||
test: &'a PyString,
|
test: Bound<'py, PyString>,
|
||||||
},
|
},
|
||||||
#[pyo3(transparent)]
|
#[pyo3(transparent)]
|
||||||
TransparentTuple(usize),
|
TransparentTuple(usize),
|
||||||
|
@ -325,7 +334,9 @@ pub struct PyBool {
|
||||||
fn test_enum() {
|
fn test_enum() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let tup = PyTuple::new_bound(py, &[1.into_py(py), "test".into_py(py)]);
|
let tup = PyTuple::new_bound(py, &[1.into_py(py), "test".into_py(py)]);
|
||||||
let f = Foo::extract(tup.as_gil_ref()).expect("Failed to extract Foo from tuple");
|
let f = tup
|
||||||
|
.extract::<Foo<'_>>()
|
||||||
|
.expect("Failed to extract Foo from tuple");
|
||||||
match f {
|
match f {
|
||||||
Foo::TupleVar(test, test2) => {
|
Foo::TupleVar(test, test2) => {
|
||||||
assert_eq!(test, 1);
|
assert_eq!(test, 1);
|
||||||
|
@ -339,43 +350,55 @@ fn test_enum() {
|
||||||
test2: 0,
|
test2: 0,
|
||||||
}
|
}
|
||||||
.into_py(py);
|
.into_py(py);
|
||||||
let f = Foo::extract(pye.as_ref(py)).expect("Failed to extract Foo from PyE");
|
let f = pye
|
||||||
|
.extract::<Foo<'_>>(py)
|
||||||
|
.expect("Failed to extract Foo from PyE");
|
||||||
match f {
|
match f {
|
||||||
Foo::StructVar { test } => assert_eq!(test.to_string_lossy(), "foo"),
|
Foo::StructVar { test } => assert_eq!(test.to_string_lossy(), "foo"),
|
||||||
_ => panic!("Expected extracting Foo::StructVar, got {:?}", f),
|
_ => panic!("Expected extracting Foo::StructVar, got {:?}", f),
|
||||||
}
|
}
|
||||||
|
|
||||||
let int: PyObject = 1.into_py(py);
|
let int: PyObject = 1.into_py(py);
|
||||||
let f = Foo::extract(int.as_ref(py)).expect("Failed to extract Foo from int");
|
let f = int
|
||||||
|
.extract::<Foo<'_>>(py)
|
||||||
|
.expect("Failed to extract Foo from int");
|
||||||
match f {
|
match f {
|
||||||
Foo::TransparentTuple(test) => assert_eq!(test, 1),
|
Foo::TransparentTuple(test) => assert_eq!(test, 1),
|
||||||
_ => panic!("Expected extracting Foo::TransparentTuple, got {:?}", f),
|
_ => panic!("Expected extracting Foo::TransparentTuple, got {:?}", f),
|
||||||
}
|
}
|
||||||
let none = py.None();
|
let none = py.None();
|
||||||
let f = Foo::extract(none.as_ref(py)).expect("Failed to extract Foo from int");
|
let f = none
|
||||||
|
.extract::<Foo<'_>>(py)
|
||||||
|
.expect("Failed to extract Foo from int");
|
||||||
match f {
|
match f {
|
||||||
Foo::TransparentStructVar { a } => assert!(a.is_none()),
|
Foo::TransparentStructVar { a } => assert!(a.is_none()),
|
||||||
_ => panic!("Expected extracting Foo::TransparentStructVar, got {:?}", f),
|
_ => panic!("Expected extracting Foo::TransparentStructVar, got {:?}", f),
|
||||||
}
|
}
|
||||||
|
|
||||||
let pybool = PyBool { bla: true }.into_py(py);
|
let pybool = PyBool { bla: true }.into_py(py);
|
||||||
let f = Foo::extract(pybool.as_ref(py)).expect("Failed to extract Foo from PyBool");
|
let f = pybool
|
||||||
|
.extract::<Foo<'_>>(py)
|
||||||
|
.expect("Failed to extract Foo from PyBool");
|
||||||
match f {
|
match f {
|
||||||
Foo::StructVarGetAttrArg { a } => assert!(a),
|
Foo::StructVarGetAttrArg { a } => assert!(a),
|
||||||
_ => panic!("Expected extracting Foo::StructVarGetAttrArg, got {:?}", f),
|
_ => panic!("Expected extracting Foo::StructVarGetAttrArg, got {:?}", f),
|
||||||
}
|
}
|
||||||
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new_bound(py);
|
||||||
dict.set_item("a", "test").expect("Failed to set item");
|
dict.set_item("a", "test").expect("Failed to set item");
|
||||||
let f = Foo::extract(dict.as_ref()).expect("Failed to extract Foo from dict");
|
let f = dict
|
||||||
|
.extract::<Foo<'_>>()
|
||||||
|
.expect("Failed to extract Foo from dict");
|
||||||
match f {
|
match f {
|
||||||
Foo::StructWithGetItem { a } => assert_eq!(a, "test"),
|
Foo::StructWithGetItem { a } => assert_eq!(a, "test"),
|
||||||
_ => panic!("Expected extracting Foo::StructWithGetItem, got {:?}", f),
|
_ => panic!("Expected extracting Foo::StructWithGetItem, got {:?}", f),
|
||||||
}
|
}
|
||||||
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new_bound(py);
|
||||||
dict.set_item("foo", "test").expect("Failed to set item");
|
dict.set_item("foo", "test").expect("Failed to set item");
|
||||||
let f = Foo::extract(dict.as_ref()).expect("Failed to extract Foo from dict");
|
let f = dict
|
||||||
|
.extract::<Foo<'_>>()
|
||||||
|
.expect("Failed to extract Foo from dict");
|
||||||
match f {
|
match f {
|
||||||
Foo::StructWithGetItemArg { a } => assert_eq!(a, "test"),
|
Foo::StructWithGetItemArg { a } => assert_eq!(a, "test"),
|
||||||
_ => panic!("Expected extracting Foo::StructWithGetItemArg, got {:?}", f),
|
_ => panic!("Expected extracting Foo::StructWithGetItemArg, got {:?}", f),
|
||||||
|
@ -386,8 +409,8 @@ fn test_enum() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_enum_error() {
|
fn test_enum_error() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new_bound(py);
|
||||||
let err = Foo::extract(dict.as_ref()).unwrap_err();
|
let err = dict.extract::<Foo<'_>>().unwrap_err();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
"\
|
"\
|
||||||
|
@ -402,7 +425,7 @@ TypeError: failed to extract enum Foo ('TupleVar | StructVar | TransparentTuple
|
||||||
);
|
);
|
||||||
|
|
||||||
let tup = PyTuple::empty_bound(py);
|
let tup = PyTuple::empty_bound(py);
|
||||||
let err = Foo::extract(tup.as_gil_ref()).unwrap_err();
|
let err = tup.extract::<Foo<'_>>().unwrap_err();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
"\
|
"\
|
||||||
|
@ -419,23 +442,24 @@ TypeError: failed to extract enum Foo ('TupleVar | StructVar | TransparentTuple
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, FromPyObject)]
|
#[derive(Debug, FromPyObject)]
|
||||||
enum EnumWithCatchAll<'a> {
|
enum EnumWithCatchAll<'py> {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[pyo3(transparent)]
|
#[pyo3(transparent)]
|
||||||
Foo(Foo<'a>),
|
Foo(Foo<'py>),
|
||||||
#[pyo3(transparent)]
|
#[pyo3(transparent)]
|
||||||
CatchAll(&'a PyAny),
|
CatchAll(Bound<'py, PyAny>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_enum_catch_all() {
|
fn test_enum_catch_all() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new_bound(py);
|
||||||
let f = EnumWithCatchAll::extract(dict.as_ref())
|
let f = dict
|
||||||
|
.extract::<EnumWithCatchAll<'_>>()
|
||||||
.expect("Failed to extract EnumWithCatchAll from dict");
|
.expect("Failed to extract EnumWithCatchAll from dict");
|
||||||
match f {
|
match f {
|
||||||
EnumWithCatchAll::CatchAll(any) => {
|
EnumWithCatchAll::CatchAll(any) => {
|
||||||
let d = <&PyDict>::extract(any).expect("Expected pydict");
|
let d = any.extract::<Bound<'_, PyDict>>().expect("Expected pydict");
|
||||||
assert!(d.is_empty());
|
assert!(d.is_empty());
|
||||||
}
|
}
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
|
@ -459,8 +483,8 @@ pub enum Bar {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_err_rename() {
|
fn test_err_rename() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new_bound(py);
|
||||||
let f = Bar::extract(dict.as_ref());
|
let f = dict.extract::<Bar>();
|
||||||
assert!(f.is_err());
|
assert!(f.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
f.unwrap_err().to_string(),
|
f.unwrap_err().to_string(),
|
||||||
|
@ -493,7 +517,7 @@ fn test_from_py_with() {
|
||||||
)
|
)
|
||||||
.expect("failed to create dict");
|
.expect("failed to create dict");
|
||||||
|
|
||||||
let zap = Zap::extract_bound(&py_zap).unwrap();
|
let zap = py_zap.extract::<Zap>().unwrap();
|
||||||
|
|
||||||
assert_eq!(zap.name, "whatever");
|
assert_eq!(zap.name, "whatever");
|
||||||
assert_eq!(zap.some_object_length, 3usize);
|
assert_eq!(zap.some_object_length, 3usize);
|
||||||
|
@ -510,7 +534,7 @@ fn test_from_py_with_tuple_struct() {
|
||||||
.eval_bound(r#"("whatever", [1, 2, 3])"#, None, None)
|
.eval_bound(r#"("whatever", [1, 2, 3])"#, None, None)
|
||||||
.expect("failed to create tuple");
|
.expect("failed to create tuple");
|
||||||
|
|
||||||
let zap = ZapTuple::extract_bound(&py_zap).unwrap();
|
let zap = py_zap.extract::<ZapTuple>().unwrap();
|
||||||
|
|
||||||
assert_eq!(zap.0, "whatever");
|
assert_eq!(zap.0, "whatever");
|
||||||
assert_eq!(zap.1, 3usize);
|
assert_eq!(zap.1, 3usize);
|
||||||
|
@ -524,7 +548,7 @@ fn test_from_py_with_tuple_struct_error() {
|
||||||
.eval_bound(r#"("whatever", [1, 2, 3], "third")"#, None, None)
|
.eval_bound(r#"("whatever", [1, 2, 3], "third")"#, None, None)
|
||||||
.expect("failed to create tuple");
|
.expect("failed to create tuple");
|
||||||
|
|
||||||
let f = ZapTuple::extract_bound(&py_zap);
|
let f = py_zap.extract::<ZapTuple>();
|
||||||
|
|
||||||
assert!(f.is_err());
|
assert!(f.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -547,7 +571,7 @@ fn test_from_py_with_enum() {
|
||||||
.eval_bound(r#"("whatever", [1, 2, 3])"#, None, None)
|
.eval_bound(r#"("whatever", [1, 2, 3])"#, None, None)
|
||||||
.expect("failed to create tuple");
|
.expect("failed to create tuple");
|
||||||
|
|
||||||
let zap = ZapEnum::extract_bound(&py_zap).unwrap();
|
let zap = py_zap.extract::<ZapEnum>().unwrap();
|
||||||
let expected_zap = ZapEnum::Zip(2);
|
let expected_zap = ZapEnum::Zip(2);
|
||||||
|
|
||||||
assert_eq!(zap, expected_zap);
|
assert_eq!(zap, expected_zap);
|
||||||
|
@ -564,8 +588,9 @@ pub struct TransparentFromPyWith {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_transparent_from_py_with() {
|
fn test_transparent_from_py_with() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let result =
|
let result = PyList::new_bound(py, [1, 2, 3])
|
||||||
TransparentFromPyWith::extract(PyList::new_bound(py, [1, 2, 3]).as_gil_ref()).unwrap();
|
.extract::<TransparentFromPyWith>()
|
||||||
|
.unwrap();
|
||||||
let expected = TransparentFromPyWith { len: 3 };
|
let expected = TransparentFromPyWith { len: 3 };
|
||||||
|
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
|
@ -216,7 +216,7 @@ fn mapping() {
|
||||||
let inst = Py::new(
|
let inst = Py::new(
|
||||||
py,
|
py,
|
||||||
Mapping {
|
Mapping {
|
||||||
values: PyDict::new(py).into(),
|
values: PyDict::new_bound(py).into(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use pyo3::{types::PyDict, Py, Python};
|
use pyo3::{types::PyDict, Bound, Py, Python};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let dict: Py<PyDict> = Python::with_gil(|py| PyDict::new(py).into());
|
let dict: Py<PyDict> = Python::with_gil(|py| PyDict::new_bound(py).unbind());
|
||||||
|
|
||||||
// Should not be able to get access to Py contents outside of with_gil.
|
// Should not be able to get access to Py contents outside of with_gil.
|
||||||
let dict: &PyDict = Python::with_gil(|py| dict.as_ref(py));
|
let dict: &Bound<'_, PyDict> = Python::with_gil(|py| dict.bind(py));
|
||||||
|
|
||||||
let _py: Python = dict.py(); // Obtain a Python<'p> without GIL.
|
let _py: Python = dict.py(); // Obtain a Python<'p> without GIL.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> tests/ui/wrong_aspyref_lifetimes.rs:7:47
|
--> tests/ui/wrong_aspyref_lifetimes.rs:7:58
|
||||||
|
|
|
|
||||||
7 | let dict: &PyDict = Python::with_gil(|py| dict.as_ref(py));
|
7 | let dict: &Bound<'_, PyDict> = Python::with_gil(|py| dict.bind(py));
|
||||||
| --- ^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
|
| --- ^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
|
||||||
| | |
|
| | |
|
||||||
| | return type of closure is &'2 PyDict
|
| | return type of closure is &'2 pyo3::Bound<'_, PyDict>
|
||||||
| has type `pyo3::Python<'1>`
|
| has type `pyo3::Python<'1>`
|
||||||
|
|
Loading…
Reference in New Issue