rust/hg-cpython/src/ancestors.rs
author Raphaël Gomès <rgomes@octobus.net>
Wed, 20 Dec 2023 14:59:31 +0100
changeset 51272 c4cbb515b006
parent 51255 24d3298189d7
child 51692 771598067be2
permissions -rw-r--r--
rust-clippy: apply some more trivial fixes All of these were hinted at by clippy and make the code simpler.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
41243
5257e6299d4c rust-cpython: set conversion for MissingAncestors.bases()
Georges Racinet <georges.racinet@octobus.net>
parents: 41240
diff changeset
    14
//!   `mercurial.ancestor.lazyancestors`. The only difference is that it is
5257e6299d4c rust-cpython: set conversion for MissingAncestors.bases()
Georges Racinet <georges.racinet@octobus.net>
parents: 41240
diff changeset
    15
//!   instantiated with a C `parsers.index` instance instead of a parents
5257e6299d4c rust-cpython: set conversion for MissingAncestors.bases()
Georges Racinet <georges.racinet@octobus.net>
parents: 41240
diff changeset
    16
//!   function.
41184
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
41243
5257e6299d4c rust-cpython: set conversion for MissingAncestors.bases()
Georges Racinet <georges.racinet@octobus.net>
parents: 41240
diff changeset
    30
//!   `ancestor._lazyancestorsiter` Python generator. From Python, instances of
5257e6299d4c rust-cpython: set conversion for MissingAncestors.bases()
Georges Racinet <georges.racinet@octobus.net>
parents: 41240
diff changeset
    31
//!   this should be mainly obtained by calling `iter()` on a [`LazyAncestors`]
5257e6299d4c rust-cpython: set conversion for MissingAncestors.bases()
Georges Racinet <georges.racinet@octobus.net>
parents: 41240
diff changeset
    32
//!   instance.
41184
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
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
    37
use crate::revlog::py_rust_index_to_graph;
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
    38
use crate::PyRevision;
42609
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    39
use crate::{
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
    40
    conversion::rev_pyiter_collect, exceptions::GraphError,
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    41
    revlog::PySharedIndex,
42609
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    42
};
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    43
use cpython::{
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    44
    ObjectProtocol, PyClone, PyDict, PyErr, PyList, PyModule, PyObject,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    45
    PyResult, Python, PythonObject, ToPyObject, UnsafePyLeaked,
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    46
};
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    47
48519
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
    48
use hg::MissingAncestors as CoreMissing;
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    49
use hg::Revision;
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    50
use std::cell::RefCell;
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
    51
use std::collections::HashSet;
48519
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
    52
use vcsgraph::lazy_ancestors::{
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
    53
    AncestorsIterator as VCGAncestorsIterator,
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
    54
    LazyAncestors as VCGLazyAncestors,
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
    55
};
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    56
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    57
// Error propagation for an [`UnsafePyLeaked`] wrapping a [`Result`]
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    58
//
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    59
// It would be nice for UnsharedPyLeaked to provide this directly as a variant
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    60
// of the `map` method with a signature such as:
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    61
//
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    62
// ```
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
    63
//   unsafe fn map_or_err(py: Python,
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
    64
//                        f: impl FnOnce(T) -> Result(U, E),
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
    65
//                        convert_err: impl FnOnce(Python, E) -> PyErr)
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    66
// ```
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    67
//
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    68
// This would spare users of the `cpython` crate the additional `unsafe` deref
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    69
// to inspect the error and return it outside `UnsafePyLeaked`, and the
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    70
// subsequent unwrapping that this function performs.
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    71
fn pyleaked_or_map_err<T, E: std::fmt::Debug + Copy>(
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    72
    py: Python,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    73
    leaked: UnsafePyLeaked<Result<T, E>>,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    74
    convert_err: impl FnOnce(Python, E) -> PyErr,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    75
) -> PyResult<UnsafePyLeaked<T>> {
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    76
    // Result.inspect_err is unstable in Rust 1.61
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
    77
    // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    78
    if let Err(e) = *unsafe { leaked.try_borrow(py)? } {
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    79
        return Err(convert_err(py, e));
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    80
    }
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
    81
    // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    82
    Ok(unsafe {
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    83
        leaked.map(py, |res| {
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    84
            res.expect("Error case should have already be treated")
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    85
        })
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    86
    })
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    87
}
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    88
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
    89
py_class!(pub class AncestorsIterator |py| {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    90
    data inner: RefCell<UnsafePyLeaked<VCGAncestorsIterator<PySharedIndex>>>;
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    91
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
    92
    def __next__(&self) -> PyResult<Option<PyRevision>> {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    93
        let mut leaked = self.inner(py).borrow_mut();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
    94
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    95
        let mut inner = unsafe { leaked.try_borrow_mut(py)? };
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
    96
        match inner.next() {
48519
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
    97
            Some(Err(e)) => Err(GraphError::pynew_from_vcsgraph(py, e)),
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    98
            None => Ok(None),
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
    99
            Some(Ok(r)) => Ok(Some(PyRevision(r))),
41053
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
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   103
    def __contains__(&self, rev: PyRevision) -> PyResult<bool> {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   104
        let mut leaked = self.inner(py).borrow_mut();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   105
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   106
        let mut inner = unsafe { leaked.try_borrow_mut(py)? };
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   107
        inner.contains(rev.0)
48519
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
   108
            .map_err(|e| GraphError::pynew_from_vcsgraph(py, e))
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   109
    }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   110
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   111
    def __iter__(&self) -> PyResult<Self> {
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   112
        Ok(self.clone_ref(py))
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   113
    }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   114
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   115
    def __new__(
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   116
        _cls,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   117
        index: PyObject,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   118
        initrevs: PyObject,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   119
        stoprev: PyRevision,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   120
        inclusive: bool
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   121
    ) -> PyResult<AncestorsIterator> {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   122
        Self::inner_new(py, index, initrevs, stoprev, inclusive)
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   123
    }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   124
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   125
});
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   126
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   127
impl AncestorsIterator {
48519
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
   128
    pub fn from_inner(
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
   129
        py: Python,
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   130
        ait: UnsafePyLeaked<VCGAncestorsIterator<PySharedIndex>>,
48519
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
   131
    ) -> PyResult<Self> {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   132
        Self::create_instance(py, RefCell::new(ait))
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   133
    }
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   134
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   135
    pub fn inner_new(
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   136
        py: Python,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   137
        index: PyObject,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   138
        initrevs: PyObject,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   139
        stoprev: PyRevision,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   140
        inclusive: bool,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   141
    ) -> PyResult<AncestorsIterator> {
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   142
        let index = py_rust_index_to_graph(py, index)?;
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   143
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   144
        let initvec: Vec<_> = {
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   145
            let borrowed_idx = unsafe { index.try_borrow(py)? };
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   146
            rev_pyiter_collect(py, &initrevs, &*borrowed_idx)?
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   147
        };
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   148
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   149
        let res_ait = unsafe {
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   150
            index.map(py, |idx| {
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   151
                VCGAncestorsIterator::new(
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   152
                    idx,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   153
                    initvec.into_iter().map(|r| r.0),
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   154
                    stoprev.0,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   155
                    inclusive,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   156
                )
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   157
            })
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   158
        };
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   159
        let ait =
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   160
            pyleaked_or_map_err(py, res_ait, GraphError::pynew_from_vcsgraph)?;
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   161
        AncestorsIterator::from_inner(py, ait)
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   162
    }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   163
}
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   164
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41114
diff changeset
   165
py_class!(pub class LazyAncestors |py| {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   166
    data inner: RefCell<UnsafePyLeaked<
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   167
        RefCell<VCGLazyAncestors<PySharedIndex>>
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   168
        >>;
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   169
    data index: PyObject;
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   170
    data initrevs: PyObject;
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   171
    data stoprev: PyRevision;
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   172
    data inclusive: bool;
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   173
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   174
    def __contains__(&self, rev: PyRevision) -> PyResult<bool> {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   175
        let leaked = self.inner(py).borrow();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   176
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   177
        let inner: &RefCell<VCGLazyAncestors<PySharedIndex>> =
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   178
            &*unsafe { leaked.try_borrow(py)? };
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   179
        let inner_mut: &mut VCGLazyAncestors<PySharedIndex> =
51272
c4cbb515b006 rust-clippy: apply some more trivial fixes
Raphaël Gomès <rgomes@octobus.net>
parents: 51255
diff changeset
   180
            &mut inner.borrow_mut();
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   181
        inner_mut.contains(rev.0)
48519
35ebe6f824be hg-cpython: use ancestor iterator impls from vcsgraph
pacien <pacien.trangirard@pacien.net>
parents: 44431
diff changeset
   182
            .map_err(|e| GraphError::pynew_from_vcsgraph(py, e))
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   183
    }
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   184
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   185
    def __iter__(&self) -> PyResult<AncestorsIterator> {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   186
        let index = self.index(py).clone_ref(py);
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   187
        let initrevs = self.initrevs(py).clone_ref(py);
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   188
        AncestorsIterator::inner_new(py, index, initrevs,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   189
                                     *self.stoprev(py),
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   190
                                     *self.inclusive(py))
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   191
    }
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   192
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   193
    def __bool__(&self) -> PyResult<bool> {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   194
        let leaked = self.inner(py).borrow();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   195
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   196
        let inner = unsafe { leaked.try_borrow(py)? };
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   197
        let empty = inner.borrow().is_empty();
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   198
        Ok(!empty)
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   199
    }
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   200
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   201
    def __new__(
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   202
        _cls,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   203
        index: PyObject,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   204
        initrevs: PyObject,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   205
        stoprev: PyRevision,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   206
        inclusive: bool
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   207
    ) -> PyResult<Self> {
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   208
        let cloned_index = index.clone_ref(py);
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   209
        let index = py_rust_index_to_graph(py, index)?;
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   210
        let initvec: Vec<_> = {
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   211
            // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   212
            let borrowed_idx =  unsafe {index.try_borrow(py)?};
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   213
            rev_pyiter_collect(py, &initrevs, &*borrowed_idx)?
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   214
        };
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   215
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   216
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   217
        let res_lazy =
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   218
            unsafe { index.map(py, |idx| VCGLazyAncestors::new(
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   219
                idx,
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   220
                initvec.into_iter().map(|r| r.0),
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   221
                stoprev.0,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   222
                inclusive
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   223
            ))};
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   224
        let lazy = pyleaked_or_map_err(py, res_lazy,
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   225
                                       GraphError::pynew_from_vcsgraph)?;
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   226
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51239
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   227
        let lazy_cell = unsafe { lazy.map(py, RefCell::new)};
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   228
        let res = Self::create_instance(
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   229
            py, RefCell::new(lazy_cell),
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   230
            cloned_index, initrevs, stoprev, inclusive)?;
7eea2e4109ae rust-index: using the `hg::index::Index` in ancestors iterator and lazy set
Georges Racinet <georges.racinet@octobus.net>
parents: 50979
diff changeset
   231
        Ok(res)
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   232
        }
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   233
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   234
});
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   235
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   236
py_class!(pub class MissingAncestors |py| {
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   237
    data inner: RefCell<UnsafePyLeaked<
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   238
        CoreMissing<PySharedIndex>
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   239
        >>;
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   240
    data index: PyObject;
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   241
44431
b24721e7c5ee rust-format: cleanup ancestors.rs to make rustfmt happy
Raphaël Gomès <rgomes@octobus.net>
parents: 43945
diff changeset
   242
    def __new__(
b24721e7c5ee rust-format: cleanup ancestors.rs to make rustfmt happy
Raphaël Gomès <rgomes@octobus.net>
parents: 43945
diff changeset
   243
        _cls,
b24721e7c5ee rust-format: cleanup ancestors.rs to make rustfmt happy
Raphaël Gomès <rgomes@octobus.net>
parents: 43945
diff changeset
   244
        index: PyObject,
b24721e7c5ee rust-format: cleanup ancestors.rs to make rustfmt happy
Raphaël Gomès <rgomes@octobus.net>
parents: 43945
diff changeset
   245
        bases: PyObject
b24721e7c5ee rust-format: cleanup ancestors.rs to make rustfmt happy
Raphaël Gomès <rgomes@octobus.net>
parents: 43945
diff changeset
   246
    )
b24721e7c5ee rust-format: cleanup ancestors.rs to make rustfmt happy
Raphaël Gomès <rgomes@octobus.net>
parents: 43945
diff changeset
   247
    -> PyResult<MissingAncestors> {
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   248
        let cloned_index = index.clone_ref(py);
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   249
        let inner_index = py_rust_index_to_graph(py, index)?;
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   250
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   251
        let bases_vec: Vec<_> = {
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   252
            let borrowed_idx = unsafe { inner_index.try_borrow(py)? };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   253
            rev_pyiter_collect(py, &bases, &*borrowed_idx)?
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   254
        };
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   255
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   256
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   257
        let inner = unsafe {
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   258
            inner_index.map(py, |idx| CoreMissing::new(idx, bases_vec))
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   259
        };
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   260
        MissingAncestors::create_instance(
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   261
            py,
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   262
            RefCell::new(inner),
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   263
            cloned_index,
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   264
        )
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   265
    }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   266
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   267
    def hasbases(&self) -> PyResult<bool> {
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   268
        let leaked = self.inner(py).borrow();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   269
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   270
        let inner: &CoreMissing<PySharedIndex> =
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   271
            &*unsafe { leaked.try_borrow(py)? };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   272
        Ok(inner.has_bases())
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   273
    }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   274
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   275
    def addbases(&self, bases: PyObject) -> PyResult<PyObject> {
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   276
        let bases_vec: Vec<_> = {
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   277
            let leaked = py_rust_index_to_graph(py,
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   278
                                               self.index(py).clone_ref(py))?;
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   279
            // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   280
            let index = &*unsafe { leaked.try_borrow(py)? };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   281
            rev_pyiter_collect(py, &bases, index)?
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   282
        };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   283
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   284
        let mut leaked = self.inner(py).borrow_mut();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   285
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   286
        let inner: &mut CoreMissing<PySharedIndex> =
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   287
            &mut *unsafe { leaked.try_borrow_mut(py)? };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   288
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   289
        inner.add_bases(bases_vec);
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   290
        // 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
   291
        //   the trait `cpython::ToPyObject` is not implemented for `()`
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   292
        // so let's return an explicit None
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   293
        Ok(py.None())
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   294
    }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   295
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   296
    def bases(&self) -> PyResult<HashSet<PyRevision>> {
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   297
        let leaked = self.inner(py).borrow();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   298
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   299
        let inner: &CoreMissing<PySharedIndex> =
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   300
            &*unsafe { leaked.try_borrow(py)? };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   301
        Ok(inner.get_bases()
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   302
           .iter()
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   303
           .map(|r| PyRevision(r.0))
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   304
           .collect()
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   305
        )
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   306
    }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   307
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   308
    def basesheads(&self) -> PyResult<HashSet<PyRevision>> {
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   309
        let leaked = self.inner(py).borrow();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   310
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   311
        let inner: &CoreMissing<PySharedIndex> =
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   312
            &*unsafe { leaked.try_borrow(py)? };
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   313
        Ok(
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   314
            inner
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   315
                .bases_heads()
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   316
                .map_err(|e| GraphError::pynew(py, e))?
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   317
                .into_iter()
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   318
                .map(|r| PyRevision(r.0))
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   319
                .collect()
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   320
        )
41246
619ee4039bd4 rust: MissingAncestors.basesheads()
Georges Racinet <georges.racinet@octobus.net>
parents: 41243
diff changeset
   321
    }
619ee4039bd4 rust: MissingAncestors.basesheads()
Georges Racinet <georges.racinet@octobus.net>
parents: 41243
diff changeset
   322
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   323
    def removeancestorsfrom(&self, revs: PyObject) -> PyResult<PyObject> {
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   324
        let mut revs_pyset: HashSet<Revision> = {
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   325
            // this is very lame: we convert to a Rust set, update it in place
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   326
            // and then convert back to Python, only to have Python remove the
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   327
            // excess (thankfully, Python is happy with a list or even an
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   328
            // iterator)
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   329
            // Leads to improve this:
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   330
            //  - have the CoreMissing instead do something emit revisions to
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   331
            //    discard
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   332
            //  - define a trait for sets of revisions in the core and
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   333
            //    implement it for a Python set rewrapped with the GIL marker
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   334
            let leaked = py_rust_index_to_graph(py,
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   335
                                               self.index(py).clone_ref(py))?;
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   336
            // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   337
            let index = &*unsafe { leaked.try_borrow(py)? };
51272
c4cbb515b006 rust-clippy: apply some more trivial fixes
Raphaël Gomès <rgomes@octobus.net>
parents: 51255
diff changeset
   338
            rev_pyiter_collect(py, &revs, index)?
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   339
        };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   340
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   341
        let mut leaked = self.inner(py).borrow_mut();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   342
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   343
        let inner: &mut CoreMissing<PySharedIndex> =
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   344
            &mut *unsafe { leaked.try_borrow_mut(py)? };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   345
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   346
        inner.remove_ancestors_from(&mut revs_pyset)
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   347
            .map_err(|e| GraphError::pynew(py, e))?;
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   348
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   349
        // convert as Python list
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   350
        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
   351
            revs_pyset.len());
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   352
        for rev in revs_pyset {
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   353
            remaining_pyint_vec.push(
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   354
                PyRevision(rev.0).to_py_object(py).into_object()
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   355
            );
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   356
        }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   357
        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
   358
        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
   359
    }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   360
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   361
    def missingancestors(&self, revs: PyObject) -> PyResult<PyList> {
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   362
        let revs_vec: Vec<Revision> = {
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   363
            let leaked = py_rust_index_to_graph(py,
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   364
                                               self.index(py).clone_ref(py))?;
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   365
            // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   366
            let index = &*unsafe { leaked.try_borrow(py)? };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   367
            rev_pyiter_collect(py, &revs, index)?
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   368
        };
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   369
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   370
        let mut leaked = self.inner(py).borrow_mut();
51255
24d3298189d7 rust-index: document safety invariants being upheld for every `unsafe` block
Raphaël Gomès <rgomes@octobus.net>
parents: 51240
diff changeset
   371
        // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked`
51240
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   372
        let inner: &mut CoreMissing<PySharedIndex> =
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   373
            &mut *unsafe { leaked.try_borrow_mut(py)? };
59d81768ad6d rust-index: using `hg::index::Index` in MissingAncestors
Georges Racinet on incendie.racinet.fr <georges@racinet.fr>
parents: 51239
diff changeset
   374
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   375
        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
   376
            Ok(missing) => missing,
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   377
            Err(e) => {
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   378
                return Err(GraphError::pynew(py, e));
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   379
            }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   380
        };
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   381
        // convert as Python list
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   382
        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
   383
            missing_vec.len());
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   384
        for rev in missing_vec {
50979
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   385
            missing_pyint_vec.push(
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   386
                PyRevision(rev.0).to_py_object(py).into_object()
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 48519
diff changeset
   387
            );
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   388
        }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   389
        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
   390
    }
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   391
});
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   392
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   393
/// Create the module, with __package__ given from parent
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   394
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
   395
    let dotted_name = &format!("{}.ancestor", package);
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   396
    let m = PyModule::new(py, dotted_name)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   397
    m.add(py, "__package__", package)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   398
    m.add(
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   399
        py,
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   400
        "__doc__",
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   401
        "Generic DAG ancestor algorithms - Rust implementation",
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   402
    )?;
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
   403
    m.add_class::<AncestorsIterator>(py)?;
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
   404
    m.add_class::<LazyAncestors>(py)?;
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
   405
    m.add_class::<MissingAncestors>(py)?;
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   406
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   407
    let sys = PyModule::import(py, "sys")?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   408
    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
   409
    sys_modules.set_item(py, dotted_name, &m)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   410
    // 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
   411
    // 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
   412
    // Rust PyObject is dropped.
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   413
    Ok(m)
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   414
}