rust/hg-cpython/src/ancestors.rs
changeset 41243 5257e6299d4c
parent 41240 ff333620a4cc
child 41246 619ee4039bd4
equal deleted inserted replaced
41242:47881d2a9d99 41243:5257e6299d4c
     9 //! `hg-core` crate. From Python, this will be seen as `rustext.ancestor`
     9 //! `hg-core` crate. From Python, this will be seen as `rustext.ancestor`
    10 //! and can be used as replacement for the the pure `ancestor` Python module.
    10 //! and can be used as replacement for the the pure `ancestor` Python module.
    11 //!
    11 //!
    12 //! # Classes visible from Python:
    12 //! # Classes visible from Python:
    13 //! - [`LazyAncestors`] is the Rust implementation of
    13 //! - [`LazyAncestors`] is the Rust implementation of
    14 //!   `mercurial.ancestor.lazyancestors`.
    14 //!   `mercurial.ancestor.lazyancestors`. The only difference is that it is
    15 //!   The only difference is that it is instantiated with a C `parsers.index`
    15 //!   instantiated with a C `parsers.index` instance instead of a parents
    16 //!   instance instead of a parents function.
    16 //!   function.
    17 //!
    17 //!
    18 //! - [`MissingAncestors`] is the Rust implementation of
    18 //! - [`MissingAncestors`] is the Rust implementation of
    19 //!   `mercurial.ancestor.incrementalmissingancestors`.
    19 //!   `mercurial.ancestor.incrementalmissingancestors`.
    20 //!
    20 //!
    21 //!   API differences:
    21 //!   API differences:
    25 //!      a set-valued attribute. We could return a Python set easily if our
    25 //!      a set-valued attribute. We could return a Python set easily if our
    26 //!      [PySet PR](https://github.com/dgrunwald/rust-cpython/pull/165)
    26 //!      [PySet PR](https://github.com/dgrunwald/rust-cpython/pull/165)
    27 //!      is accepted.
    27 //!      is accepted.
    28 //!
    28 //!
    29 //! - [`AncestorsIterator`] is the Rust counterpart of the
    29 //! - [`AncestorsIterator`] is the Rust counterpart of the
    30 //!   `ancestor._lazyancestorsiter` Python generator.
    30 //!   `ancestor._lazyancestorsiter` Python generator. From Python, instances of
    31 //!   From Python, instances of this should be mainly obtained by calling
    31 //!   this should be mainly obtained by calling `iter()` on a [`LazyAncestors`]
    32 //!   `iter()` on a [`LazyAncestors`] instance.
    32 //!   instance.
    33 //!
    33 //!
    34 //! [`LazyAncestors`]: struct.LazyAncestors.html
    34 //! [`LazyAncestors`]: struct.LazyAncestors.html
    35 //! [`MissingAncestors`]: struct.MissingAncestors.html
    35 //! [`MissingAncestors`]: struct.MissingAncestors.html
    36 //! [`AncestorsIterator`]: struct.AncestorsIterator.html
    36 //! [`AncestorsIterator`]: struct.AncestorsIterator.html
    37 use crate::conversion::rev_pyiter_collect;
    37 use crate::conversion::rev_pyiter_collect;
    38 use cindex::Index;
    38 use cindex::Index;
    39 use cpython::{
    39 use cpython::{
    40     ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject,
    40     ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject, PyResult,
    41     PyResult, PyTuple, Python, PythonObject, ToPyObject,
    41     PyTuple, Python, PythonObject, ToPyObject,
    42 };
    42 };
    43 use exceptions::GraphError;
    43 use exceptions::GraphError;
    44 use hg::Revision;
    44 use hg::Revision;
    45 use hg::{
    45 use hg::{
    46     AncestorsIterator as CoreIterator, LazyAncestors as CoreLazy,
    46     AncestorsIterator as CoreIterator, LazyAncestors as CoreLazy,
    88     pub fn from_inner(py: Python, ait: CoreIterator<Index>) -> PyResult<Self> {
    88     pub fn from_inner(py: Python, ait: CoreIterator<Index>) -> PyResult<Self> {
    89         Self::create_instance(py, RefCell::new(Box::new(ait)))
    89         Self::create_instance(py, RefCell::new(Box::new(ait)))
    90     }
    90     }
    91 }
    91 }
    92 
    92 
       
    93 /// Copy and convert an `HashSet<Revision>` in a Python set
       
    94 ///
       
    95 /// This will probably turn useless once `PySet` support lands in
       
    96 /// `rust-cpython`.
       
    97 ///
       
    98 /// This builds a Python tuple, then calls Python's "set()" on it
       
    99 fn py_set(py: Python, set: &HashSet<Revision>) -> PyResult<PyObject> {
       
   100     let as_vec: Vec<PyObject> = set
       
   101         .iter()
       
   102         .map(|rev| rev.to_py_object(py).into_object())
       
   103         .collect();
       
   104     let as_pytuple = PyTuple::new(py, as_vec.as_slice());
       
   105 
       
   106     let locals = PyDict::new(py);
       
   107     locals.set_item(py, "obj", as_pytuple.to_py_object(py))?;
       
   108     py.eval("set(obj)", None, Some(&locals))
       
   109 }
       
   110 
    93 py_class!(pub class LazyAncestors |py| {
   111 py_class!(pub class LazyAncestors |py| {
    94     data inner: RefCell<Box<CoreLazy<Index>>>;
   112     data inner: RefCell<Box<CoreLazy<Index>>>;
    95 
   113 
    96     def __contains__(&self, rev: Revision) -> PyResult<bool> {
   114     def __contains__(&self, rev: Revision) -> PyResult<bool> {
    97         self.inner(py)
   115         self.inner(py)
   142         //   the trait `cpython::ToPyObject` is not implemented for `()`
   160         //   the trait `cpython::ToPyObject` is not implemented for `()`
   143         // so let's return an explicit None
   161         // so let's return an explicit None
   144         Ok(py.None())
   162         Ok(py.None())
   145     }
   163     }
   146 
   164 
   147     def bases(&self) -> PyResult<PyTuple> {
   165     def bases(&self) -> PyResult<PyObject> {
   148         let inner = self.inner(py).borrow();
   166         py_set(py, self.inner(py).borrow().get_bases())
   149         let bases_set = inner.get_bases();
       
   150         // convert as Python tuple TODO how to return a proper Python set?
       
   151         let mut bases_vec: Vec<PyObject> = Vec::with_capacity(
       
   152             bases_set.len());
       
   153         for rev in bases_set {
       
   154             bases_vec.push(rev.to_py_object(py).into_object());
       
   155         }
       
   156         Ok(PyTuple::new(py, bases_vec.as_slice()))
       
   157     }
   167     }
   158 
   168 
   159     def removeancestorsfrom(&self, revs: PyObject) -> PyResult<PyObject> {
   169     def removeancestorsfrom(&self, revs: PyObject) -> PyResult<PyObject> {
   160         let mut inner = self.inner(py).borrow_mut();
   170         let mut inner = self.inner(py).borrow_mut();
   161         // this is very lame: we convert to a Rust set, update it in place
   171         // this is very lame: we convert to a Rust set, update it in place