##// END OF EJS Templates
rust-discovery: exposing sampling to python...
Georges Racinet -
r42967:1c4b5689 default
parent child Browse files
Show More
@@ -1,135 +1,161 b''
1 // discovery.rs
1 // discovery.rs
2 //
2 //
3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
4 //
4 //
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 //! Bindings for the `hg::discovery` module provided by the
8 //! Bindings for the `hg::discovery` module provided by the
9 //! `hg-core` crate. From Python, this will be seen as `rustext.discovery`
9 //! `hg-core` crate. From Python, this will be seen as `rustext.discovery`
10 //!
10 //!
11 //! # Classes visible from Python:
11 //! # Classes visible from Python:
12 //! - [`PartialDiscover`] is the Rust implementation of
12 //! - [`PartialDiscover`] is the Rust implementation of
13 //! `mercurial.setdiscovery.partialdiscovery`.
13 //! `mercurial.setdiscovery.partialdiscovery`.
14
14
15 use crate::{
15 use crate::{
16 cindex::Index,
16 cindex::Index,
17 conversion::{py_set, rev_pyiter_collect},
17 conversion::{py_set, rev_pyiter_collect},
18 exceptions::GraphError,
18 exceptions::GraphError,
19 };
19 };
20 use cpython::{
20 use cpython::{
21 ObjectProtocol, PyDict, PyModule, PyObject, PyResult, Python,
21 ObjectProtocol, PyDict, PyModule, PyObject, PyResult, PyTuple, Python,
22 PythonObject, ToPyObject,
22 PythonObject, ToPyObject,
23 };
23 };
24 use hg::discovery::PartialDiscovery as CorePartialDiscovery;
24 use hg::discovery::PartialDiscovery as CorePartialDiscovery;
25 use hg::Revision;
25 use hg::Revision;
26
26
27 use std::cell::RefCell;
27 use std::cell::RefCell;
28
28
29 py_class!(pub class PartialDiscovery |py| {
29 py_class!(pub class PartialDiscovery |py| {
30 data inner: RefCell<Box<CorePartialDiscovery<Index>>>;
30 data inner: RefCell<Box<CorePartialDiscovery<Index>>>;
31
31
32 // `_respectsize` is currently only here to replicate the Python API and
32 // `_respectsize` is currently only here to replicate the Python API and
33 // will be used in future patches inside methods that are yet to be
33 // will be used in future patches inside methods that are yet to be
34 // implemented.
34 // implemented.
35 def __new__(
35 def __new__(
36 _cls,
36 _cls,
37 repo: PyObject,
37 repo: PyObject,
38 targetheads: PyObject,
38 targetheads: PyObject,
39 respectsize: bool
39 respectsize: bool
40 ) -> PyResult<PartialDiscovery> {
40 ) -> PyResult<PartialDiscovery> {
41 let index = repo.getattr(py, "changelog")?.getattr(py, "index")?;
41 let index = repo.getattr(py, "changelog")?.getattr(py, "index")?;
42 Self::create_instance(
42 Self::create_instance(
43 py,
43 py,
44 RefCell::new(Box::new(CorePartialDiscovery::new(
44 RefCell::new(Box::new(CorePartialDiscovery::new(
45 Index::new(py, index)?,
45 Index::new(py, index)?,
46 rev_pyiter_collect(py, &targetheads)?,
46 rev_pyiter_collect(py, &targetheads)?,
47 respectsize
47 respectsize
48 )))
48 )))
49 )
49 )
50 }
50 }
51
51
52 def addcommons(&self, commons: PyObject) -> PyResult<PyObject> {
52 def addcommons(&self, commons: PyObject) -> PyResult<PyObject> {
53 let mut inner = self.inner(py).borrow_mut();
53 let mut inner = self.inner(py).borrow_mut();
54 let commons_vec: Vec<Revision> = rev_pyiter_collect(py, &commons)?;
54 let commons_vec: Vec<Revision> = rev_pyiter_collect(py, &commons)?;
55 inner.add_common_revisions(commons_vec)
55 inner.add_common_revisions(commons_vec)
56 .map_err(|e| GraphError::pynew(py, e))?;
56 .map_err(|e| GraphError::pynew(py, e))?;
57 Ok(py.None())
57 Ok(py.None())
58 }
58 }
59
59
60 def addmissings(&self, missings: PyObject) -> PyResult<PyObject> {
60 def addmissings(&self, missings: PyObject) -> PyResult<PyObject> {
61 let mut inner = self.inner(py).borrow_mut();
61 let mut inner = self.inner(py).borrow_mut();
62 let missings_vec: Vec<Revision> = rev_pyiter_collect(py, &missings)?;
62 let missings_vec: Vec<Revision> = rev_pyiter_collect(py, &missings)?;
63 inner.add_missing_revisions(missings_vec)
63 inner.add_missing_revisions(missings_vec)
64 .map_err(|e| GraphError::pynew(py, e))?;
64 .map_err(|e| GraphError::pynew(py, e))?;
65 Ok(py.None())
65 Ok(py.None())
66 }
66 }
67
67
68 def addinfo(&self, sample: PyObject) -> PyResult<PyObject> {
68 def addinfo(&self, sample: PyObject) -> PyResult<PyObject> {
69 let mut missing: Vec<Revision> = Vec::new();
69 let mut missing: Vec<Revision> = Vec::new();
70 let mut common: Vec<Revision> = Vec::new();
70 let mut common: Vec<Revision> = Vec::new();
71 for info in sample.iter(py)? { // info is a pair (Revision, bool)
71 for info in sample.iter(py)? { // info is a pair (Revision, bool)
72 let mut revknown = info?.iter(py)?;
72 let mut revknown = info?.iter(py)?;
73 let rev: Revision = revknown.next().unwrap()?.extract(py)?;
73 let rev: Revision = revknown.next().unwrap()?.extract(py)?;
74 let known: bool = revknown.next().unwrap()?.extract(py)?;
74 let known: bool = revknown.next().unwrap()?.extract(py)?;
75 if known {
75 if known {
76 common.push(rev);
76 common.push(rev);
77 } else {
77 } else {
78 missing.push(rev);
78 missing.push(rev);
79 }
79 }
80 }
80 }
81 let mut inner = self.inner(py).borrow_mut();
81 let mut inner = self.inner(py).borrow_mut();
82 inner.add_common_revisions(common)
82 inner.add_common_revisions(common)
83 .map_err(|e| GraphError::pynew(py, e))?;
83 .map_err(|e| GraphError::pynew(py, e))?;
84 inner.add_missing_revisions(missing)
84 inner.add_missing_revisions(missing)
85 .map_err(|e| GraphError::pynew(py, e))?;
85 .map_err(|e| GraphError::pynew(py, e))?;
86 Ok(py.None())
86 Ok(py.None())
87 }
87 }
88
88
89 def hasinfo(&self) -> PyResult<bool> {
89 def hasinfo(&self) -> PyResult<bool> {
90 Ok(self.inner(py).borrow().has_info())
90 Ok(self.inner(py).borrow().has_info())
91 }
91 }
92
92
93 def iscomplete(&self) -> PyResult<bool> {
93 def iscomplete(&self) -> PyResult<bool> {
94 Ok(self.inner(py).borrow().is_complete())
94 Ok(self.inner(py).borrow().is_complete())
95 }
95 }
96
96
97 def stats(&self) -> PyResult<PyDict> {
97 def stats(&self) -> PyResult<PyDict> {
98 let stats = self.inner(py).borrow().stats();
98 let stats = self.inner(py).borrow().stats();
99 let as_dict: PyDict = PyDict::new(py);
99 let as_dict: PyDict = PyDict::new(py);
100 as_dict.set_item(py, "undecided",
100 as_dict.set_item(py, "undecided",
101 stats.undecided.map(
101 stats.undecided.map(
102 |l| l.to_py_object(py).into_object())
102 |l| l.to_py_object(py).into_object())
103 .unwrap_or_else(|| py.None()))?;
103 .unwrap_or_else(|| py.None()))?;
104 Ok(as_dict)
104 Ok(as_dict)
105 }
105 }
106
106
107 def commonheads(&self) -> PyResult<PyObject> {
107 def commonheads(&self) -> PyResult<PyObject> {
108 py_set(
108 py_set(
109 py,
109 py,
110 &self.inner(py).borrow().common_heads()
110 &self.inner(py).borrow().common_heads()
111 .map_err(|e| GraphError::pynew(py, e))?
111 .map_err(|e| GraphError::pynew(py, e))?
112 )
112 )
113 }
113 }
114
115 def takefullsample(&self, _headrevs: PyObject,
116 size: usize) -> PyResult<PyObject> {
117 let mut inner = self.inner(py).borrow_mut();
118 let sample = inner.take_full_sample(size)
119 .map_err(|e| GraphError::pynew(py, e))?;
120 let as_vec: Vec<PyObject> = sample
121 .iter()
122 .map(|rev| rev.to_py_object(py).into_object())
123 .collect();
124 Ok(PyTuple::new(py, as_vec.as_slice()).into_object())
125 }
126
127 def takequicksample(&self, headrevs: PyObject,
128 size: usize) -> PyResult<PyObject> {
129 let mut inner = self.inner(py).borrow_mut();
130 let revsvec: Vec<Revision> = rev_pyiter_collect(py, &headrevs)?;
131 let sample = inner.take_quick_sample(revsvec, size)
132 .map_err(|e| GraphError::pynew(py, e))?;
133 let as_vec: Vec<PyObject> = sample
134 .iter()
135 .map(|rev| rev.to_py_object(py).into_object())
136 .collect();
137 Ok(PyTuple::new(py, as_vec.as_slice()).into_object())
138 }
139
114 });
140 });
115
141
116 /// Create the module, with __package__ given from parent
142 /// Create the module, with __package__ given from parent
117 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
143 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
118 let dotted_name = &format!("{}.discovery", package);
144 let dotted_name = &format!("{}.discovery", package);
119 let m = PyModule::new(py, dotted_name)?;
145 let m = PyModule::new(py, dotted_name)?;
120 m.add(py, "__package__", package)?;
146 m.add(py, "__package__", package)?;
121 m.add(
147 m.add(
122 py,
148 py,
123 "__doc__",
149 "__doc__",
124 "Discovery of common node sets - Rust implementation",
150 "Discovery of common node sets - Rust implementation",
125 )?;
151 )?;
126 m.add_class::<PartialDiscovery>(py)?;
152 m.add_class::<PartialDiscovery>(py)?;
127
153
128 let sys = PyModule::import(py, "sys")?;
154 let sys = PyModule::import(py, "sys")?;
129 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
155 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
130 sys_modules.set_item(py, dotted_name, &m)?;
156 sys_modules.set_item(py, dotted_name, &m)?;
131 // Example C code (see pyexpat.c and import.c) will "give away the
157 // Example C code (see pyexpat.c and import.c) will "give away the
132 // reference", but we won't because it will be consumed once the
158 // reference", but we won't because it will be consumed once the
133 // Rust PyObject is dropped.
159 // Rust PyObject is dropped.
134 Ok(m)
160 Ok(m)
135 }
161 }
General Comments 0
You need to be logged in to leave comments. Login now