##// END OF EJS Templates
typing: make `bundlerepository` subclass `localrepository` while type checking...
typing: make `bundlerepository` subclass `localrepository` while type checking Currently, `mercurial/bundlerepo.py` is excluded from pytype, mostly because it complains that various `ui` and `vfs` fields in `localrepository` are missing. (`bundlerepository` dynamically subclasses `localrepository` when it is instantiated, so it works at runtime.) This makes that class hierarchy known to pytype. Having a protocol for `Repository` is probably the right thing to do, but that will be a lot of work and this still reflects the class at runtime. Subclassing also has the benefit of making sure any method overrides have a matching signature, so maybe this is a situation where we do both of these things. (I'm not sure how clear the diagnostics are if a class *almost* implements a protocol, but is missing a method argument or similar.) The subclassing is not done outside of type checking runs to avoid any side effects on already complex code.

File last commit:

r52114:5a7d5fd6 default
r52763:9d4ad05b default
Show More
conversion.rs
57 lines | 1.8 KiB | application/rls-services+xml | RustLexer
// conversion.rs
//
// Copyright 2019 Georges Racinet <georges.racinet@octobus.net>
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
//! Bindings for the hg::ancestors module provided by the
//! `hg-core` crate. From Python, this will be seen as `rustext.ancestor`
use cpython::{ObjectProtocol, PyErr, PyObject, PyResult, Python};
use hg::{Revision, RevlogIndex, UncheckedRevision};
use crate::{exceptions::GraphError, PyRevision};
/// Utility function to convert a Python iterable into various collections
///
/// We need this in particular to feed to various methods of inner objects
/// with `impl IntoIterator<Item=Revision>` arguments, because
/// a `PyErr` can arise at each step of iteration, whereas these methods
/// expect iterables over `Revision`, not over some `Result<Revision, PyErr>`
pub fn rev_pyiter_collect<C, I>(
py: Python,
revs: &PyObject,
index: &I,
) -> PyResult<C>
where
C: FromIterator<Revision>,
I: RevlogIndex,
{
rev_pyiter_collect_or_else(py, revs, index, |r| {
PyErr::new::<GraphError, _>(py, ("InvalidRevision", r.0))
})
}
/// Same as [`rev_pyiter_collect`], giving control on returned errors
pub fn rev_pyiter_collect_or_else<C, I>(
py: Python,
revs: &PyObject,
index: &I,
invalid_rev_error: impl FnOnce(PyRevision) -> PyErr + Copy,
) -> PyResult<C>
where
C: FromIterator<Revision>,
I: RevlogIndex,
{
revs.iter(py)?
.map(|r| {
r.and_then(|o| match o.extract::<PyRevision>(py) {
Ok(r) => index
.check_revision(UncheckedRevision(r.0))
.ok_or_else(|| invalid_rev_error(r)),
Err(e) => Err(e),
})
})
.collect()
}