Add IntoPy<PyObject> for HashSet and BTreeSet (#865)

This commit is contained in:
David Hewitt 2020-04-12 06:44:01 +01:00 committed by GitHub
parent 5e285fda78
commit 97fd658593
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 3 deletions

View File

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added ### Added
* `_PyDict_NewPresized`. [#849](https://github.com/PyO3/pyo3/pull/849) * `_PyDict_NewPresized`. [#849](https://github.com/PyO3/pyo3/pull/849)
* `IntoPy<PyObject>` for `HashSet` and `BTreeSet`. [#864](https://github.com/PyO3/pyo3/pull/864)
### Fixed ### Fixed
* `__radd__` and other `__r*__` methods now correctly work with operators. [#839](https://github.com/PyO3/pyo3/pull/839) * `__radd__` and other `__r*__` methods now correctly work with operators. [#839](https://github.com/PyO3/pyo3/pull/839)

View File

@ -4,8 +4,8 @@
use crate::err::{self, PyErr, PyResult}; use crate::err::{self, PyErr, PyResult};
use crate::internal_tricks::Unsendable; use crate::internal_tricks::Unsendable;
use crate::{ use crate::{
ffi, AsPyPointer, FromPyObject, PyAny, PyNativeType, PyObject, Python, ToBorrowedObject, ffi, AsPyPointer, FromPy, FromPyObject, IntoPy, PyAny, PyNativeType, PyObject, Python,
ToPyObject, ToBorrowedObject, ToPyObject,
}; };
use std::cmp; use std::cmp;
use std::collections::{BTreeSet, HashSet}; use std::collections::{BTreeSet, HashSet};
@ -184,6 +184,22 @@ where
} }
} }
impl<K, S> FromPy<HashSet<K, S>> for PyObject
where
K: IntoPy<PyObject> + Eq + hash::Hash,
S: hash::BuildHasher + Default,
{
fn from_py(src: HashSet<K, S>, py: Python) -> Self {
let set = PySet::empty(py).expect("Failed to construct empty set");
{
for val in src {
set.add(val.into_py(py)).expect("Failed to add to set");
}
}
set.into()
}
}
impl<'source, K, S> FromPyObject<'source> for HashSet<K, S> impl<'source, K, S> FromPyObject<'source> for HashSet<K, S>
where where
K: FromPyObject<'source> + cmp::Eq + hash::Hash, K: FromPyObject<'source> + cmp::Eq + hash::Hash,
@ -195,6 +211,21 @@ where
} }
} }
impl<K> FromPy<BTreeSet<K>> for PyObject
where
K: IntoPy<PyObject> + cmp::Ord + ToPyObject,
{
fn from_py(src: BTreeSet<K>, py: Python) -> Self {
let set = PySet::empty(py).expect("Failed to construct empty set");
{
for val in src {
set.add(val.into_py(py)).expect("Failed to add to set");
}
}
set.into()
}
}
impl<'source, K> FromPyObject<'source> for BTreeSet<K> impl<'source, K> FromPyObject<'source> for BTreeSet<K>
where where
K: FromPyObject<'source> + cmp::Ord, K: FromPyObject<'source> + cmp::Ord,
@ -271,7 +302,7 @@ impl<'a> std::iter::IntoIterator for &'a PyFrozenSet {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{PyFrozenSet, PySet}; use super::{PyFrozenSet, PySet};
use crate::{AsPyRef, ObjectProtocol, PyTryFrom, Python, ToPyObject}; use crate::{AsPyRef, IntoPy, ObjectProtocol, PyObject, PyTryFrom, Python, ToPyObject};
use std::collections::{BTreeSet, HashSet}; use std::collections::{BTreeSet, HashSet};
use std::iter::FromIterator; use std::iter::FromIterator;
@ -451,4 +482,19 @@ mod test {
BTreeSet::from_iter([1, 2, 3, 4, 5].iter().copied()) BTreeSet::from_iter([1, 2, 3, 4, 5].iter().copied())
); );
} }
#[test]
fn test_set_into_py() {
let gil = Python::acquire_gil();
let py = gil.python();
let bt: BTreeSet<u64> = [1, 2, 3, 4, 5].iter().cloned().collect();
let hs: HashSet<u64> = [1, 2, 3, 4, 5].iter().cloned().collect();
let bto: PyObject = bt.clone().into_py(py);
let hso: PyObject = hs.clone().into_py(py);
assert_eq!(bt, bto.extract(py).unwrap());
assert_eq!(hs, hso.extract(py).unwrap());
}
} }