Merge pull request #717 from kngwyu/pyset-iter

Implement iter for PySet and PyFrozenSet
This commit is contained in:
Yuji Kanagawa 2020-01-09 12:42:33 +09:00 committed by GitHub
commit 41e3b25070
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 23 deletions

View File

@ -150,23 +150,20 @@ impl PyDict {
} }
} }
/// Returns a iterator of (key, value) pairs in this dictionary /// Returns a iterator of (key, value) pairs in this dictionary.
/// Note that it's unsafe to use when the dictionary might be changed ///
/// by other python code. /// Note that it's unsafe to use when the dictionary might be changed by other code.
pub fn iter(&self) -> PyDictIterator { pub fn iter(&self) -> PyDictIterator {
let py = self.py();
PyDictIterator { PyDictIterator {
dict: self.to_object(py), dict: self.as_ref(),
pos: 0, pos: 0,
py,
} }
} }
} }
pub struct PyDictIterator<'py> { pub struct PyDictIterator<'py> {
dict: PyObject, dict: &'py PyAny,
pos: isize, pos: isize,
py: Python<'py>,
} }
impl<'py> Iterator for PyDictIterator<'py> { impl<'py> Iterator for PyDictIterator<'py> {
@ -178,7 +175,7 @@ impl<'py> Iterator for PyDictIterator<'py> {
let mut key: *mut ffi::PyObject = std::ptr::null_mut(); let mut key: *mut ffi::PyObject = std::ptr::null_mut();
let mut value: *mut ffi::PyObject = std::ptr::null_mut(); let mut value: *mut ffi::PyObject = std::ptr::null_mut();
if ffi::PyDict_Next(self.dict.as_ptr(), &mut self.pos, &mut key, &mut value) != 0 { if ffi::PyDict_Next(self.dict.as_ptr(), &mut self.pos, &mut key, &mut value) != 0 {
let py = self.py; let py = self.dict.py();
Some((py.from_borrowed_ptr(key), py.from_borrowed_ptr(value))) Some((py.from_borrowed_ptr(key), py.from_borrowed_ptr(value)))
} else { } else {
None None

View File

@ -113,7 +113,7 @@ impl PyList {
}) })
} }
/// Returns an iterator over the tuple items. /// Returns an iterator over this list items.
pub fn iter(&self) -> PyListIterator { pub fn iter(&self) -> PyListIterator {
PyListIterator { PyListIterator {
list: self, list: self,

View File

@ -95,6 +95,17 @@ impl PySet {
pub fn pop(&self) -> Option<PyObject> { pub fn pop(&self) -> Option<PyObject> {
unsafe { PyObject::from_owned_ptr_or_opt(self.py(), ffi::PySet_Pop(self.as_ptr())) } unsafe { PyObject::from_owned_ptr_or_opt(self.py(), ffi::PySet_Pop(self.as_ptr())) }
} }
/// Returns an iterator of values in this set.
///
/// Note that it can be unsafe to use when the set might be changed by other code.
#[cfg(not(Py_LIMITED_API))]
pub fn iter(&self) -> PySetIterator {
PySetIterator {
set: self.as_ref(),
pos: 0,
}
}
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
@ -127,10 +138,7 @@ impl<'a> std::iter::IntoIterator for &'a PySet {
type IntoIter = PySetIterator<'a>; type IntoIter = PySetIterator<'a>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
PySetIterator { self.iter()
set: self.as_ref(),
pos: 0,
}
} }
} }
@ -204,7 +212,16 @@ impl PyFrozenSet {
} }
}) })
} }
/// Returns an iterator of values in this frozen set.
///
/// Note that it can be unsafe to use when the set might be changed by other code.
#[cfg(not(Py_LIMITED_API))]
pub fn iter(&self) -> PySetIterator {
self.into_iter()
}
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
impl<'a> std::iter::IntoIterator for &'a PyFrozenSet { impl<'a> std::iter::IntoIterator for &'a PyFrozenSet {
type Item = &'a PyAny; type Item = &'a PyAny;
@ -222,9 +239,7 @@ impl<'a> std::iter::IntoIterator for &'a PyFrozenSet {
mod test { mod test {
use super::{PyFrozenSet, PySet}; use super::{PyFrozenSet, PySet};
use crate::instance::AsPyRef; use crate::instance::AsPyRef;
use crate::objectprotocol::ObjectProtocol; use crate::{ObjectProtocol, PyTryFrom, Python, ToPyObject};
use crate::Python;
use crate::{PyTryFrom, ToPyObject};
use std::collections::HashSet; use std::collections::HashSet;
#[test] #[test]
@ -317,9 +332,10 @@ mod test {
let py = gil.python(); let py = gil.python();
let set = PySet::new(py, &[1]).unwrap(); let set = PySet::new(py, &[1]).unwrap();
// objectprotocol iteration
for el in set.iter().unwrap() { // iter method
assert_eq!(1i32, el.unwrap().extract::<i32>().unwrap()); for el in set.iter() {
assert_eq!(1i32, el.extract().unwrap());
} }
// intoiterator iteration // intoiterator iteration
@ -363,9 +379,9 @@ mod test {
let set = PyFrozenSet::new(py, &[1]).unwrap(); let set = PyFrozenSet::new(py, &[1]).unwrap();
// objectprotocol iteration // iter method
for el in set.iter().unwrap() { for el in set.iter() {
assert_eq!(1i32, el.unwrap().extract::<i32>().unwrap()); assert_eq!(1i32, el.extract::<i32>().unwrap());
} }
// intoiterator iteration // intoiterator iteration