changeset 52870:c60f69556924

rust-pyo3: new module for conversions of HgPath and friends Same as `PyRevision`, the `PyHgPathRef` new-type wrapper is not a Python type, but it implements `IntoPyObject`, which will spare us tedious uses of `PyBytes::new`. The `paths_py_list` function is the the analog of `revs_py_list` for paths. There was one similar utility in `hg-cpython`, within the `dirstate::status` module. We feel it should be in a more global location, and have a name consistent with utilities for revisions. The `paths_pyiter_collect` function is similarly the analog of `revs_pyiter_collect`.
author Georges Racinet <georges.racinet@cloudcrane.io>
date Thu, 06 Feb 2025 11:18:28 +0100
parents e7b825893e1b
children 9f083ff3c96c
files rust/hg-pyo3/src/lib.rs rust/hg-pyo3/src/path.rs
diffstat 2 files changed, 68 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/rust/hg-pyo3/src/lib.rs	Wed Jan 29 14:05:26 2025 +0100
+++ b/rust/hg-pyo3/src/lib.rs	Thu Feb 06 11:18:28 2025 +0100
@@ -6,6 +6,7 @@
 mod discovery;
 mod exceptions;
 mod node;
+mod path;
 mod revision;
 mod revlog;
 mod store;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/hg-pyo3/src/path.rs	Thu Feb 06 11:18:28 2025 +0100
@@ -0,0 +1,67 @@
+// path.rs
+//
+// Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
+//           2025 Georges Racinet <georges.racinet@cloudcrane.io>
+//
+// This software may be used and distributed according to the terms of the
+// GNU General Public License version 2 or any later version.
+//! Utilities about `HgPath` and related objects provided by the `hg-core`
+//! package.
+
+use pyo3::prelude::*;
+use pyo3::types::{PyBytes, PyList};
+
+use std::convert::Infallible;
+
+use hg::utils::hg_path::{HgPath, HgPathBuf};
+
+#[allow(dead_code)]
+#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, derive_more::From)]
+pub struct PyHgPathRef<'a>(pub &'a HgPath);
+
+impl<'py> IntoPyObject<'py> for PyHgPathRef<'_> {
+    type Target = PyBytes;
+    type Output = Bound<'py, Self::Target>;
+    type Error = Infallible;
+
+    fn into_pyobject(
+        self,
+        py: Python<'py>,
+    ) -> Result<Self::Output, Self::Error> {
+        Ok(PyBytes::new(py, self.0.as_bytes()))
+    }
+}
+
+#[allow(dead_code)]
+pub fn paths_py_list<I, U>(
+    py: Python<'_>,
+    paths: impl IntoIterator<Item = I, IntoIter = U>,
+) -> PyResult<Py<PyList>>
+where
+    I: AsRef<HgPath>,
+    U: ExactSizeIterator<Item = I>,
+{
+    Ok(PyList::new(
+        py,
+        paths
+            .into_iter()
+            .map(|p| PyBytes::new(py, p.as_ref().as_bytes())),
+    )?
+    .unbind())
+}
+
+#[allow(dead_code)]
+pub fn paths_pyiter_collect<C>(paths: &Bound<'_, PyAny>) -> PyResult<C>
+where
+    C: FromIterator<HgPathBuf>,
+{
+    paths
+        .try_iter()?
+        .map(|p| {
+            let path = p?;
+            Ok(HgPathBuf::from_bytes(
+                path.downcast::<PyBytes>()?.as_bytes(),
+            ))
+        })
+        .collect()
+}