diff --git a/rust/hg-cpython/src/ancestors.rs b/rust/hg-cpython/src/ancestors.rs --- a/rust/hg-cpython/src/ancestors.rs +++ b/rust/hg-cpython/src/ancestors.rs @@ -34,6 +34,7 @@ //! [`LazyAncestors`]: struct.LazyAncestors.html //! [`MissingAncestors`]: struct.MissingAncestors.html //! [`AncestorsIterator`]: struct.AncestorsIterator.html +use crate::conversion::rev_pyiter_collect; use cindex::Index; use cpython::{ ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject, @@ -46,24 +47,8 @@ MissingAncestors as CoreMissing, }; use std::cell::RefCell; -use std::iter::FromIterator; use std::collections::HashSet; -/// Utility function to convert a Python iterable into various collections -/// -/// We need this in particular to feed to various methods of inner objects -/// with `impl IntoIterator` arguments, because -/// a `PyErr` can arise at each step of iteration, whereas these methods -/// expect iterables over `Revision`, not over some `Result` -fn rev_pyiter_collect(py: Python, revs: &PyObject) -> PyResult -where - C: FromIterator, -{ - revs.iter(py)? - .map(|r| r.and_then(|o| o.extract::(py))) - .collect() -} - py_class!(pub class AncestorsIterator |py| { data inner: RefCell>>; diff --git a/rust/hg-cpython/src/conversion.rs b/rust/hg-cpython/src/conversion.rs new file mode 100644 --- /dev/null +++ b/rust/hg-cpython/src/conversion.rs @@ -0,0 +1,28 @@ +// conversion.rs +// +// Copyright 2019 Georges Racinet +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. + +//! Bindings for the hg::ancestors module provided by the +//! `hg-core` crate. From Python, this will be seen as `rustext.ancestor` + +use cpython::{ObjectProtocol, PyObject, PyResult, Python}; +use hg::Revision; +use std::iter::FromIterator; + +/// Utility function to convert a Python iterable into various collections +/// +/// We need this in particular to feed to various methods of inner objects +/// with `impl IntoIterator` arguments, because +/// a `PyErr` can arise at each step of iteration, whereas these methods +/// expect iterables over `Revision`, not over some `Result` +pub fn rev_pyiter_collect(py: Python, revs: &PyObject) -> PyResult +where + C: FromIterator, +{ + revs.iter(py)? + .map(|r| r.and_then(|o| o.extract::(py))) + .collect() +} diff --git a/rust/hg-cpython/src/lib.rs b/rust/hg-cpython/src/lib.rs --- a/rust/hg-cpython/src/lib.rs +++ b/rust/hg-cpython/src/lib.rs @@ -26,6 +26,7 @@ pub mod ancestors; mod cindex; +mod conversion; pub mod exceptions; py_module_initializer!(rustext, initrustext, PyInit_rustext, |py, m| {