Skip to content

Commit

Permalink
major improvement on MGraph__Json__Export
Browse files Browse the repository at this point in the history
added use of new OSBot_Utils Json.json__equals__list_and_set  method which helps with comparing dicts that have sets (whose order is not stable)
  • Loading branch information
DinisCruz committed Jan 28, 2025
1 parent 2a2ff1b commit 14b07d9
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 49 deletions.
2 changes: 1 addition & 1 deletion mgraph_ai/providers/json/actions/MGraph__Json__Edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class MGraph__Json__Edit(MGraph__Edit):

def add_property(self, property_name, value=None, node_id=None):
print()
node_property_data = Schema__MGraph__Json__Node__Property__Data(name = property_name )
node_property_data = Schema__MGraph__Json__Node__Property__Data(name = property_name )
node_property = Schema__MGraph__Json__Node__Property (node_data = node_property_data)
new_node = self.add_node(node_property)

Expand Down
70 changes: 56 additions & 14 deletions mgraph_ai/providers/json/actions/MGraph__Json__Export.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,84 @@
from typing import Union, Dict, List, Optional, Any
from mgraph_ai.providers.json.actions.exporters.MGraph__Export__Json__Dot import MGraph__Export__Json__Dot
from mgraph_ai.providers.json.actions.exporters.MGraph__Export__Json__Mermaid import MGraph__Export__Json__Mermaid
from mgraph_ai.providers.json.models.Model__MGraph__Json__Node__Dict import Model__MGraph__Json__Node__Dict
from mgraph_ai.providers.json.models.Model__MGraph__Json__Node__List import Model__MGraph__Json__Node__List
from mgraph_ai.providers.json.models.Model__MGraph__Json__Node__Value import Model__MGraph__Json__Node__Value
from mgraph_ai.providers.json.schemas.Schema__MGraph__Json__Node__Value import Schema__MGraph__Json__Node__Value
from osbot_utils.utils.Files import file_save
from osbot_utils.utils.Json import json_dumps
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Node__Dict import Domain__MGraph__Json__Node__Dict
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Node__List import Domain__MGraph__Json__Node__List
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Node__Value import Domain__MGraph__Json__Node__Value
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Graph import Domain__MGraph__Json__Graph
from mgraph_ai.mgraph.actions.MGraph__Export import MGraph__Export
from mgraph_ai.mgraph.index.MGraph__Index import MGraph__Index
from osbot_utils.helpers.Obj_Id import Obj_Id

class MGraph__Json__Export(MGraph__Export): # JSON export handler
class MGraph__Json__Export(MGraph__Export):
graph: Domain__MGraph__Json__Graph

def to_dict(self) -> Union[Dict, List, Any]: # Export to Python object
def process_value_node(self, node_id: Obj_Id) -> Any:
domain_node = self.graph.node(node_id)
model_node = domain_node.node
if isinstance(model_node, Model__MGraph__Json__Node__Value):
return model_node.value
return None

def process_dict_node(self, node_id: Obj_Id, index: MGraph__Index) -> Dict[str, Any]:
result = {}
for edge_id in index.edges_ids__from__node_id(node_id):
property_id = index.edge_to_nodes()[edge_id][1]
property_node = self.graph.node(property_id)

if property_node:
property_name = property_node.node_data.name
value_edges = index.edges_ids__from__node_id(property_id)
if value_edges:
value_node_id = index.edge_to_nodes()[value_edges[0]][1]
result[property_name] = self.process_node(value_node_id, index)
return result

def process_list_node(self, node_id: Obj_Id, index: MGraph__Index) -> List[Any]:
result = []
for edge_id in index.edges_ids__from__node_id(node_id):
item_id = index.edge_to_nodes()[edge_id][1]
item_value = self.process_node(item_id, index)
result.append(item_value)
return result

def process_node(self, node_id: Obj_Id, index: MGraph__Index) -> Any:
domain_node = self.graph.node(node_id)
model_node = domain_node.node
if not domain_node:
return None

if isinstance(model_node, Model__MGraph__Json__Node__Value): return self.process_value_node(node_id)
elif isinstance(model_node, Model__MGraph__Json__Node__Dict ): return self.process_dict_node (node_id, index)
elif isinstance(model_node, Model__MGraph__Json__Node__List ): return self.process_list_node (node_id, index)
return None

def to_dict(self) -> Union[Dict, List, Any]:
root_content = self.graph.root_content()
if not root_content:
return None

if isinstance(root_content, Domain__MGraph__Json__Node__Dict):
return root_content.properties()
elif isinstance(root_content, Domain__MGraph__Json__Node__List):
return root_content.items()
elif isinstance(root_content, Domain__MGraph__Json__Node__Value):
return root_content.value
index = MGraph__Index.from_graph(self.graph) # todo: replace with index = self.data().index()
return self.process_node(root_content.node_id, index)

def to_string(self, indent: Optional[int] = None) -> str: # Export to JSON string
def to_string(self, indent: Optional[int] = None) -> str:
data = self.to_dict()
return json_dumps(data, indent=indent)

def to_dot(self):
return MGraph__Export__Json__Dot(graph=self.graph)

def to_file(self, file_path: str, indent: Optional[int] = None) -> bool: # Export to JSON file
def to_file(self, file_path: str, indent: Optional[int] = None) -> bool:
file_contents = self.to_string(indent=indent)
if file_contents:
file_save(contents=file_contents, path=file_path)
return True
return False

def to_dot(self):
return MGraph__Export__Json__Dot(graph=self.graph)

def to_mermaid(self) -> MGraph__Export__Json__Mermaid:
return MGraph__Export__Json__Mermaid(graph=self.graph)
return MGraph__Export__Json__Mermaid(graph=self.graph)
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def properties(self) -> Dict[str, Any]:
if value_edge.from_node_id() == property_node.node_id:
value_node = self.graph.node(value_edge.to_node_id())
if value_node.data.node_type == Schema__MGraph__Json__Node__Value: # todo: there is an interest case here, what happens if there is more than one Schema__MGraph__Json__Node__Value per Schema__MGraph__Json__Node__Property
result[property_name] = value_node.data.node_data.value # todo: solve issue of value not being recognized here
result[property_name] = value_node.data.node_data.value # todo: solve issue of value not being recognized here
break
elif value_node.data.node_type == Schema__MGraph__Json__Node__List:
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Node__List import Domain__MGraph__Json__Node__List
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
from unittest import TestCase
from osbot_utils.utils.Json import json_file_load
from osbot_utils.utils.Json import json_file_load, json__equals__list_and_set
from osbot_utils.context_managers.print_duration import print_duration
from osbot_utils.utils.Http import current_host_offline
from mgraph_ai.providers.json.MGraph__Json import MGraph__Json
Expand Down Expand Up @@ -69,7 +69,7 @@ def test_trace(self):
dot_code = mgraph_json.export().to_dot().to_string()
#pprint(round_trip)
#print(dot_code)
assert target_json == round_trip
assert json__equals__list_and_set(target_json, round_trip)



Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from unittest import TestCase
from osbot_utils.utils.Json import json_loads
from osbot_utils.utils.Json import json_loads, json__equals__list_and_set
from mgraph_ai.providers.json.MGraph__Json import MGraph__Json
from mgraph_ai.providers.json.actions.exporters.MGraph__Export__Json__Dot import MGraph__Export__Json__Dot
from mgraph_ai.providers.json.actions.exporters.MGraph__Json__Export__Base import Export__Json__Node_Type, \
Expand Down Expand Up @@ -175,7 +175,7 @@ def test_nested_structure(self): # Test
}
}
self.mgraph.load().from_data(nested_data)
assert json_loads(self.mgraph.export().to_string()) == nested_data # BUG
assert json__equals__list_and_set(json_loads(self.mgraph.export().to_string()), nested_data) # BUG
dot = self.exporter.to_string()
assert dot == """\
digraph {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from unittest import TestCase
from osbot_utils.utils.Json import json_loads
from osbot_utils.utils.Json import json_loads, json__equals__list_and_set
from mgraph_ai.providers.json.MGraph__Json import MGraph__Json
from mgraph_ai.providers.json.actions.exporters.MGraph__Export__Json__Mermaid import MGraph__Export__Json__Mermaid
from mgraph_ai.providers.json.actions.exporters.MGraph__Json__Export__Base import Export__Json__Node_Type, Export__Json__Relation_Type
Expand Down Expand Up @@ -144,7 +144,7 @@ def test_nested_structure(self):
}
}
self.mgraph.load().from_data(nested_data)
assert json_loads(self.mgraph.export().to_string()) == nested_data
assert json__equals__list_and_set(json_loads(self.mgraph.export().to_string()), nested_data)
mermaid = self.exporter.to_string()
assert mermaid == """\
flowchart LR
Expand Down
32 changes: 28 additions & 4 deletions tests/unit/providers/json/actions/test_MGraph__Json__Edit.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from unittest import TestCase

from osbot_utils.utils.Dev import pprint

from osbot_utils.helpers.Obj_Id import Obj_Id
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Node import Domain__MGraph__Json__Node
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Node__Dict import Domain__MGraph__Json__Node__Dict
Expand Down Expand Up @@ -31,8 +34,6 @@ def test_add_root_property_node(self):

def test_add_property(self):
assert self.mgraph_json.export().to_dict() is None
with self.mgraph_json.data() as _:
root_property_id = _.root_property_id()
with self.mgraph_json.edit() as _:

root_property_node = _.add_root_property_node()
Expand All @@ -50,5 +51,28 @@ def test_add_property(self):

assert self.mgraph_json.export().to_dict() == {'1234': 'xyz', 'abc': '12345'} # confirm values set correctly

#self.mgraph_json.screenshot().save().dot__just_ids()
#self.mgraph_json.screenshot().save().dot()
def test_add_property_to_property(self):
with self.mgraph_json.edit() as _:
root_property_node = _.add_root_property_node()
new_property_1 = _.add_property('parent', node_id=root_property_node.node_id)
new_property_2 = _.add_property('child' , node_id=new_property_1.node_id )

assert type(new_property_1) == Domain__MGraph__Json__Node
assert type(new_property_2) == Domain__MGraph__Json__Node
# print()
# print('root_property_node', root_property_node.node_id)
# print('new_property_1 ', new_property_1.node_id )
# print('new_property_2 ', new_property_2.node_id )
# pprint(new_property_1.node.json())
pprint(new_property_2.node.json())

# with self.mgraph_json.index() as _:
# _.print()


self.mgraph_json.screenshot().save().dot__just_ids()
#self.mgraph_json.screenshot().save().dot()

#assert self.mgraph_json.export().to_dict() == {'parent': None}

pprint(self.mgraph_json.export().to_dict())
20 changes: 10 additions & 10 deletions tests/unit/providers/json/actions/test_MGraph__Json__Export.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from unittest import TestCase
from osbot_utils.utils.Files import file_exists, file_delete
from osbot_utils.utils.Json import json_loads
from osbot_utils.utils.Json import json_loads, json__equals__list_and_set
from mgraph_ai.providers.json.MGraph__Json import MGraph__Json


Expand All @@ -23,12 +23,12 @@ def test_export_formats(self):
str_export_indented = self.mgraph.export().to_string(indent=2) # Test string export with indent

assert type(dict_export) is dict
assert dict_export == self.test_data
assert type(str_export) is str
assert json_loads(str_export) == self.test_data
assert type(str_export_indented) is str
assert json_loads(str_export_indented) == self.test_data
assert len(str_export_indented) > len(str_export)
assert json__equals__list_and_set(dict_export , self.test_data) is True
assert type(str_export) is str
assert json__equals__list_and_set(json_loads(str_export) ,self.test_data) is True
assert type(str_export_indented) is str
assert json__equals__list_and_set(json_loads(str_export_indented), self.test_data) is True
assert len(str_export_indented) > len(str_export)

def test_file_operations(self): # Test file import/export
file_path = "test.json"
Expand All @@ -38,9 +38,9 @@ def test_file_operations(self):

new_graph = MGraph__Json() # Test import from file
imported = new_graph.load().from_file(str(file_path))
assert imported.root_content() is not None
assert new_graph.export().to_dict() == self.test_data
assert file_delete(file_path) is True
assert imported.root_content() is not None
assert json__equals__list_and_set(new_graph.export().to_dict(), self.test_data) is True
assert file_delete(file_path) is True

def test_error_handling(self): # Test error conditions
assert self.mgraph.load().from_string("{invalid json}") is None
Expand Down
22 changes: 11 additions & 11 deletions tests/unit/providers/json/actions/test_MGraph__Json__Load.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from unittest import TestCase
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Node__List import Domain__MGraph__Json__Node__List
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Node__Value import Domain__MGraph__Json__Node__Value
from osbot_utils.utils.Json import json_loads
from osbot_utils.utils.Json import json_loads, json__equals__list_and_set
from mgraph_ai.providers.json.MGraph__Json import MGraph__Json
from mgraph_ai.providers.json.domain.Domain__MGraph__Json__Node__Dict import Domain__MGraph__Json__Node__Dict

Expand Down Expand Up @@ -35,18 +35,18 @@ def test_import_from_string(self):
def test_export_to_dict(self): # Test exporting to dict
self.mgraph.load().from_data(self.test_data)
exported = self.mgraph.export().to_dict()
assert exported == self.test_data
assert exported["string" ] == "value"
assert exported["number" ] == 42
assert exported["boolean"] is True
assert exported["null" ] is None
assert exported["array" ] == [1, 2, 3]
assert exported["object" ] == {"key": "value"}
assert json__equals__list_and_set(exported, self.test_data) is True
assert exported["string" ] == "value"
assert exported["number" ] == 42
assert exported["boolean"] is True
assert exported["null" ] is None
assert json__equals__list_and_set(exported["array" ], [1, 2, 3]) is True
assert exported["object" ] == {"key": "value"}

def test_export_to_string(self): # Test exporting to JSON string
self.mgraph.load().from_data(self.test_data)
exported = self.mgraph.export().to_string()
assert json_loads(exported) == self.test_data
assert json__equals__list_and_set(json_loads(exported), self.test_data) is True

def test_primitive_values(self): # Test handling primitive values
values = ["string", 42, 3.14, True, False, None ]
Expand All @@ -67,15 +67,15 @@ def test_array_handling(self):
assert items[1] == "two"
assert items[2] == {"three": 3}
assert items[3] == [4, 5]
assert self.mgraph.export().to_dict() == array_data
assert json__equals__list_and_set(self.mgraph.export().to_dict(), array_data)

def test_nested_structures(self): # Test nested JSON structures
nested_data = {"level1": {"level2": {"level3": {"array": [1, 2, {"key": "value"}],
"value": "nested" }}}}
graph = self.mgraph.load().from_data(nested_data)
root_content = graph.root_content()
assert isinstance(root_content, Domain__MGraph__Json__Node__Dict)
assert self.mgraph.export().to_dict() == nested_data
assert json__equals__list_and_set(self.mgraph.export().to_dict(), nested_data) is True

def test_empty_structures(self): # Test empty JSON structures
empty_data = { "empty_object" : {} ,
Expand Down
6 changes: 4 additions & 2 deletions tests/unit/query/actions/test_MGraph__Query__Export__View.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from mgraph_ai.providers.json.models.Model__MGraph__Json__Graph import Model__MGraph__Json__Graph
from mgraph_ai.providers.json.schemas.Schema__MGraph__Json__Graph import Schema__MGraph__Json__Graph
from mgraph_ai.query.models.Model__MGraph__Query__View import Model__MGraph__Query__View
from osbot_utils.utils.Json import json__equals__list_and_set


class test_MGraph__Query__Export__View(TestCase):
Expand Down Expand Up @@ -71,8 +72,9 @@ def test__create_dot__no_filter(self):
property_2 = _.add_property('1234', node_id=root_property_id, value='xyz')
_.add_value ('12345', node_id=property_1.node_id)

assert self.mgraph_json.export().to_dict() == {'1234': 'xyz', 'abc': '12345' ,
** self.test_data}
expected_dict = {'1234': 'xyz', 'abc': '12345' ,
** self.test_data}
assert json__equals__list_and_set(self.mgraph_json.export().to_dict(),expected_dict)

#edge_1 = _.new_edge(from_node_id=root_property_id, to_node_id=property_node.node_id)

Expand Down

0 comments on commit 14b07d9

Please sign in to comment.