docs: def validate(self):
          """
          Asserts that every declared :term:`specification` can actually be
          realized, meaning that all of its :term:`dependencies <dependency>` are
          present and there are no self-dependencies or :term:`dependency cycles
          <dependency cycle>`. If such a problem is found, a proper exception
          (deriving from :py:class:`GraphValidationError`) is raised.
  
          :raises:
              :py:exc:`MissingDependencyError`,
              :py:exc:`SelfDependencyError`,
              :py:exc:`DependencyCycleError`
          """
          # This method uses Tarjan's strongly connected components algorithm
          # with added self-dependency check to find dependency cyclces.
  
          # Index is just an integer, it's wrapped in a list as a workaround for
          # Python 2's lack of `nonlocal` keyword, so the nested
          # `strongconnect()` may modify it.
          index = [0]
  
          indices = {}
          lowlinks = {}
          stack = []
  
          def strongconnect(specification):
              # Set the depth index for the node to the smallest unused index.
              indices[specification] = index[0]
              lowlinks[specification] = index[0]
              index[0] += 1
              stack.append(specification)
              provider = self.providers[specification]
              dependencies = six.itervalues(provider.dependencies)
              for dependency in dependencies:
                  if isinstance(dependency, Factory):
                      dependency = dependency.specification
                  if dependency not in self.providers:
                      raise MissingDependencyError(specification, dependency)
                  if dependency == specification:
                      raise SelfDependencyError(specification)
                  if dependency not in indices:
                      # Dependency has not yet been visited; recurse on it.
                      strongconnect(dependency)
                      lowlinks[specification] = min(
                          lowlinks[specification],
                          lowlinks[dependency]
                      )
                  elif dependency in stack:
                      # Dependency is in stack and hence in the current strongly
                      # connected component.
                      lowlinks[specification] = min(
                          lowlinks[specification],
                          indices[dependency]
                      )
              if lowlinks[specification] == indices[specification]:
                  component = []
                  while True:
                      component.append(stack.pop())
                      if component[-1] == specification:
                          break
                  if len(component) > 1:
                      raise DependencyCycleError(reversed(component))
  
          for specification, provider in six.iteritems(self.providers):
              if specification not in indices:
                  strongconnect(specification)