annotate rust/hg-cpython/src/ancestors.rs @ 41228:3b35ebdb9f8c

narrow: include working copy narrowspec in transaction journal Now that we have separate narrowspecs for the store and the working copy, we need to include both in the transaction journal. Differential Revision: https://phab.mercurial-scm.org/D5505
author Martin von Zweigbergk <martinvonz@google.com>
date Sat, 29 Dec 2018 22:34:38 -0800
parents 006c9ce486fa
children ff333620a4cc
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
1 // ancestors.rs
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
2 //
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
4 //
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
5 // This software may be used and distributed according to the terms of the
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
6 // GNU General Public License version 2 or any later version.
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
7
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
8 //! Bindings for the `hg::ancestors` module provided by the
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
9 //! `hg-core` crate. From Python, this will be seen as `rustext.ancestor`
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
10 //! and can be used as replacement for the the pure `ancestor` Python module.
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
11 //!
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
12 //! # Classes visible from Python:
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
13 //! - [`LazyAncestors`] is the Rust implementation of
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
14 //! `mercurial.ancestor.lazyancestors`.
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
15 //! The only difference is that it is instantiated with a C `parsers.index`
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
16 //! instance instead of a parents function.
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
17 //!
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
18 //! - [`MissingAncestors`] is the Rust implementation of
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
19 //! `mercurial.ancestor.incrementalmissingancestors`.
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
20 //!
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
21 //! API differences:
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
22 //! + it is instantiated with a C `parsers.index`
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
23 //! instance instead of a parents function.
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
24 //! + `MissingAncestors.bases` is a method returning a tuple instead of
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
25 //! a set-valued attribute. We could return a Python set easily if our
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
26 //! [PySet PR](https://github.com/dgrunwald/rust-cpython/pull/165)
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
27 //! is accepted.
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
28 //!
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
29 //! - [`AncestorsIterator`] is the Rust counterpart of the
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
30 //! `ancestor._lazyancestorsiter` Python generator.
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
31 //! From Python, instances of this should be mainly obtained by calling
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
32 //! `iter()` on a [`LazyAncestors`] instance.
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
33 //!
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
34 //! [`LazyAncestors`]: struct.LazyAncestors.html
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
35 //! [`MissingAncestors`]: struct.MissingAncestors.html
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
36 //! [`AncestorsIterator`]: struct.AncestorsIterator.html
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
37 use cindex::Index;
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
38 use cpython::{
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
39 ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject,
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
40 PyResult, PyTuple, Python, PythonObject, ToPyObject,
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
41 };
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
42 use exceptions::GraphError;
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
43 use hg::Revision;
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
44 use hg::{
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
45 AncestorsIterator as CoreIterator, LazyAncestors as CoreLazy,
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
46 MissingAncestors as CoreMissing,
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
47 };
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
48 use std::cell::RefCell;
41187
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
49 use std::iter::FromIterator;
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
50 use std::collections::HashSet;
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
51
41187
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
52 /// Utility function to convert a Python iterable into various collections
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
53 ///
41187
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
54 /// We need this in particular to feed to various methods of inner objects
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
55 /// with `impl IntoIterator<Item=Revision>` arguments, because
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
56 /// a `PyErr` can arise at each step of iteration, whereas these methods
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
57 /// expect iterables over `Revision`, not over some `Result<Revision, PyErr>`
41187
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
58 fn rev_pyiter_collect<C>(py: Python, revs: &PyObject) -> PyResult<C>
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
59 where
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
60 C: FromIterator<Revision>,
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
61 {
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
62 revs.iter(py)?
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
63 .map(|r| r.and_then(|o| o.extract::<Revision>(py)))
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
64 .collect()
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
65 }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
66
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
67 py_class!(pub class AncestorsIterator |py| {
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
68 data inner: RefCell<Box<CoreIterator<Index>>>;
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
69
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
70 def __next__(&self) -> PyResult<Option<Revision>> {
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
71 match self.inner(py).borrow_mut().next() {
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
72 Some(Err(e)) => Err(GraphError::pynew(py, e)),
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
73 None => Ok(None),
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
74 Some(Ok(r)) => Ok(Some(r)),
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
75 }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
76 }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
77
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
78 def __contains__(&self, rev: Revision) -> PyResult<bool> {
41186
1b4b94bac8a0 rust-cpython: style consistency leftovers
Georges Racinet <georges.racinet@octobus.net>
parents: 41185
diff changeset
79 self.inner(py).borrow_mut().contains(rev)
1b4b94bac8a0 rust-cpython: style consistency leftovers
Georges Racinet <georges.racinet@octobus.net>
parents: 41185
diff changeset
80 .map_err(|e| GraphError::pynew(py, e))
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
81 }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
82
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
83 def __iter__(&self) -> PyResult<Self> {
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
84 Ok(self.clone_ref(py))
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
85 }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
86
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
87 def __new__(_cls, index: PyObject, initrevs: PyObject, stoprev: Revision,
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
88 inclusive: bool) -> PyResult<AncestorsIterator> {
41187
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
89 let initvec: Vec<Revision> = rev_pyiter_collect(py, &initrevs)?;
41186
1b4b94bac8a0 rust-cpython: style consistency leftovers
Georges Racinet <georges.racinet@octobus.net>
parents: 41185
diff changeset
90 let ait = CoreIterator::new(
1b4b94bac8a0 rust-cpython: style consistency leftovers
Georges Racinet <georges.racinet@octobus.net>
parents: 41185
diff changeset
91 Index::new(py, index)?,
1b4b94bac8a0 rust-cpython: style consistency leftovers
Georges Racinet <georges.racinet@octobus.net>
parents: 41185
diff changeset
92 initvec,
1b4b94bac8a0 rust-cpython: style consistency leftovers
Georges Racinet <georges.racinet@octobus.net>
parents: 41185
diff changeset
93 stoprev,
1b4b94bac8a0 rust-cpython: style consistency leftovers
Georges Racinet <georges.racinet@octobus.net>
parents: 41185
diff changeset
94 inclusive,
1b4b94bac8a0 rust-cpython: style consistency leftovers
Georges Racinet <georges.racinet@octobus.net>
parents: 41185
diff changeset
95 )
1b4b94bac8a0 rust-cpython: style consistency leftovers
Georges Racinet <georges.racinet@octobus.net>
parents: 41185
diff changeset
96 .map_err(|e| GraphError::pynew(py, e))?;
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
97 AncestorsIterator::from_inner(py, ait)
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
98 }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
99
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
100 });
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
101
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
102 impl AncestorsIterator {
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
103 pub fn from_inner(py: Python, ait: CoreIterator<Index>) -> PyResult<Self> {
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
104 Self::create_instance(py, RefCell::new(Box::new(ait)))
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
105 }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
106 }
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
107
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
108 py_class!(pub class LazyAncestors |py| {
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
109 data inner: RefCell<Box<CoreLazy<Index>>>;
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
110
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
111 def __contains__(&self, rev: Revision) -> PyResult<bool> {
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
112 self.inner(py)
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
113 .borrow_mut()
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
114 .contains(rev)
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
115 .map_err(|e| GraphError::pynew(py, e))
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
116 }
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
117
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
118 def __iter__(&self) -> PyResult<AncestorsIterator> {
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
119 AncestorsIterator::from_inner(py, self.inner(py).borrow().iter())
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
120 }
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
121
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
122 def __bool__(&self) -> PyResult<bool> {
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
123 Ok(!self.inner(py).borrow().is_empty())
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
124 }
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
125
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
126 def __new__(_cls, index: PyObject, initrevs: PyObject, stoprev: Revision,
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
127 inclusive: bool) -> PyResult<Self> {
41187
3bf6979a1785 rust-cpython: generalised conversion function
Georges Racinet <georges.racinet@octobus.net>
parents: 41186
diff changeset
128 let initvec: Vec<Revision> = rev_pyiter_collect(py, &initrevs)?;
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
129
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
130 let lazy =
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
131 CoreLazy::new(Index::new(py, index)?, initvec, stoprev, inclusive)
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
132 .map_err(|e| GraphError::pynew(py, e))?;
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
133
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
134 Self::create_instance(py, RefCell::new(Box::new(lazy)))
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
135 }
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
136
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
137 });
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
138
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
139 py_class!(pub class MissingAncestors |py| {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
140 data inner: RefCell<Box<CoreMissing<Index>>>;
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
141
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
142 def __new__(_cls, index: PyObject, bases: PyObject) -> PyResult<MissingAncestors> {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
143 let bases_vec: Vec<Revision> = rev_pyiter_collect(py, &bases)?;
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
144 let inner = CoreMissing::new(Index::new(py, index)?, bases_vec);
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
145 MissingAncestors::create_instance(py, RefCell::new(Box::new(inner)))
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
146 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
147
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
148 def hasbases(&self) -> PyResult<bool> {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
149 Ok(self.inner(py).borrow().has_bases())
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
150 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
151
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
152 def addbases(&self, bases: PyObject) -> PyResult<PyObject> {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
153 let mut inner = self.inner(py).borrow_mut();
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
154 let bases_vec: Vec<Revision> = rev_pyiter_collect(py, &bases)?;
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
155 inner.add_bases(bases_vec);
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
156 // cpython doc has examples with PyResult<()> but this gives me
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
157 // the trait `cpython::ToPyObject` is not implemented for `()`
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
158 // so let's return an explicit None
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
159 Ok(py.None())
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
160 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
161
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
162 def bases(&self) -> PyResult<PyTuple> {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
163 let inner = self.inner(py).borrow();
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
164 let bases_set = inner.get_bases();
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
165 // convert as Python tuple TODO how to return a proper Python set?
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
166 let mut bases_vec: Vec<PyObject> = Vec::with_capacity(
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
167 bases_set.len());
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
168 for rev in bases_set {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
169 bases_vec.push(rev.to_py_object(py).into_object());
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
170 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
171 Ok(PyTuple::new(py, bases_vec.as_slice()))
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
172 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
173
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
174 def removeancestorsfrom(&self, revs: PyObject) -> PyResult<PyObject> {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
175 let mut inner = self.inner(py).borrow_mut();
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
176 // this is very lame: we convert to a Rust set, update it in place
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
177 // and then convert back to Python, only to have Python remove the
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
178 // excess (thankfully, Python is happy with a list or even an iterator)
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
179 // Leads to improve this:
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
180 // - have the CoreMissing instead do something emit revisions to
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
181 // discard
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
182 // - define a trait for sets of revisions in the core and implement
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
183 // it for a Python set rewrapped with the GIL marker
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
184 let mut revs_pyset: HashSet<Revision> = rev_pyiter_collect(py, &revs)?;
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
185 inner.remove_ancestors_from(&mut revs_pyset)
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
186 .map_err(|e| GraphError::pynew(py, e))?;
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
187
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
188 // convert as Python list
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
189 let mut remaining_pyint_vec: Vec<PyObject> = Vec::with_capacity(
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
190 revs_pyset.len());
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
191 for rev in revs_pyset {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
192 remaining_pyint_vec.push(rev.to_py_object(py).into_object());
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
193 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
194 let remaining_pylist = PyList::new(py, remaining_pyint_vec.as_slice());
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
195 revs.call_method(py, "intersection_update", (remaining_pylist, ), None)
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
196 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
197
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
198 def missingancestors(&self, revs: PyObject) -> PyResult<PyList> {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
199 let mut inner = self.inner(py).borrow_mut();
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
200 let revs_vec: Vec<Revision> = rev_pyiter_collect(py, &revs)?;
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
201 let missing_vec = match inner.missing_ancestors(revs_vec) {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
202 Ok(missing) => missing,
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
203 Err(e) => {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
204 return Err(GraphError::pynew(py, e));
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
205 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
206 };
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
207 // convert as Python list
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
208 let mut missing_pyint_vec: Vec<PyObject> = Vec::with_capacity(
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
209 missing_vec.len());
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
210 for rev in missing_vec {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
211 missing_pyint_vec.push(rev.to_py_object(py).into_object());
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
212 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
213 Ok(PyList::new(py, missing_pyint_vec.as_slice()))
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
214 }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
215 });
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
216
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
217 /// Create the module, with __package__ given from parent
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
218 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
219 let dotted_name = &format!("{}.ancestor", package);
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
220 let m = PyModule::new(py, dotted_name)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
221 m.add(py, "__package__", package)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
222 m.add(
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
223 py,
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
224 "__doc__",
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
225 "Generic DAG ancestor algorithms - Rust implementation",
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
226 )?;
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
227 m.add_class::<AncestorsIterator>(py)?;
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
228 m.add_class::<LazyAncestors>(py)?;
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
229 m.add_class::<MissingAncestors>(py)?;
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
230
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
231 let sys = PyModule::import(py, "sys")?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
232 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
233 sys_modules.set_item(py, dotted_name, &m)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
234 // Example C code (see pyexpat.c and import.c) will "give away the
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
235 // reference", but we won't because it will be consumed once the
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
236 // Rust PyObject is dropped.
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
237 Ok(m)
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
238 }