Skip to content

GA-157 | Review #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 48 additions & 37 deletions nx_arangodb/classes/dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,22 +167,18 @@ def __init__(
)

result = doc_get_or_insert(self.db, self.COLLECTION_NAME, self.graph_id)
self.data = self.dict_to_graph_attr_dicts(result)

def mutate_dict(self, parent_key: str, obj: Any) -> Any:
if isinstance(obj, dict):
graph_attr_dict = self.graph_attr_dict_factory()
graph_attr_dict.parent_keys = [parent_key]
graph_attr_dict.data = build_graph_attr_dict_data(graph_attr_dict, obj)
graph_attr_dict.graph_id = self.graph_id
return graph_attr_dict
else:
return obj
for k, v in result.items():
self.data[k] = self.__process_graph_dict_value(k, v)

def __process_graph_dict_value(self, key: str, value: Any) -> Any:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

introduced this private method to process any value that would be added to GraphDict. Similar to process_graph_attr_dict_value, but without the concept of parent_keys and root

if not isinstance(value, dict):
return value

def dict_to_graph_attr_dicts(self, d):
for key, value in list(d.items()):
d[key] = self.mutate_dict(key, value)
return d
graph_attr_dict = self.graph_attr_dict_factory()
graph_attr_dict.parent_keys = [key]
graph_attr_dict.data = build_graph_attr_dict_data(graph_attr_dict, value)

return graph_attr_dict

@key_is_string
@logger_debug
Expand All @@ -206,29 +202,22 @@ def __getitem__(self, key: str) -> Any:
if result is None:
raise KeyError(key)

self.data[key] = result
graph_dict_value = self.__process_graph_dict_value(key, result)
self.data[key] = graph_dict_value

return result
return graph_dict_value

@key_is_string
@key_is_not_reserved
@logger_debug
def __setitem__(self, key: str, value: Any) -> None:
"""G.graph['foo'] = 'bar'"""

if type(value) is dict:
graph_attr_dict = self.graph_attr_dict_factory()
graph_attr_dict.parent_keys = [key]
graph_attr_dict.data = build_graph_attr_dict_data(graph_attr_dict, value)
graph_attr_dict.graph_id = self.graph_id

self.data[key] = graph_attr_dict
elif value is None:
if value is None:
self.__delitem__(key)
return
else:
self.data[key] = value

graph_dict_value = self.__process_graph_dict_value(key, value)
self.data[key] = graph_dict_value
self.data["_rev"] = doc_update(self.db, self.graph_id, {key: value})

@key_is_string
Expand All @@ -248,9 +237,10 @@ def update(self, attrs: Any) -> None:
return

graph_attr_dict = self.graph_attr_dict_factory()
graph_attr_dict.data = build_graph_attr_dict_data(graph_attr_dict, attrs)
graph_attr_dict_data = build_graph_attr_dict_data(graph_attr_dict, attrs)
graph_attr_dict.data = graph_attr_dict_data

self.data.update(graph_attr_dict)
self.data.update(graph_attr_dict_data)
self.data["_rev"] = doc_update(self.db, self.graph_id, attrs)

@logger_debug
Expand All @@ -263,6 +253,15 @@ def clear(self) -> None:
class GraphAttrDict(UserDict[str, Any]):
"""The inner-level of the dict of dict structure
representing the attributes of a graph stored in the database.

Only used if the value associated with a GraphDict key is a dict.

:param db: The ArangoDB database.
:type db: StandardDatabase
:param graph: The ArangoDB graph.
:type graph: Graph
:param graph_id: The ArangoDB graph ID.
:type graph_id: str
"""

@logger_debug
Expand Down Expand Up @@ -290,6 +289,7 @@ def __init__(
@key_is_string
@logger_debug
def __contains__(self, key: str) -> bool:
"""'bar' in G.graph['foo']"""
if key in self.data:
return True

Expand All @@ -298,9 +298,10 @@ def __contains__(self, key: str) -> bool:
@key_is_string
@logger_debug
def __getitem__(self, key: str) -> Any:
"""G.graph['foo']['bar']"""

if value := self.data.get(key):
return value
assert self.graph_id
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing any need for graph_id assertions as you were able to make use of the factory method to set graph_id


result = aql_doc_get_key(self.db, self.graph_id, key, self.parent_keys)

Expand All @@ -310,17 +311,20 @@ def __getitem__(self, key: str) -> Any:
graph_attr_dict_value = process_graph_attr_dict_value(self, key, result)
self.data[key] = graph_attr_dict_value

return result
return graph_attr_dict_value
Comment on lines -313 to +314
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returning the graph_attr_dict_value to maintain any remote connection (if result is of type dict)


@key_is_string
@logger_debug
def __setitem__(self, key, value):
# TODO: Add this as well to all the other __setitems__ calls
"""
G.graph['foo'] = 'bar'
G.graph['object'] = {'foo': 'bar'}
G._node['object']['foo'] = 'baz'
"""
if value is None:
self.__delitem__(key)
return

assert self.graph_id
graph_attr_dict_value = process_graph_attr_dict_value(self, key, value)
update_dict = get_update_dict(self.parent_keys, {key: value})
self.data[key] = graph_attr_dict_value
Expand All @@ -330,19 +334,19 @@ def __setitem__(self, key, value):
@key_is_string
@logger_debug
def __delitem__(self, key):
assert self.graph_id
"""del G.graph['foo']['bar']"""
self.data.pop(key, None)
update_dict = get_update_dict(self.parent_keys, {key: None})
root_data = self.root.data if self.root else self.data
root_data["_rev"] = doc_update(self.db, self.graph_id, update_dict)

@logger_debug
def update(self, attrs: Any) -> None:
"""G.graph['foo'].update({'bar': 'baz'})"""
if not attrs:
return

self.data.update(build_graph_attr_dict_data(self, attrs))
assert self.graph_id
updated_dict = get_update_dict(self.parent_keys, attrs)
root_data = self.root.data if self.root else self.data
root_data["_rev"] = doc_update(self.db, self.graph_id, updated_dict)
Expand All @@ -359,7 +363,6 @@ def process_node_attr_dict_value(parent: NodeAttrDict, key: str, value: Any) ->

node_attr_dict = parent.node_attr_dict_factory()
node_attr_dict.root = parent.root or parent
# TODO: Check if node_id can be passes by reference
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turns out this is already the case, my bad:

a = "hello world"
b = a
print(id(a) == id(b))

node_attr_dict.node_id = parent.node_id
node_attr_dict.parent_keys = parent.parent_keys + [key]
node_attr_dict.data = build_node_attr_dict_data(node_attr_dict, value)
Expand Down Expand Up @@ -460,6 +463,10 @@ def __setitem__(self, key: str, value: Any) -> None:
G._node['node/1']['object'] = {'foo': 'bar'}
G._node['node/1']['object']['foo'] = 'baz'
"""
if value is None:
self.__delitem__(key)
return

assert self.node_id
node_attr_dict_value = process_node_attr_dict_value(self, key, value)
update_dict = get_update_dict(self.parent_keys, {key: value})
Expand Down Expand Up @@ -812,6 +819,10 @@ def __getitem__(self, key: str) -> Any:
@logger_debug
def __setitem__(self, key: str, value: Any) -> None:
"""G._adj['node/1']['node/2']['foo'] = 'bar'"""
if value is None:
self.__delitem__(key)
return

assert self.edge_id
edge_attr_dict_value = process_edge_attr_dict_value(self, key, value)
update_dict = get_update_dict(self.parent_keys, {key: value})
Expand Down