Skip to content

Commit 661e9ad

Browse files
author
Frank Dekervel
committed
python: expose LinkMLValue.equals(); tests: add python_equals coverage
1 parent 5c31a7b commit 661e9ad

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/python/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,11 @@ impl Clone for PyLinkMLValue {
478478

479479
#[pymethods]
480480
impl PyLinkMLValue {
481+
/// Semantic equality per LinkML Instances spec.
482+
/// Compares this value with another `LinkMLValue`.
483+
fn equals(&self, other: &PyLinkMLValue) -> bool {
484+
self.value.equals(&other.value)
485+
}
481486
#[getter]
482487
fn slot_name(&self) -> Option<String> {
483488
match &self.value {

src/python/tests/python_equals.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use linkml_runtime_python::runtime_module;
2+
use pyo3::prelude::*;
3+
use pyo3::types::PyDict;
4+
use std::path::PathBuf;
5+
6+
fn data_path(name: &str) -> PathBuf {
7+
let base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
8+
let candidates = [
9+
base.join("../runtime/tests/data").join(name),
10+
base.join("../schemaview/tests/data").join(name),
11+
base.join("tests/data").join(name),
12+
];
13+
for c in candidates {
14+
if c.exists() {
15+
return c;
16+
}
17+
}
18+
panic!("test data not found: {}", name);
19+
}
20+
21+
#[test]
22+
fn python_equals_api() {
23+
pyo3::prepare_freethreaded_python();
24+
Python::with_gil(|py| {
25+
let module = PyModule::new(py, "linkml_runtime").unwrap();
26+
runtime_module(&module).unwrap();
27+
let sys = py.import("sys").unwrap();
28+
let modules = sys.getattr("modules").unwrap();
29+
let sys_modules = modules.downcast::<PyDict>().unwrap();
30+
sys_modules.set_item("linkml_runtime", module).unwrap();
31+
32+
let locals = PyDict::new(py);
33+
locals
34+
.set_item(
35+
"schema_path",
36+
data_path("personinfo.yaml").to_str().unwrap(),
37+
)
38+
.unwrap();
39+
40+
pyo3::py_run!(
41+
py,
42+
*locals,
43+
r#"
44+
import linkml_runtime as lr
45+
import json
46+
sv = lr.make_schema_view(schema_path)
47+
cls = sv.get_class_view('Container')
48+
49+
doc1 = {
50+
'objects': [
51+
{
52+
'objecttype': 'personinfo:Person',
53+
'id': 'P:1',
54+
'name': 'Alice',
55+
'current_address': None
56+
}
57+
]
58+
}
59+
doc2 = {
60+
'objects': [
61+
{
62+
'objecttype': 'personinfo:Person',
63+
'id': 'P:1',
64+
'name': 'Alice'
65+
}
66+
]
67+
}
68+
69+
v1 = lr.load_json(json.dumps(doc1), sv, cls)
70+
v2 = lr.load_json(json.dumps(doc2), sv, cls)
71+
assert v1['objects'][0].equals(v2['objects'][0])
72+
"#
73+
);
74+
});
75+
}

0 commit comments

Comments
 (0)