# HG changeset patch # User Georges Racinet # Date 1547484374 -3600 # Node ID 5257e6299d4c219e01f5e162ecdedcaa4af9fca4 # Parent 47881d2a9d99f2de0a391e2f00229b5bb7b9c149 rust-cpython: set conversion for MissingAncestors.bases() Also I hope that the separate `py_set()` helper will help transition to proper `PySet` support in `rust-cpython` Took the opportunity to replace explict for loop with iteration and collect(). Differential Revision: https://phab.mercurial-scm.org/D5581 diff -r 47881d2a9d99 -r 5257e6299d4c rust/hg-cpython/src/ancestors.rs --- a/rust/hg-cpython/src/ancestors.rs Mon Jan 14 10:07:48 2019 +0100 +++ b/rust/hg-cpython/src/ancestors.rs Mon Jan 14 17:46:14 2019 +0100 @@ -11,9 +11,9 @@ //! //! # Classes visible from Python: //! - [`LazyAncestors`] is the Rust implementation of -//! `mercurial.ancestor.lazyancestors`. -//! The only difference is that it is instantiated with a C `parsers.index` -//! instance instead of a parents function. +//! `mercurial.ancestor.lazyancestors`. The only difference is that it is +//! instantiated with a C `parsers.index` instance instead of a parents +//! function. //! //! - [`MissingAncestors`] is the Rust implementation of //! `mercurial.ancestor.incrementalmissingancestors`. @@ -27,9 +27,9 @@ //! is accepted. //! //! - [`AncestorsIterator`] is the Rust counterpart of the -//! `ancestor._lazyancestorsiter` Python generator. -//! From Python, instances of this should be mainly obtained by calling -//! `iter()` on a [`LazyAncestors`] instance. +//! `ancestor._lazyancestorsiter` Python generator. From Python, instances of +//! this should be mainly obtained by calling `iter()` on a [`LazyAncestors`] +//! instance. //! //! [`LazyAncestors`]: struct.LazyAncestors.html //! [`MissingAncestors`]: struct.MissingAncestors.html @@ -37,8 +37,8 @@ use crate::conversion::rev_pyiter_collect; use cindex::Index; use cpython::{ - ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject, - PyResult, PyTuple, Python, PythonObject, ToPyObject, + ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject, PyResult, + PyTuple, Python, PythonObject, ToPyObject, }; use exceptions::GraphError; use hg::Revision; @@ -90,6 +90,24 @@ } } +/// Copy and convert an `HashSet` in a Python set +/// +/// This will probably turn useless once `PySet` support lands in +/// `rust-cpython`. +/// +/// This builds a Python tuple, then calls Python's "set()" on it +fn py_set(py: Python, set: &HashSet) -> PyResult { + let as_vec: Vec = set + .iter() + .map(|rev| rev.to_py_object(py).into_object()) + .collect(); + let as_pytuple = PyTuple::new(py, as_vec.as_slice()); + + let locals = PyDict::new(py); + locals.set_item(py, "obj", as_pytuple.to_py_object(py))?; + py.eval("set(obj)", None, Some(&locals)) +} + py_class!(pub class LazyAncestors |py| { data inner: RefCell>>; @@ -144,16 +162,8 @@ Ok(py.None()) } - def bases(&self) -> PyResult { - let inner = self.inner(py).borrow(); - let bases_set = inner.get_bases(); - // convert as Python tuple TODO how to return a proper Python set? - let mut bases_vec: Vec = Vec::with_capacity( - bases_set.len()); - for rev in bases_set { - bases_vec.push(rev.to_py_object(py).into_object()); - } - Ok(PyTuple::new(py, bases_vec.as_slice())) + def bases(&self) -> PyResult { + py_set(py, self.inner(py).borrow().get_bases()) } def removeancestorsfrom(&self, revs: PyObject) -> PyResult { diff -r 47881d2a9d99 -r 5257e6299d4c tests/test-rust-ancestor.py --- a/tests/test-rust-ancestor.py Mon Jan 14 10:07:48 2019 +0100 +++ b/tests/test-rust-ancestor.py Mon Jan 14 17:46:14 2019 +0100 @@ -112,7 +112,7 @@ self.assertTrue(missanc.hasbases()) self.assertEqual(missanc.missingancestors([3]), [2, 3]) missanc.addbases({2}) - self.assertEqual(set(missanc.bases()), {1, 2}) + self.assertEqual(missanc.bases(), {1, 2}) self.assertEqual(missanc.missingancestors([3]), [3]) def testmissingancestorsremove(self):