import networkx as nx class Graph(object): NODE_TYPE_KEY = "nodeType" not_allowed_node = type('NotAllowedNode', (Exception, ), {}) def __init__(self, user=None): self.user = user self.nodes = {} self.nx_graph = nx.DiGraph() self.params = {} @classmethod def parse_graph(cls, json_graph, nodes_cls, common_params={}): graph = cls(user=json_graph['owner']) for node in json_graph['nodes']: node = nodes_cls.parse(node, graph) graph.add_node(node) for link in json_graph['links']: source_node = graph.get_node(link['source']) target_node = graph.get_node(link["target"]) graph.add_edge(source_node, target_node) for key in common_params: graph.set_common_param(key, common_params[key]) return graph def run(self, **kwargs): # Lineal execution. Study graph theory for more complexity. ############## for node in self.nx_graph: self.nodes[node].super_run() ########################################################################## def add_node(self, node): self.nx_graph.add_node(node.id) self.nodes[node.id] = node def change_node(self, node_id, value): self.nodes[node_id] = value def add_edge(self, source_node, target_node): self.nx_graph.add_edge(source_node.id, target_node.id) def get_node(self, node_id): return self.nodes[node_id] def set_param(self, key, value): self.params[key] = value def set_common_param(self, key, value): self.set_param(key, value) for node in self.nodes: self.nodes[node].set_param(key, value) def get_leaves(self): leaves = [x for x in self.nx_graph.nodes() if self.nx_graph.out_degree(x) == 0 and self.nx_graph.in_degree(x) == 1] if len(self.nx_graph.nodes()) == 1: leaves = self.nx_graph.nodes() return leaves def get_roots(self): roots = [x for x in self.nx_graph.nodes() if self.nx_graph.in_degree(x) == 0] return roots