rust-index: variant of assert_py_eq with normalizer expression
authorGeorges Racinet <georges.racinet@octobus.net>
Sat, 30 Sep 2023 16:52:40 +0200
changeset 51214 050098d60c30
parent 51213 62e39bef36ca
child 51215 a7bba7df9189
rust-index: variant of assert_py_eq with normalizer expression The example given in doc-comment is the main use case: some methods may require ordering insensitive comparison. This is about to be used for `reachableroots2`
rust/hg-cpython/src/revlog.rs
--- a/rust/hg-cpython/src/revlog.rs	Thu Aug 03 15:50:14 2023 +0200
+++ b/rust/hg-cpython/src/revlog.rs	Sat Sep 30 16:52:40 2023 +0200
@@ -823,25 +823,49 @@
     }
 }
 
+/// assert two Python objects to be equal from a Python point of view
+///
+/// `method` is a label for the assertion error message, intended to be the
+/// name of the caller.
+/// `normalizer` is a function that takes a Python variable name and returns
+/// an expression that the conparison will actually use.
+/// Foe example: `|v| format!("sorted({})", v)`
+fn assert_py_eq_normalized(
+    py: Python,
+    method: &str,
+    rust: &PyObject,
+    c: &PyObject,
+    normalizer: impl FnOnce(&str) -> String + Copy,
+) -> PyResult<()> {
+    let locals = PyDict::new(py);
+    locals.set_item(py, "rust".into_py_object(py).into_object(), rust)?;
+    locals.set_item(py, "c".into_py_object(py).into_object(), c)?;
+    //    let lhs = format!(normalizer_fmt, "rust");
+    //    let rhs = format!(normalizer_fmt, "c");
+    let is_eq: PyBool = py
+        .eval(
+            &format!("{} == {}", &normalizer("rust"), &normalizer("c")),
+            None,
+            Some(&locals),
+        )?
+        .extract(py)?;
+    assert!(
+        is_eq.is_true(),
+        "{} results differ. Rust: {:?} C: {:?} (before any normalization)",
+        method,
+        rust,
+        c
+    );
+    Ok(())
+}
+
 fn assert_py_eq(
     py: Python,
     method: &str,
     rust: &PyObject,
     c: &PyObject,
 ) -> PyResult<()> {
-    let locals = PyDict::new(py);
-    locals.set_item(py, "rust".into_py_object(py).into_object(), rust)?;
-    locals.set_item(py, "c".into_py_object(py).into_object(), c)?;
-    let is_eq: PyBool =
-        py.eval("rust == c", None, Some(&locals))?.extract(py)?;
-    assert!(
-        is_eq.is_true(),
-        "{} results differ. Rust: {:?} C: {:?}",
-        method,
-        rust,
-        c
-    );
-    Ok(())
+    assert_py_eq_normalized(py, method, rust, c, |v| v.to_owned())
 }
 
 /// Create the module, with __package__ given from parent