diff --git a/CHANGELOG.md b/CHANGELOG.md index cc743503..1879d72d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## Unreleased +### Added +* `FromPyObject` implementations for `HashSet` and `BTreeSet`. [#842](https://github.com/PyO3/pyo3/pull/842) + ## [0.9.1] ### Fixed diff --git a/src/types/set.rs b/src/types/set.rs index 0e4b6a03..39a1afed 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -4,8 +4,11 @@ use crate::err::{self, PyErr, PyResult}; use crate::internal_tricks::Unsendable; use crate::{ - ffi, AsPyPointer, PyAny, PyNativeType, PyObject, Python, ToBorrowedObject, ToPyObject, + ffi, AsPyPointer, FromPyObject, PyAny, PyNativeType, PyObject, PyTryFrom, Python, + ToBorrowedObject, ToPyObject, }; +use std::cmp; +use std::collections::{BTreeSet, HashSet}; use std::{collections, hash, ptr}; /// Represents a Python `set` @@ -181,6 +184,35 @@ where } } +impl<'source, K, S> FromPyObject<'source> for HashSet +where + K: FromPyObject<'source> + cmp::Eq + hash::Hash, + S: hash::BuildHasher + Default, +{ + fn extract(ob: &'source PyAny) -> Result { + let set = ::try_from(ob)?; + let mut ret = HashSet::default(); + for k in set.iter() { + ret.insert(K::extract(k)?); + } + Ok(ret) + } +} + +impl<'source, K> FromPyObject<'source> for BTreeSet +where + K: FromPyObject<'source> + cmp::Ord, +{ + fn extract(ob: &'source PyAny) -> Result { + let set = ::try_from(ob)?; + let mut ret = BTreeSet::default(); + for k in set.iter() { + ret.insert(K::extract(k)?); + } + Ok(ret) + } +} + impl PyFrozenSet { /// Creates a new frozenset. ///