text: import collections
  
  
  class DrawGraphMixin:
  
      DRAW_POPULATION_ANIMATION = False
      DRAW_POPULATION_ANIMATION_PATH = ''
      DRAW_POPULATION_ANIMATION_FILENO_PADDING = 6
      SHOW_OBJ_IDS_OF_WORDS = {}
  
      def draw_graph(self, file_path, starting_word=None, agraph_kwargs=None, prog='dot'):
          """
          Draws the graph of autocomplete words.
  
          parameters:
  
          - file_path: the full path to the file to save the graph into.
          Graphviz library will determine the format of the file based on the extension you choose.
          - starting_word: what word to start from. All descendants of the this word will be in the graph.
          If left as None, the graph will start from the rootn node.
          - agraph_kwargs: kwargs that will be pased to PyGraphViz Agraph creator. You can control how the graph
          will be rendered using these kwargs.
          """
          try:
              import pygraphviz as pgv
          except ImportError:
              print('You need to install pygraphviz in order to draw graphs')
  
          agraph_kwargs = agraph_kwargs if agraph_kwargs else {}
          graph = pgv.AGraph(strict=False, directed=True, **agraph_kwargs)
  
          edges = set()
          que = collections.deque()
          if starting_word:
              matched_prefix_of_last_word, rest_of_word, new_node, matched_words = self._prefix_autofill(word=starting_word)
              try:
                  matched_word = matched_words[-1]
              except IndexError:
                  new_node = self._dwg
                  matched_word = 'root'
          else:
              new_node = self._dwg
              matched_word = 'root'
          que.append((matched_word, new_node, ''))
          node_alternative_names = {}
          while que:
              parent_name, node, edge_name = que.popleft()
              node_id = id(node)
              if node_id not in node_alternative_names:
                  node_alternative_names[node_id] = f'.{len(node_alternative_names)}'
              if node.word:
                  node_name = node.word
                  if node_name in self.SHOW_OBJ_IDS_OF_WORDS:
                      node_name = f'{node_name} {id(node)}'
                  else:
                      try:
                          node_name = self.words[node_name].display
                      except (KeyError, AttributeError):
                          pass
                  graph.add_node(node_name, fontcolor='blue', fontname='Arial', shape='rectangle')
              else:
                  node_name = node_alternative_names[node_id]
                  graph.add_node(node_name, color='grey', shape='point')
              edge_name = "' '" if edge_name == ' ' else edge_name
              edge = (parent_name, node_name)
              if edge not in edges:
                  edges.add(edge)
                  graph.add_edge(*edge, color='blue', label=edge_name)
                  for edge_name, child in node.children.items():
                      que.append((node_name, child, edge_name))
          graph.draw(file_path, prog=prog)
  
      def insert_word_callback(self, word):
          """
          Once word is inserted, this call back is run.
          """
          if self.DRAW_POPULATION_ANIMATION:
              if not hasattr(self, '_graph_fileno'):
                  self._graph_fileno = 0
                  self._graph_filepath = self.DRAW_POPULATION_ANIMATION_PATH.replace('.', r'{}.')
  
              fileno = str(self._graph_fileno).zfill(self.DRAW_POPULATION_ANIMATION_FILENO_PADDING)
              file_path = self._graph_filepath.format(fileno)
              self.draw_graph(file_path=file_path)
              self._graph_fileno += 1
  