code: def _annotate_groups(self):
          
          g = {}
          for x in self.metadata:
              g[x.id] = x
  
          idx = 0
          for x in self.metadata:
              if not hasattr(x, 'group'):
                  x.group = idx
                  idx += 1
              neighbors = set()
              for e in self.edges:
                  if e.src == x.id:
                      neighbors.add(e.dst)
                  if e.dst == x.id:
                      neighbors.add(e.src)
              for nb in neighbors:
                  g[nb].group = min(x.group, getattr(g[nb], 'group', idx))
  
          # Assign the edges to the respective groups. Both "ends" of the edge
          # should share the same group so just use the first object's group.
          for e in self.edges:
              e.group = g[e.src].group
  
          self._max_group = idx
docs: Annotate the objects belonging to separate (non-connected) graphs with
          individual indices.