docs: def get_dependencies(factory):
      """
      This function inspects a function to find its arguments marked for
      injection, either with :py:func:`inject()` decorator,
      :py:class:`UnrealizedInjection` class of through Python 3 function
      annotations.  If `factory` is a class, then its constructor is inspected.
  
      Returned dictionary is a mapping of::
  
          [argument index/name] -> [specification]
  
      For example, dependencies for function::
  
          @inject(ILogger, db=(IDBConnection, 'archive'))
          def foo(log, db=None):
              pass
  
      would be::
  
          {
              0: ILogger,
              'db': (IDBConnection, 'archive'),
          }
  
      `Old-style classes`_ (from before Python 2.2) are not supported.
  
      .. _Old-style classes:
          https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes
      """
      if inspect.isclass(factory):
          # If factory is a class we want to check constructor depdendencies.
          if six.PY3:
              init_check = inspect.isfunction
          else:
              init_check = inspect.ismethod
          dependencies = {}
          if hasattr(factory, '__init__') and init_check(factory.__init__):
              dependencies.update(get_dependencies(factory.__init__))
          if hasattr(factory, '__new__') and inspect.isfunction(factory.__new__):
              dependencies.update(get_dependencies(factory.__new__))
          return dependencies
      elif inspect.isfunction(factory) or inspect.ismethod(factory):
          function = factory
      else:
          raise TypeError("`factory` must be a class or a function.")
  
      if hasattr(function, '__injection__'):
          # Function has precollected dependencies (happens when using `inject()`
          # decorator. Nothing to do here.
          return function.__injection__
  
      dependencies = {}
  
      def process_dependency_tuples(tuples):
          for key, value in tuples:
              if isinstance(value, UnrealizedInjection):
                  dependencies[key] = value.specification
      if six.PY3:
          argument_specification = inspect.getfullargspec(function)
          if argument_specification.kwonlydefaults:
              process_dependency_tuples(
                  six.iteritems(argument_specification.kwonlydefaults)
              )
          if argument_specification.annotations:
              dependencies.update(argument_specification.annotations)
      else:
          argument_specification = inspect.getargspec(function)
      if argument_specification.defaults:
          process_dependency_tuples(zip(
              reversed(argument_specification.args),
              reversed(argument_specification.defaults)
          ))
      return dependencies