|
1 | 1 | use crate::err::{self, PyResult}; |
2 | 2 | use crate::ffi::{self, Py_ssize_t}; |
3 | 3 | use crate::ffi_ptr_ext::FfiPtrExt; |
| 4 | +use crate::internal::state::thread_is_attached; |
4 | 5 | use crate::internal_tricks::get_ssize_index; |
5 | 6 | use crate::types::sequence::PySequenceMethods; |
6 | 7 | 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 | +}; |
8 | 11 | use std::iter::FusedIterator; |
9 | 12 | #[cfg(feature = "nightly")] |
10 | 13 | use std::num::NonZero; |
@@ -451,6 +454,23 @@ impl<'py> PyListMethods<'py> for Bound<'py, PyList> { |
451 | 454 | } |
452 | 455 | } |
453 | 456 |
|
| 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 | + |
454 | 474 | // New types for type checking when using BoundListIterator associated methods, like |
455 | 475 | // BoundListIterator::next_unchecked. |
456 | 476 | struct Index(usize); |
@@ -944,7 +964,7 @@ mod tests { |
944 | 964 | use crate::types::list::PyListMethods; |
945 | 965 | use crate::types::sequence::PySequenceMethods; |
946 | 966 | use crate::types::{PyList, PyTuple}; |
947 | | - use crate::{IntoPyObject, PyResult, Python}; |
| 967 | + use crate::{IntoPyObject, Py, PyResult, Python}; |
948 | 968 | #[cfg(feature = "nightly")] |
949 | 969 | use std::num::NonZero; |
950 | 970 |
|
@@ -1786,4 +1806,22 @@ mod tests { |
1786 | 1806 | ); |
1787 | 1807 | }) |
1788 | 1808 | } |
| 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 | + } |
1789 | 1827 | } |
0 commit comments