Skip to content

Commit 7ffddf7

Browse files
Add FromIterator for Py<PyList>
1 parent e9151b4 commit 7ffddf7

1 file changed

Lines changed: 40 additions & 2 deletions

File tree

src/types/list.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use crate::err::{self, PyResult};
22
use crate::ffi::{self, Py_ssize_t};
33
use crate::ffi_ptr_ext::FfiPtrExt;
4+
use crate::internal::state::thread_is_attached;
45
use crate::internal_tricks::get_ssize_index;
56
use crate::types::sequence::PySequenceMethods;
67
use crate::types::{PySequence, PyTuple};
7-
use crate::{Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt, PyAny, PyErr, Python};
8+
use crate::{
9+
Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt, Py, PyAny, PyErr, Python,
10+
};
811
use std::iter::FusedIterator;
912
#[cfg(feature = "nightly")]
1013
use std::num::NonZero;
@@ -451,6 +454,23 @@ impl<'py> PyListMethods<'py> for Bound<'py, PyList> {
451454
}
452455
}
453456

457+
impl<'py> FromIterator<Bound<'py, PyAny>> for Py<PyList> {
458+
fn from_iter<T: IntoIterator<Item = Bound<'py, PyAny>>>(iter: T) -> Self {
459+
let mut elements = iter.into_iter().peekable();
460+
let py = elements.peek().map_or_else(
461+
|| {
462+
assert!(thread_is_attached());
463+
unsafe { Python::assume_attached() }
464+
},
465+
|item| item.py(),
466+
);
467+
468+
PyList::new(py, elements)
469+
.expect("Could not allocate enough memory to add elements to the list")
470+
.unbind()
471+
}
472+
}
473+
454474
// New types for type checking when using BoundListIterator associated methods, like
455475
// BoundListIterator::next_unchecked.
456476
struct Index(usize);
@@ -944,7 +964,7 @@ mod tests {
944964
use crate::types::list::PyListMethods;
945965
use crate::types::sequence::PySequenceMethods;
946966
use crate::types::{PyList, PyTuple};
947-
use crate::{IntoPyObject, PyResult, Python};
967+
use crate::{IntoPyObject, Py, PyResult, Python};
948968
#[cfg(feature = "nightly")]
949969
use std::num::NonZero;
950970

@@ -1786,4 +1806,22 @@ mod tests {
17861806
);
17871807
})
17881808
}
1809+
1810+
#[test]
1811+
fn test_from_iter() {
1812+
Python::attach(|py| {
1813+
let list = [py.None().into_bound(py)]
1814+
.into_iter()
1815+
.collect::<Py<PyList>>()
1816+
.into_bound(py);
1817+
assert_eq!(list.len(), 1);
1818+
1819+
let list = [Ok(py.None().into_bound(py))]
1820+
.into_iter()
1821+
.collect::<PyResult<Py<PyList>>>()
1822+
.unwrap()
1823+
.into_bound(py);
1824+
assert_eq!(list.len(), 1);
1825+
})
1826+
}
17891827
}

0 commit comments

Comments
 (0)