add list bound constructors
This commit is contained in:
parent
0973da27e9
commit
eed196329d
|
@ -23,21 +23,17 @@ fn enum_from_pyobject(b: &mut Bencher<'_>) {
|
|||
|
||||
fn list_via_downcast(b: &mut Bencher<'_>) {
|
||||
Python::with_gil(|py| {
|
||||
let any: &PyAny = PyList::empty(py).into();
|
||||
let any: &Bound<'_, PyAny> = &PyList::empty_bound(py);
|
||||
|
||||
b.iter(|| {
|
||||
let _list: &PyList = black_box(any).downcast().unwrap();
|
||||
});
|
||||
b.iter(|| black_box(any).downcast::<PyList>().unwrap());
|
||||
})
|
||||
}
|
||||
|
||||
fn list_via_extract(b: &mut Bencher<'_>) {
|
||||
Python::with_gil(|py| {
|
||||
let any: &PyAny = PyList::empty(py).into();
|
||||
let any: &Bound<'_, PyAny> = &PyList::empty_bound(py);
|
||||
|
||||
b.iter(|| {
|
||||
let _list: &PyList = black_box(any).extract().unwrap();
|
||||
});
|
||||
b.iter(|| black_box(any).extract::<Bound<'_, PyList>>().unwrap());
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -45,9 +41,7 @@ fn not_a_list_via_downcast(b: &mut Bencher<'_>) {
|
|||
Python::with_gil(|py| {
|
||||
let any: &PyAny = PyString::new(py, "foobar").into();
|
||||
|
||||
b.iter(|| {
|
||||
black_box(any).downcast::<PyList>().unwrap_err();
|
||||
});
|
||||
b.iter(|| black_box(any).downcast::<PyList>().unwrap_err());
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -55,9 +49,7 @@ fn not_a_list_via_extract(b: &mut Bencher<'_>) {
|
|||
Python::with_gil(|py| {
|
||||
let any: &PyAny = PyString::new(py, "foobar").into();
|
||||
|
||||
b.iter(|| {
|
||||
black_box(any).extract::<&PyList>().unwrap_err();
|
||||
});
|
||||
b.iter(|| black_box(any).extract::<&PyList>().unwrap_err());
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,10 @@ use pyo3::types::{PyList, PySequence};
|
|||
fn iter_list(b: &mut Bencher<'_>) {
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 100_000;
|
||||
let list = PyList::new(py, 0..LEN);
|
||||
let list = PyList::new_bound(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for x in list {
|
||||
for x in list.iter() {
|
||||
let i: u64 = x.extract().unwrap();
|
||||
sum += i;
|
||||
}
|
||||
|
@ -20,14 +20,14 @@ fn iter_list(b: &mut Bencher<'_>) {
|
|||
fn list_new(b: &mut Bencher<'_>) {
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
b.iter(|| PyList::new(py, 0..LEN));
|
||||
b.iter(|| PyList::new_bound(py, 0..LEN));
|
||||
});
|
||||
}
|
||||
|
||||
fn list_get_item(b: &mut Bencher<'_>) {
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
let list = PyList::new(py, 0..LEN);
|
||||
let list = PyList::new_bound(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
|
@ -41,7 +41,7 @@ fn list_get_item(b: &mut Bencher<'_>) {
|
|||
fn list_get_item_unchecked(b: &mut Bencher<'_>) {
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
let list = PyList::new(py, 0..LEN);
|
||||
let list = PyList::new_bound(py, 0..LEN);
|
||||
let mut sum = 0;
|
||||
b.iter(|| {
|
||||
for i in 0..LEN {
|
||||
|
@ -56,9 +56,10 @@ fn list_get_item_unchecked(b: &mut Bencher<'_>) {
|
|||
fn sequence_from_list(b: &mut Bencher<'_>) {
|
||||
Python::with_gil(|py| {
|
||||
const LEN: usize = 50_000;
|
||||
let list = PyList::new(py, 0..LEN).to_object(py);
|
||||
let list = PyList::new_bound(py, 0..LEN).to_object(py);
|
||||
b.iter(|| {
|
||||
let _: &PySequence = list.extract(py).unwrap();
|
||||
let seq: &PySequence = list.extract(py).unwrap();
|
||||
seq
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -95,14 +95,14 @@ where
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::types::{PyDict, PyList};
|
||||
use crate::types::{any::PyAnyMethods, PyDict, PyList};
|
||||
|
||||
#[test]
|
||||
fn test_smallvec_into_py() {
|
||||
Python::with_gil(|py| {
|
||||
let sv: SmallVec<[u64; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect();
|
||||
let hso: PyObject = sv.clone().into_py(py);
|
||||
let l = PyList::new(py, [1, 2, 3, 4, 5]);
|
||||
let l = PyList::new_bound(py, [1, 2, 3, 4, 5]);
|
||||
assert!(l.eq(hso).unwrap());
|
||||
});
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_smallvec_from_py_object() {
|
||||
Python::with_gil(|py| {
|
||||
let l = PyList::new(py, [1, 2, 3, 4, 5]);
|
||||
let l = PyList::new_bound(py, [1, 2, 3, 4, 5]);
|
||||
let sv: SmallVec<[u64; 8]> = l.extract().unwrap();
|
||||
assert_eq!(sv.as_slice(), [1, 2, 3, 4, 5]);
|
||||
});
|
||||
|
@ -133,7 +133,7 @@ mod tests {
|
|||
Python::with_gil(|py| {
|
||||
let sv: SmallVec<[u64; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect();
|
||||
let hso: PyObject = sv.to_object(py);
|
||||
let l = PyList::new(py, [1, 2, 3, 4, 5]);
|
||||
let l = PyList::new_bound(py, [1, 2, 3, 4, 5]);
|
||||
assert!(l.eq(hso).unwrap());
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1067,8 +1067,7 @@ impl<'unbound> Python<'unbound> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::types::{IntoPyDict, PyDict, PyList};
|
||||
use crate::Py;
|
||||
use crate::types::{any::PyAnyMethods, IntoPyDict, PyDict, PyList};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[test]
|
||||
|
@ -1150,17 +1149,14 @@ mod tests {
|
|||
|
||||
// If allow_threads is implemented correctly, this thread still owns the GIL here
|
||||
// so the following Python calls should not cause crashes.
|
||||
let list = PyList::new(py, [1, 2, 3, 4]);
|
||||
let list = PyList::new_bound(py, [1, 2, 3, 4]);
|
||||
assert_eq!(list.extract::<Vec<i32>>().unwrap(), vec![1, 2, 3, 4]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_allow_threads_pass_stuff_in() {
|
||||
let list: Py<PyList> = Python::with_gil(|py| {
|
||||
let list = PyList::new(py, vec!["foo", "bar"]);
|
||||
list.into()
|
||||
});
|
||||
let list = Python::with_gil(|py| PyList::new_bound(py, vec!["foo", "bar"]).unbind());
|
||||
let mut v = vec![1, 2, 3];
|
||||
let a = Arc::new(String::from("foo"));
|
||||
|
||||
|
|
|
@ -76,8 +76,8 @@ impl Dummy {
|
|||
|
||||
fn __delattr__(&mut self, name: ::std::string::String) {}
|
||||
|
||||
fn __dir__<'py>(&self, py: crate::Python<'py>) -> &'py crate::types::PyList {
|
||||
crate::types::PyList::new(py, ::std::vec![0_u8])
|
||||
fn __dir__<'py>(&self, py: crate::Python<'py>) -> crate::Bound<'py, crate::types::PyList> {
|
||||
crate::types::PyList::new_bound(py, ::std::vec![0_u8])
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
|
@ -469,8 +469,8 @@ impl Dummy {
|
|||
|
||||
fn __delattr__(&mut self, name: ::std::string::String) {}
|
||||
|
||||
fn __dir__<'py>(&self, py: crate::Python<'py>) -> &'py crate::types::PyList {
|
||||
crate::types::PyList::new(py, ::std::vec![0_u8])
|
||||
fn __dir__<'py>(&self, py: crate::Python<'py>) -> crate::Bound<'py, crate::types::PyList> {
|
||||
crate::types::PyList::new_bound(py, ::std::vec![0_u8])
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
|
|
|
@ -697,6 +697,7 @@ where
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[cfg(not(PyPy))]
|
||||
|
|
|
@ -56,6 +56,24 @@ pub(crate) fn new_from_iter<'py>(
|
|||
}
|
||||
|
||||
impl PyList {
|
||||
/// Deprecated form of [`PyList::new_bound`].
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
#[cfg_attr(
|
||||
not(feature = "gil-refs"),
|
||||
deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyList::new` will be replaced by `PyList::new_bound` in a future PyO3 version"
|
||||
)
|
||||
)]
|
||||
pub fn new<T, U>(py: Python<'_>, elements: impl IntoIterator<Item = T, IntoIter = U>) -> &PyList
|
||||
where
|
||||
T: ToPyObject,
|
||||
U: ExactSizeIterator<Item = T>,
|
||||
{
|
||||
Self::new_bound(py, elements).into_gil_ref()
|
||||
}
|
||||
|
||||
/// Constructs a new list with the given elements.
|
||||
///
|
||||
/// If you want to create a [`PyList`] with elements of different or unknown types, or from an
|
||||
|
@ -82,18 +100,38 @@ impl PyList {
|
|||
/// All standard library structures implement this trait correctly, if they do, so calling this
|
||||
/// function with (for example) [`Vec`]`<T>` or `&[T]` will always succeed.
|
||||
#[track_caller]
|
||||
pub fn new<T, U>(py: Python<'_>, elements: impl IntoIterator<Item = T, IntoIter = U>) -> &PyList
|
||||
pub fn new_bound<T, U>(
|
||||
py: Python<'_>,
|
||||
elements: impl IntoIterator<Item = T, IntoIter = U>,
|
||||
) -> Bound<'_, PyList>
|
||||
where
|
||||
T: ToPyObject,
|
||||
U: ExactSizeIterator<Item = T>,
|
||||
{
|
||||
let mut iter = elements.into_iter().map(|e| e.to_object(py));
|
||||
new_from_iter(py, &mut iter).into_gil_ref()
|
||||
new_from_iter(py, &mut iter)
|
||||
}
|
||||
|
||||
/// Deprecated form of [`PyList::empty_bound`].
|
||||
#[inline]
|
||||
#[cfg_attr(
|
||||
not(feature = "gil-refs"),
|
||||
deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyList::empty` will be replaced by `PyList::empty_bound` in a future PyO3 version"
|
||||
)
|
||||
)]
|
||||
pub fn empty(py: Python<'_>) -> &PyList {
|
||||
Self::empty_bound(py).into_gil_ref()
|
||||
}
|
||||
|
||||
/// Constructs a new empty list.
|
||||
pub fn empty(py: Python<'_>) -> &PyList {
|
||||
unsafe { py.from_owned_ptr(ffi::PyList_New(0)) }
|
||||
pub fn empty_bound(py: Python<'_>) -> Bound<'_, PyList> {
|
||||
unsafe {
|
||||
ffi::PyList_New(0)
|
||||
.assume_owned(py)
|
||||
.downcast_into_unchecked()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the length of the list.
|
||||
|
@ -667,6 +705,7 @@ impl<'py> IntoIterator for Bound<'py, PyList> {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))]
|
||||
mod tests {
|
||||
use crate::types::{PyList, PyTuple};
|
||||
use crate::Python;
|
||||
|
|
|
@ -560,7 +560,7 @@ impl<'py> PyModuleMethods<'py> for Bound<'py, PyModule> {
|
|||
Ok(idx) => idx.downcast_into().map_err(PyErr::from),
|
||||
Err(err) => {
|
||||
if err.is_instance_of::<exceptions::PyAttributeError>(self.py()) {
|
||||
let l = PyList::empty(self.py()).as_borrowed().to_owned();
|
||||
let l = PyList::empty_bound(self.py());
|
||||
self.setattr(__all__, &l).map_err(PyErr::from)?;
|
||||
Ok(l)
|
||||
} else {
|
||||
|
|
|
@ -566,6 +566,7 @@ impl<'v> crate::PyTryFrom<'v> for PySequence {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))]
|
||||
mod tests {
|
||||
use crate::types::{PyList, PySequence, PyTuple};
|
||||
use crate::{PyObject, Python, ToPyObject};
|
||||
|
|
|
@ -564,7 +564,8 @@ pub struct TransparentFromPyWith {
|
|||
#[test]
|
||||
fn test_transparent_from_py_with() {
|
||||
Python::with_gil(|py| {
|
||||
let result = TransparentFromPyWith::extract(PyList::new(py, [1, 2, 3])).unwrap();
|
||||
let result =
|
||||
TransparentFromPyWith::extract(PyList::new_bound(py, [1, 2, 3]).as_gil_ref()).unwrap();
|
||||
let expected = TransparentFromPyWith { len: 3 };
|
||||
|
||||
assert_eq!(result, expected);
|
||||
|
|
|
@ -42,8 +42,8 @@ impl ClassWithProperties {
|
|||
}
|
||||
|
||||
#[getter]
|
||||
fn get_data_list<'py>(&self, py: Python<'py>) -> &'py PyList {
|
||||
PyList::new(py, [self.num])
|
||||
fn get_data_list<'py>(&self, py: Python<'py>) -> Bound<'py, PyList> {
|
||||
PyList::new_bound(py, [self.num])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -689,12 +689,12 @@ struct MethodWithLifeTime {}
|
|||
|
||||
#[pymethods]
|
||||
impl MethodWithLifeTime {
|
||||
fn set_to_list<'py>(&self, py: Python<'py>, set: &'py PySet) -> PyResult<&'py PyList> {
|
||||
fn set_to_list<'py>(&self, py: Python<'py>, set: &'py PySet) -> PyResult<Bound<'py, PyList>> {
|
||||
let mut items = vec![];
|
||||
for _ in 0..set.len() {
|
||||
items.push(set.pop().unwrap());
|
||||
}
|
||||
let list = PyList::new(py, items);
|
||||
let list = PyList::new_bound(py, items);
|
||||
list.sort()?;
|
||||
Ok(list)
|
||||
}
|
||||
|
|
|
@ -850,7 +850,7 @@ struct DefaultedContains;
|
|||
#[pymethods]
|
||||
impl DefaultedContains {
|
||||
fn __iter__(&self, py: Python<'_>) -> PyObject {
|
||||
PyList::new(py, ["a", "b", "c"])
|
||||
PyList::new_bound(py, ["a", "b", "c"])
|
||||
.as_ref()
|
||||
.iter()
|
||||
.unwrap()
|
||||
|
@ -864,7 +864,7 @@ struct NoContains;
|
|||
#[pymethods]
|
||||
impl NoContains {
|
||||
fn __iter__(&self, py: Python<'_>) -> PyObject {
|
||||
PyList::new(py, ["a", "b", "c"])
|
||||
PyList::new_bound(py, ["a", "b", "c"])
|
||||
.as_ref()
|
||||
.iter()
|
||||
.unwrap()
|
||||
|
|
Loading…
Reference in New Issue