##// END OF EJS Templates
rust-pyo3: conversion helpers for Revision objects...
Georges Racinet -
r53306:a642c0a3 default
parent child Browse files
Show More
@@ -0,0 +1,78
1 use pyo3::prelude::*;
2
3 use hg::revlog::RevlogIndex;
4 use hg::{BaseRevision, Revision, UncheckedRevision};
5
6 use crate::exceptions::GraphError;
7
8 /// Revision as exposed to/from the Python layer.
9 ///
10 /// We need this indirection because of the orphan rule, meaning we can't
11 /// implement a foreign trait (like [`cpython::ToPyObject`])
12 /// for a foreign type (like [`hg::UncheckedRevision`]).
13 ///
14 /// This also acts as a deterrent against blindly trusting Python to send
15 /// us valid revision numbers.
16 #[derive(
17 Debug,
18 Copy,
19 Clone,
20 PartialEq,
21 Eq,
22 PartialOrd,
23 Ord,
24 Hash,
25 derive_more::From,
26 IntoPyObject,
27 FromPyObject,
28 )]
29 pub struct PyRevision(pub BaseRevision);
30
31 impl From<Revision> for PyRevision {
32 fn from(r: Revision) -> Self {
33 PyRevision(r.0)
34 }
35 }
36
37 /// Utility function to convert a Python iterable into various collections
38 ///
39 /// We need this in particular
40 /// - because of the checked upgrade from [`PyRevision`] to [`Revision`].
41 /// - to feed to various methods of inner objects with `impl
42 /// IntoIterator<Item=Revision>` arguments, because a `PyErr` can arise at
43 /// each step of iteration, whereas these methods expect iterables over
44 /// `Revision`, not over some `Result<Revision, PyErr>`
45 pub fn rev_pyiter_collect<C, I>(
46 revs: &Bound<'_, PyAny>,
47 index: &I,
48 ) -> PyResult<C>
49 where
50 C: FromIterator<Revision>,
51 I: RevlogIndex,
52 {
53 rev_pyiter_collect_or_else(revs, index, |r| {
54 PyErr::new::<GraphError, _>(("InvalidRevision", r.0))
55 })
56 }
57
58 /// Same as [`rev_pyiter_collect`], giving control on returned errors
59 pub fn rev_pyiter_collect_or_else<C, I>(
60 revs: &Bound<'_, PyAny>,
61 index: &I,
62 invalid_rev_error: impl FnOnce(PyRevision) -> PyErr + Copy,
63 ) -> PyResult<C>
64 where
65 C: FromIterator<Revision>,
66 I: RevlogIndex,
67 {
68 revs.try_iter()?
69 .map(|r| {
70 r.and_then(|o| match o.extract::<PyRevision>() {
71 Ok(r) => index
72 .check_revision(UncheckedRevision(r.0))
73 .ok_or_else(|| invalid_rev_error(r)),
74 Err(e) => Err(e),
75 })
76 })
77 .collect()
78 }
@@ -712,6 +712,7 dependencies = [
712 name = "hg-pyo3"
712 name = "hg-pyo3"
713 version = "0.1.0"
713 version = "0.1.0"
714 dependencies = [
714 dependencies = [
715 "derive_more",
715 "env_logger 0.9.3",
716 "env_logger 0.9.3",
716 "hg-core",
717 "hg-core",
717 "log",
718 "log",
@@ -12,4 +12,5 pyo3 = { version = "0.23.1", features =
12 hg-core = { path = "../hg-core"}
12 hg-core = { path = "../hg-core"}
13 stable_deref_trait = "1.2.0"
13 stable_deref_trait = "1.2.0"
14 log = "0.4.17"
14 log = "0.4.17"
15 env_logger = "0.9.3" No newline at end of file
15 env_logger = "0.9.3"
16 derive_more = "0.99.17"
@@ -2,6 +2,7 use pyo3::prelude::*;
2
2
3 mod dagops;
3 mod dagops;
4 mod exceptions;
4 mod exceptions;
5 mod revision;
5 mod util;
6 mod util;
6
7
7 #[pymodule]
8 #[pymodule]
General Comments 0
You need to be logged in to leave comments. Login now