nodes: 0, module; 1, function_definition; 2, function_name:_topo_sort; 3, parameters; 4, block; 5, identifier:self; 6, default_parameter; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, expression_statement; 11, comment:# select the operation that will be performed; 12, if_statement; 13, for_statement; 14, while_statement; 15, if_statement; 16, return_statement; 17, identifier:forward; 18, True; 19, comment:"""
          Topological sort.
  
          Returns a list of nodes where the successors (based on outgoing and
          incoming edges selected by the forward parameter) of any given node
          appear in the sequence after that node.
          """; 20, assignment; 21, assignment; 22, assignment; 23, identifier:forward; 24, block; 25, else_clause; 26, identifier:node; 27, call; 28, block; 29, identifier:queue; 30, block; 31, comparison_operator:len(topo_list) == len(self.node_list()); 32, block; 33, else_clause; 34, tuple; 35, identifier:topo_list; 36, list; 37, identifier:queue; 38, call; 39, identifier:indeg; 40, dictionary; 41, expression_statement; 42, expression_statement; 43, expression_statement; 44, block; 45, attribute; 46, argument_list; 47, expression_statement; 48, if_statement; 49, expression_statement; 50, expression_statement; 51, for_statement; 52, call; 53, call; 54, expression_statement; 55, comment:# the graph has cycles, invalid topological sort; 56, block; 57, identifier:valid; 58, identifier:topo_list; 59, identifier:deque; 60, argument_list; 61, assignment; 62, assignment; 63, assignment; 64, expression_statement; 65, expression_statement; 66, expression_statement; 67, identifier:self; 68, identifier:node_list; 69, assignment; 70, identifier:degree; 71, block; 72, else_clause; 73, assignment; 74, call; 75, identifier:edge; 76, call; 77, block; 78, identifier:len; 79, argument_list; 80, identifier:len; 81, argument_list; 82, assignment; 83, expression_statement; 84, identifier:get_edges; 85, attribute; 86, identifier:get_degree; 87, attribute; 88, identifier:get_next; 89, attribute; 90, assignment; 91, assignment; 92, assignment; 93, identifier:degree; 94, call; 95, expression_statement; 96, block; 97, identifier:curr_node; 98, call; 99, attribute; 100, argument_list; 101, identifier:get_edges; 102, argument_list; 103, expression_statement; 104, if_statement; 105, identifier:topo_list; 106, call; 107, identifier:valid; 108, True; 109, assignment; 110, identifier:self; 111, identifier:out_edges; 112, identifier:self; 113, identifier:inc_degree; 114, identifier:self; 115, identifier:tail; 116, identifier:get_edges; 117, attribute; 118, identifier:get_degree; 119, attribute; 120, identifier:get_next; 121, attribute; 122, identifier:get_degree; 123, argument_list; 124, assignment; 125, expression_statement; 126, attribute; 127, argument_list; 128, identifier:topo_list; 129, identifier:append; 130, identifier:curr_node; 131, identifier:curr_node; 132, assignment; 133, comparison_operator:tail_id in indeg; 134, block; 135, attribute; 136, argument_list; 137, identifier:valid; 138, False; 139, identifier:self; 140, identifier:inc_edges; 141, identifier:self; 142, identifier:out_degree; 143, identifier:self; 144, identifier:head; 145, identifier:node; 146, subscript; 147, identifier:degree; 148, call; 149, identifier:queue; 150, identifier:popleft; 151, identifier:tail_id; 152, call; 153, identifier:tail_id; 154, identifier:indeg; 155, expression_statement; 156, if_statement; 157, identifier:self; 158, identifier:node_list; 159, identifier:indeg; 160, identifier:node; 161, attribute; 162, argument_list; 163, identifier:get_next; 164, argument_list; 165, augmented_assignment; 166, comparison_operator:indeg[tail_id] == 0; 167, block; 168, identifier:queue; 169, identifier:append; 170, identifier:node; 171, identifier:edge; 172, subscript; 173, integer:1; 174, subscript; 175, integer:0; 176, expression_statement; 177, identifier:indeg; 178, identifier:tail_id; 179, identifier:indeg; 180, identifier:tail_id; 181, call; 182, attribute; 183, argument_list; 184, identifier:queue; 185, identifier:append; 186, identifier:tail_id
code: def _topo_sort(self, forward=True):
          """
          Topological sort.
  
          Returns a list of nodes where the successors (based on outgoing and
          incoming edges selected by the forward parameter) of any given node
          appear in the sequence after that node.
          """
          topo_list = []
          queue = deque()
          indeg = {}
  
          # select the operation that will be performed
          if forward:
              get_edges = self.out_edges
              get_degree = self.inc_degree
              get_next = self.tail
          else:
              get_edges = self.inc_edges
              get_degree = self.out_degree
              get_next = self.head
  
          for node in self.node_list():
              degree = get_degree(node)
              if degree:
                  indeg[node] = degree
              else:
                  queue.append(node)
  
          while queue:
              curr_node = queue.popleft()
              topo_list.append(curr_node)
              for edge in get_edges(curr_node):
                  tail_id = get_next(edge)
                  if tail_id in indeg:
                      indeg[tail_id] -= 1
                      if indeg[tail_id] == 0:
                          queue.append(tail_id)
  
          if len(topo_list) == len(self.node_list()):
              valid = True
          else:
              # the graph has cycles, invalid topological sort
              valid = False
  
          return (valid, topo_list)