##// END OF EJS Templates
rust-pyo3: dagop submodule implementation...
Georges Racinet -
r53310:20fe0bf9 default
parent child Browse files
Show More
@@ -11,12 +11,63
11 11 //! From Python, this will be seen as `mercurial.pyo3-rustext.dagop`
12 12 use pyo3::prelude::*;
13 13
14 use std::collections::HashSet;
15
16 use hg::{dagops, Revision};
17
18 use crate::convert_cpython::{from_cpython_pyerr, proxy_index_extract};
19 use crate::exceptions::GraphError;
20 use crate::revision::{rev_pyiter_collect, PyRevision};
14 21 use crate::util::new_submodule;
15 22
23 /// Using the the `index_proxy`, return heads out of any Python iterable of
24 /// Revisions
25 ///
26 /// This is the Rust counterpart for `mercurial.dagop.headrevs`
27 #[pyfunction]
28 pub fn headrevs(
29 index_proxy: &Bound<'_, PyAny>,
30 revs: &Bound<'_, PyAny>,
31 ) -> PyResult<HashSet<PyRevision>> {
32 let (py, py_leaked) = proxy_index_extract(index_proxy)?;
33 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
34 let index = &*unsafe {
35 py_leaked
36 .try_borrow(py)
37 .map_err(|e| from_cpython_pyerr(py, e))?
38 };
39
40 let mut as_set: HashSet<Revision> = rev_pyiter_collect(revs, index)?;
41 dagops::retain_heads(index, &mut as_set).map_err(GraphError::from_hg)?;
42 Ok(as_set.into_iter().map(Into::into).collect())
43 }
44
45 /// Computes the rank, i.e. the number of ancestors including itself,
46 /// of a node represented by its parents.
47 ///
48 /// Currently, the pure Rust index supports only the REVLOGV1 format, hence
49 /// the only possible return value is that the rank is unknown.
50 ///
51 /// References:
52 /// - C implementation, function `index_fast_rank()`.
53 /// - `impl vcsgraph::graph::RankedGraph for Index` in `crate::cindex`.
54 #[pyfunction]
55 pub fn rank(
56 _index: &Bound<'_, PyAny>,
57 _p1r: PyRevision,
58 _p2r: PyRevision,
59 ) -> PyResult<()> {
60 Err(GraphError::from_vcsgraph(
61 vcsgraph::graph::GraphReadError::InconsistentGraphData,
62 ))
63 }
64
16 65 pub fn init_module<'py>(
17 66 py: Python<'py>,
18 67 package: &str,
19 68 ) -> PyResult<Bound<'py, PyModule>> {
20 69 let m = new_submodule(py, package, "dagop")?;
70 m.add_function(wrap_pyfunction!(headrevs, &m)?)?;
71 m.add_function(wrap_pyfunction!(rank, &m)?)?;
21 72 Ok(m)
22 73 }
@@ -5,11 +5,12 from mercurial.node import wdirrev
5 5 from mercurial.testing import revlog as revlogtesting
6 6
7 7 try:
8 from mercurial import rustext
8 from mercurial import pyo3_rustext, rustext
9 9
10 10 rustext.__name__ # trigger immediate actual import
11 pyo3_rustext.__name__
11 12 except ImportError:
12 rustext = None
13 rustext = pyo3_rustext = None
13 14 else:
14 15 # this would fail already without appropriate ancestor.__package__
15 16 from mercurial.rustext.ancestor import (
@@ -148,6 +149,17 class rustancestorstest(revlogtesting.Ru
148 149 idx = self.parserustindex()
149 150 self.assertEqual(dagop.headrevs(idx, [1, 2, 3]), {3})
150 151
152 def testpyo3_headrevs(self):
153 idx = self.parserustindex()
154 self.assertEqual(pyo3_rustext.dagop.headrevs(idx, [1, 2, 3]), {3})
155
156 def testpyo3_rank(self):
157 idx = self.parserustindex()
158 try:
159 pyo3_rustext.dagop.rank(idx, 1, 2)
160 except pyo3_rustext.GraphError as exc:
161 self.assertEqual(exc.args, ("InconsistentGraphData",))
162
151 163
152 164 if __name__ == '__main__':
153 165 import silenttestrunner
General Comments 0
You need to be logged in to leave comments. Login now