nodes: 0, module; 1, function_definition; 2, function_name:sort_nodes; 3, parameters; 4, block; 5, identifier:self; 6, expression_statement; 7, expression_statement; 8, expression_statement; 9, for_statement; 10, comment:# Now that we have our dependency tree properly built, topologically; 11, comment:# sort the nodes and reorder them.; 12, expression_statement; 13, expression_statement; 14, comment:#Check root nodes all topographically sorted to the beginning; 15, for_statement; 16, comment:"""Topologically sort all of our nodes.
  
          Topologically sorting our nodes makes nodes that are inputs to other
          nodes come first in the list of nodes.  This is important to do before
          programming a sensorgraph into an embedded device whose engine assumes
          a topologically sorted graph.
  
          The sorting is done in place on self.nodes
          """; 17, assignment; 18, assignment; 19, pattern_list; 20, call; 21, block; 22, assignment; 23, assignment; 24, identifier:root; 25, attribute; 26, block; 27, identifier:node_map; 28, dictionary_comprehension; 29, identifier:node_deps; 30, dictionary; 31, identifier:node; 32, identifier:inputs; 33, identifier:_outputs; 34, attribute; 35, argument_list; 36, expression_statement; 37, expression_statement; 38, expression_statement; 39, identifier:node_order; 40, call; 41, attribute; 42, list_comprehension; 43, identifier:self; 44, identifier:roots; 45, if_statement; 46, pair; 47, for_in_clause; 48, identifier:self; 49, identifier:iterate_bfs; 50, assignment; 51, assignment; 52, assignment; 53, identifier:toposort_flatten; 54, argument_list; 55, identifier:self; 56, identifier:nodes; 57, subscript; 58, for_in_clause; 59, comparison_operator:root not in self.nodes[0:len(self.roots)]; 60, block; 61, call; 62, identifier:i; 63, pattern_list; 64, call; 65, identifier:node_index; 66, subscript; 67, identifier:deps; 68, set_comprehension; 69, subscript; 70, identifier:deps; 71, identifier:node_deps; 72, attribute; 73, identifier:x; 74, identifier:x; 75, identifier:node_order; 76, identifier:root; 77, subscript; 78, raise_statement; 79, identifier:id; 80, argument_list; 81, identifier:i; 82, identifier:node; 83, identifier:enumerate; 84, argument_list; 85, identifier:node_map; 86, call; 87, subscript; 88, for_in_clause; 89, identifier:node_deps; 90, identifier:node_index; 91, identifier:self; 92, identifier:nodes; 93, attribute; 94, slice; 95, call; 96, identifier:node; 97, attribute; 98, identifier:id; 99, argument_list; 100, identifier:node_map; 101, call; 102, identifier:x; 103, identifier:inputs; 104, identifier:self; 105, identifier:nodes; 106, integer:0; 107, call; 108, identifier:NodeConnectionError; 109, argument_list; 110, identifier:self; 111, identifier:nodes; 112, identifier:node; 113, identifier:id; 114, argument_list; 115, identifier:len; 116, argument_list; 117, string:"Inputs not sorted in the beginning"; 118, keyword_argument; 119, keyword_argument; 120, identifier:x; 121, attribute; 122, identifier:node; 123, call; 124, identifier:node_position; 125, call; 126, identifier:self; 127, identifier:roots; 128, identifier:str; 129, argument_list; 130, attribute; 131, argument_list; 132, identifier:root; 133, attribute; 134, identifier:index; 135, identifier:root; 136, identifier:self; 137, identifier:nodes
code: def sort_nodes(self):
          """Topologically sort all of our nodes.
  
          Topologically sorting our nodes makes nodes that are inputs to other
          nodes come first in the list of nodes.  This is important to do before
          programming a sensorgraph into an embedded device whose engine assumes
          a topologically sorted graph.
  
          The sorting is done in place on self.nodes
          """
  
          node_map = {id(node): i for i, node in enumerate(self.nodes)}
          node_deps = {}
  
          for node, inputs, _outputs in self.iterate_bfs():
              node_index = node_map[id(node)]
  
              deps = {node_map[id(x)] for x in inputs}
              node_deps[node_index] = deps
  
          # Now that we have our dependency tree properly built, topologically
          # sort the nodes and reorder them.
          node_order = toposort_flatten(node_deps)
          self.nodes = [self.nodes[x] for x in node_order]
  
          #Check root nodes all topographically sorted to the beginning
          for root in self.roots:
              if root not in self.nodes[0:len(self.roots)]:
                  raise NodeConnectionError("Inputs not sorted in the beginning", node=str(root), node_position=self.nodes.index(root))