Skip to content

Commit d9e7e74

Browse files
committed
wip: mirror_crud_to_nxcg
1 parent 2406459 commit d9e7e74

File tree

6 files changed

+238
-114
lines changed

6 files changed

+238
-114
lines changed

nx_arangodb/classes/dict/adj.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1815,7 +1815,7 @@ def propagate_edge_directed_symmetric(
18151815
set_adj_inner_dict_mirror(src_node_id)
18161816
set_adj_inner_dict_mirror(dst_node_id)
18171817

1818-
edge_attr_or_key_dict = set_edge_func( # type: ignore[operator]
1818+
edge_attr_or_key_dict = set_edge_func(
18191819
src_node_id, dst_node_id, edge_or_edges
18201820
)
18211821

nx_arangodb/classes/digraph.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from .dict.adj import AdjListOuterDict
1111
from .enum import TraversalDirection
12-
from .function import get_node_id
12+
from .function import get_node_id, mirror_to_nxcg
1313

1414
networkx_api = nxadb.utils.decorators.networkx_class(nx.DiGraph) # type: ignore
1515

@@ -161,6 +161,7 @@ def __init__(
161161
symmetrize_edges: bool = False,
162162
use_arango_views: bool = False,
163163
overwrite_graph: bool = False,
164+
mirror_crud_to_nxcg: bool = False,
164165
*args: Any,
165166
**kwargs: Any,
166167
):
@@ -179,16 +180,23 @@ def __init__(
179180
symmetrize_edges,
180181
use_arango_views,
181182
overwrite_graph,
183+
mirror_crud_to_nxcg,
182184
*args,
183185
**kwargs,
184186
)
185187

186188
if self.graph_exists_in_db:
187189
self.clear_edges = self.clear_edges_override
190+
self.reverse = self.reverse_override
191+
188192
self.add_node = self.add_node_override
189193
self.add_nodes_from = self.add_nodes_from_override
190194
self.remove_node = self.remove_node_override
191-
self.reverse = self.reverse_override
195+
self.remove_nodes_from = self.remove_nodes_from_override
196+
self.add_edge = self.add_edge_override
197+
self.add_edges_from = self.add_edges_from_override
198+
self.remove_edge = self.remove_edge_override
199+
self.remove_edges_from = self.remove_edges_from_override
192200

193201
assert isinstance(self._succ, AdjListOuterDict)
194202
assert isinstance(self._pred, AdjListOuterDict)
@@ -234,6 +242,7 @@ def clear_edges_override(self):
234242

235243
super().clear_edges()
236244

245+
@mirror_to_nxcg
237246
def add_node_override(self, node_for_adding, **attr):
238247
if node_for_adding is None:
239248
raise ValueError("None cannot be a node")
@@ -269,6 +278,7 @@ def add_node_override(self, node_for_adding, **attr):
269278

270279
nx._clear_cache(self)
271280

281+
@mirror_to_nxcg
272282
def add_nodes_from_override(self, nodes_for_adding, **attr):
273283
for n in nodes_for_adding:
274284
try:
@@ -312,6 +322,7 @@ def add_nodes_from_override(self, nodes_for_adding, **attr):
312322

313323
nx._clear_cache(self)
314324

325+
@mirror_to_nxcg
315326
def remove_node_override(self, n):
316327
if isinstance(n, (str, int)):
317328
n = get_node_id(str(n), self.default_node_type)
@@ -361,3 +372,23 @@ def remove_node_override(self, n):
361372
del self._succ[u][n] # remove all edges n-u in digraph
362373
del self._pred[n] # remove node from pred
363374
nx._clear_cache(self)
375+
376+
@mirror_to_nxcg
377+
def remove_nodes_from_override(self, nodes):
378+
nx.DiGraph.remove_nodes_from(self, nodes)
379+
380+
@mirror_to_nxcg
381+
def add_edge_override(self, u, v, **attr):
382+
nx.DiGraph.add_edge(self, u, v, **attr)
383+
384+
@mirror_to_nxcg
385+
def add_edges_from_override(self, ebunch_to_add, **attr):
386+
nx.DiGraph.add_edges_from(self, ebunch_to_add, **attr)
387+
388+
@mirror_to_nxcg
389+
def remove_edge_override(self, u, v):
390+
nx.DiGraph.remove_edge(self, u, v)
391+
392+
@mirror_to_nxcg
393+
def remove_edges_from_override(self, ebunch):
394+
nx.DiGraph.remove_edges_from(self, ebunch)

nx_arangodb/classes/function.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from __future__ import annotations
88

9+
from functools import wraps
910
from typing import Any, Callable, Generator, Tuple
1011

1112
import networkx as nx
@@ -932,3 +933,14 @@ def upsert_collection_edges(
932933
)
933934

934935
return results
936+
937+
938+
def mirror_to_nxcg(func):
939+
@wraps(func)
940+
def wrapper(self, *args, **kwargs):
941+
result = func(self, *args, **kwargs)
942+
if self.mirror_to_nxcg and self.nxcg_graph is not None:
943+
getattr(self.nxcg_graph, func.__name__)(*args, **kwargs)
944+
return result
945+
946+
return wrapper

nx_arangodb/classes/graph.py

Lines changed: 122 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
node_attr_dict_factory,
3030
node_dict_factory,
3131
)
32-
from .function import get_node_id
32+
from .function import get_node_id, mirror_to_nxcg
3333
from .reportviews import ArangoEdgeView, ArangoNodeView
3434

3535
networkx_api = nxadb.utils.decorators.networkx_class(nx.Graph) # type: ignore
@@ -195,12 +195,14 @@ def __init__(
195195
symmetrize_edges: bool = False,
196196
use_arango_views: bool = False,
197197
overwrite_graph: bool = False,
198+
mirror_crud_to_nxcg: bool = False,
198199
*args: Any,
199200
**kwargs: Any,
200201
):
201202
self.__db = None
202203
self.__use_arango_views = use_arango_views
203204
self.__graph_exists_in_db = False
205+
self.__mirror_crud_to_nxcg = mirror_crud_to_nxcg
204206

205207
self.__set_db(db)
206208
if all([self.__db, name]):
@@ -261,11 +263,19 @@ def __init__(
261263
self.subgraph = self.subgraph_override
262264
self.clear = self.clear_override
263265
self.clear_edges = self.clear_edges_override
264-
self.add_node = self.add_node_override
265-
self.add_nodes_from = self.add_nodes_from_override
266266
self.number_of_edges = self.number_of_edges_override
267267
self.nbunch_iter = self.nbunch_iter_override
268268

269+
self.add_node = self.add_node_override
270+
self.add_nodes_from = self.add_nodes_from_override
271+
self.remove_node = self.remove_node_override
272+
self.remove_nodes_from = self.remove_nodes_from_override
273+
self.add_edge = self.add_edge_override
274+
self.add_edges_from = self.add_edges_from_override
275+
self.remove_edge = self.remove_edge_override
276+
self.remove_edges_from = self.remove_edges_from_override
277+
self.update = self.update_override
278+
269279
# If incoming_graph_data wasn't loaded by the NetworkX Adapter,
270280
# then we can rely on the CRUD operations of the modified dictionaries
271281
# to load the data into the graph. However, if the graph is directed
@@ -541,6 +551,10 @@ def is_smart(self) -> bool:
541551
def smart_field(self) -> str | None:
542552
return self.__smart_field
543553

554+
@property
555+
def mirror_crud_to_nxcg(self) -> bool:
556+
return self.__mirror_crud_to_nxcg
557+
544558
###########
545559
# Setters #
546560
###########
@@ -691,81 +705,6 @@ def clear_edges_override(self):
691705
nbr_dict.clear()
692706
nx._clear_cache(self)
693707

694-
def add_node_override(self, node_for_adding, **attr):
695-
if node_for_adding is None:
696-
raise ValueError("None cannot be a node")
697-
698-
if node_for_adding not in self._node:
699-
self._adj[node_for_adding] = self.adjlist_inner_dict_factory()
700-
701-
######################
702-
# NOTE: monkey patch #
703-
######################
704-
705-
# Old:
706-
# attr_dict = self._node[node_for_adding] = self.node_attr_dict_factory()
707-
# attr_dict.update(attr)
708-
709-
# New:
710-
node_attr_dict = self.node_attr_dict_factory()
711-
node_attr_dict.data = attr
712-
self._node[node_for_adding] = node_attr_dict
713-
714-
# Reason:
715-
# We can optimize the process of adding a node by creating avoiding
716-
# the creation of a new dictionary and updating it with the attributes.
717-
# Instead, we can create a new node_attr_dict object and set the attributes
718-
# directly. This only makes 1 network call to the database instead of 2.
719-
720-
###########################
721-
722-
else:
723-
self._node[node_for_adding].update(attr)
724-
725-
nx._clear_cache(self)
726-
727-
def add_nodes_from_override(self, nodes_for_adding, **attr):
728-
for n in nodes_for_adding:
729-
try:
730-
newnode = n not in self._node
731-
newdict = attr
732-
except TypeError:
733-
n, ndict = n
734-
newnode = n not in self._node
735-
newdict = attr.copy()
736-
newdict.update(ndict)
737-
if newnode:
738-
if n is None:
739-
raise ValueError("None cannot be a node")
740-
self._adj[n] = self.adjlist_inner_dict_factory()
741-
742-
######################
743-
# NOTE: monkey patch #
744-
######################
745-
746-
# Old:
747-
# self._node[n] = self.node_attr_dict_factory()
748-
#
749-
# self._node[n].update(newdict)
750-
751-
# New:
752-
node_attr_dict = self.node_attr_dict_factory()
753-
node_attr_dict.data = newdict
754-
self._node[n] = node_attr_dict
755-
756-
else:
757-
self._node[n].update(newdict)
758-
759-
# Reason:
760-
# We can optimize the process of adding a node by creating avoiding
761-
# the creation of a new dictionary and updating it with the attributes.
762-
# Instead, we create a new node_attr_dict object and set the attributes
763-
# directly. This only makes 1 network call to the database instead of 2.
764-
765-
###########################
766-
767-
nx._clear_cache(self)
768-
769708
def number_of_edges_override(self, u=None, v=None):
770709
if u is not None:
771710
return super().number_of_edges(u, v)
@@ -847,3 +786,108 @@ def bunch_iter(nlist, adj):
847786

848787
bunch = bunch_iter(nbunch, self._adj)
849788
return bunch
789+
790+
@mirror_to_nxcg
791+
def add_node_override(self, node_for_adding, **attr):
792+
if node_for_adding is None:
793+
raise ValueError("None cannot be a node")
794+
795+
if node_for_adding not in self._node:
796+
self._adj[node_for_adding] = self.adjlist_inner_dict_factory()
797+
798+
######################
799+
# NOTE: monkey patch #
800+
######################
801+
802+
# Old:
803+
# attr_dict = self._node[node_for_adding] = self.node_attr_dict_factory()
804+
# attr_dict.update(attr)
805+
806+
# New:
807+
node_attr_dict = self.node_attr_dict_factory()
808+
node_attr_dict.data = attr
809+
self._node[node_for_adding] = node_attr_dict
810+
811+
# Reason:
812+
# We can optimize the process of adding a node by creating avoiding
813+
# the creation of a new dictionary and updating it with the attributes.
814+
# Instead, we can create a new node_attr_dict object and set the attributes
815+
# directly. This only makes 1 network call to the database instead of 2.
816+
817+
###########################
818+
819+
else:
820+
self._node[node_for_adding].update(attr)
821+
822+
nx._clear_cache(self)
823+
824+
@mirror_to_nxcg
825+
def add_nodes_from_override(self, nodes_for_adding, **attr):
826+
for n in nodes_for_adding:
827+
try:
828+
newnode = n not in self._node
829+
newdict = attr
830+
except TypeError:
831+
n, ndict = n
832+
newnode = n not in self._node
833+
newdict = attr.copy()
834+
newdict.update(ndict)
835+
if newnode:
836+
if n is None:
837+
raise ValueError("None cannot be a node")
838+
self._adj[n] = self.adjlist_inner_dict_factory()
839+
840+
######################
841+
# NOTE: monkey patch #
842+
######################
843+
844+
# Old:
845+
# self._node[n] = self.node_attr_dict_factory()
846+
#
847+
# self._node[n].update(newdict)
848+
849+
# New:
850+
node_attr_dict = self.node_attr_dict_factory()
851+
node_attr_dict.data = newdict
852+
self._node[n] = node_attr_dict
853+
854+
else:
855+
self._node[n].update(newdict)
856+
857+
# Reason:
858+
# We can optimize the process of adding a node by creating avoiding
859+
# the creation of a new dictionary and updating it with the attributes.
860+
# Instead, we create a new node_attr_dict object and set the attributes
861+
# directly. This only makes 1 network call to the database instead of 2.
862+
863+
###########################
864+
865+
nx._clear_cache(self)
866+
867+
@mirror_to_nxcg
868+
def remove_node_override(self, n):
869+
super().remove_node(n)
870+
871+
@mirror_to_nxcg
872+
def remove_nodes_from_override(self, nodes):
873+
super().remove_nodes_from(nodes)
874+
875+
@mirror_to_nxcg
876+
def add_edge_override(self, u, v, **attr):
877+
super().add_edge(u, v, **attr)
878+
879+
@mirror_to_nxcg
880+
def add_edges_from_override(self, ebunch_to_add, **attr):
881+
super().add_edges_from(ebunch_to_add, **attr)
882+
883+
@mirror_to_nxcg
884+
def remove_edge_override(self, u, v):
885+
super().remove_edge(u, v)
886+
887+
@mirror_to_nxcg
888+
def remove_edges_from_override(self, ebunch):
889+
super().remove_edges_from(ebunch)
890+
891+
@mirror_to_nxcg
892+
def update_override(self, *args, **kwargs):
893+
super().update(*args, **kwargs)

0 commit comments

Comments
 (0)