diff --git a/python/src/graphql.rs b/python/src/graphql.rs index 9fd7b5f66..ac5092145 100644 --- a/python/src/graphql.rs +++ b/python/src/graphql.rs @@ -889,6 +889,39 @@ impl PyRaphtoryClient { ))), } } + + /// Move graph from a path `path` on the server to a `new_path` on the server + /// + /// Arguments: + /// * `path`: the path of the graph to be moved + /// * `new_path`: the new path of the moved graph + /// + /// Returns: + /// Move status as boolean + #[pyo3(signature = (path, new_path))] + fn move_graph(&self, path: String, new_path: String) -> PyResult { + let query = r#" + mutation MoveGraph($path: String!, $newPath: String!) { + moveGraph( + path: $path, + newPath: $newPath, + ) + }"# + .to_owned(); + + let variables = [ + ("path".to_owned(), json!(path)), + ("newPath".to_owned(), json!(new_path)), + ]; + + let data = self.query_with_json_variables(query.clone(), variables.into())?; + match data.get("moveGraph") { + Some(JsonValue::Bool(res)) => Ok((*res).clone()), + _ => Err(PyException::new_err(format!( + "Error while reading server response for query:\n\t{query}\nGot data:\n\t'{data:?}'" + ))), + } + } } fn translate_from_python(py: Python, value: PyObject) -> PyResult { diff --git a/python/tests/test_graphql.py b/python/tests/test_graphql.py index cc0889463..18047df21 100644 --- a/python/tests/test_graphql.py +++ b/python/tests/test_graphql.py @@ -947,6 +947,47 @@ def test_move_graph_succeeds(): server.stop() +def test_move_graph_using_client_api_succeeds(): + g = Graph() + g.add_edge(1, "ben", "hamza") + g.add_edge(2, "haaroon", "hamza") + g.add_edge(3, "ben", "haaroon") + + work_dir = tempfile.mkdtemp() + os.makedirs(os.path.join(work_dir, "shivam"), exist_ok=True) + g.save_to_file(os.path.join(work_dir, "shivam", "g3")) + + server = RaphtoryServer(work_dir).start() + client = RaphtoryClient("http://localhost:1736") + + # Assert if rename graph succeeds and old graph is deleted + res = client.move_graph("shivam/g3", "ben/g4") + assert res + + query = """{graph(path: "shivam/g3") {nodes {list {name}}}}""" + try: + client.query(query) + except Exception as e: + assert "Graph not found shivam/g3" in str(e), f"Unexpected exception message: {e}" + + query = """{graph(path: "ben/g4") { + nodes {list {name}} + properties { + constant { + lastUpdated: get(key: "lastUpdated") { value } + lastOpened: get(key: "lastOpened") { value } + } + } + }}""" + + result = client.query(query) + assert result['graph']['nodes']['list'] == [{'name': 'ben'}, {"name": "hamza"}, {'name': 'haaroon'}] + assert result['graph']['properties']['constant']['lastUpdated']['value'] is not None + assert result['graph']['properties']['constant']['lastOpened']['value'] is not None + + server.stop() + + def test_move_graph_succeeds_at_same_namespace_as_graph(): g = Graph() g.add_edge(1, "ben", "hamza") @@ -1229,6 +1270,7 @@ def test_copy_graph_using_client_api_succeeds(): server.stop() + def test_copy_graph_succeeds_at_same_namespace_as_graph(): g = Graph() g.add_edge(1, "ben", "hamza") diff --git a/raphtory-graphql/src/model/mod.rs b/raphtory-graphql/src/model/mod.rs index a01bcf6df..14fbad021 100644 --- a/raphtory-graphql/src/model/mod.rs +++ b/raphtory-graphql/src/model/mod.rs @@ -157,6 +157,7 @@ impl Mut { graph.update_constant_properties([("lastUpdated", Prop::I64(timestamp * 1000))])?; graph.update_constant_properties([("lastOpened", Prop::I64(timestamp * 1000))])?; + create_dirs_if_not_present(&new_full_path)?; graph.save_to_file(&new_full_path)?; delete_graph(&full_path)?;