##// 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 //! From Python, this will be seen as `mercurial.pyo3-rustext.dagop`
11 //! From Python, this will be seen as `mercurial.pyo3-rustext.dagop`
12 use pyo3::prelude::*;
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 use crate::util::new_submodule;
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 pub fn init_module<'py>(
65 pub fn init_module<'py>(
17 py: Python<'py>,
66 py: Python<'py>,
18 package: &str,
67 package: &str,
19 ) -> PyResult<Bound<'py, PyModule>> {
68 ) -> PyResult<Bound<'py, PyModule>> {
20 let m = new_submodule(py, package, "dagop")?;
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 Ok(m)
72 Ok(m)
22 }
73 }
@@ -5,11 +5,12 from mercurial.node import wdirrev
5 from mercurial.testing import revlog as revlogtesting
5 from mercurial.testing import revlog as revlogtesting
6
6
7 try:
7 try:
8 from mercurial import rustext
8 from mercurial import pyo3_rustext, rustext
9
9
10 rustext.__name__ # trigger immediate actual import
10 rustext.__name__ # trigger immediate actual import
11 pyo3_rustext.__name__
11 except ImportError:
12 except ImportError:
12 rustext = None
13 rustext = pyo3_rustext = None
13 else:
14 else:
14 # this would fail already without appropriate ancestor.__package__
15 # this would fail already without appropriate ancestor.__package__
15 from mercurial.rustext.ancestor import (
16 from mercurial.rustext.ancestor import (
@@ -148,6 +149,17 class rustancestorstest(revlogtesting.Ru
148 idx = self.parserustindex()
149 idx = self.parserustindex()
149 self.assertEqual(dagop.headrevs(idx, [1, 2, 3]), {3})
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 if __name__ == '__main__':
164 if __name__ == '__main__':
153 import silenttestrunner
165 import silenttestrunner
General Comments 0
You need to be logged in to leave comments. Login now