Let modules detect additional configuration values.

    `config` is the initial dictionary with command-line and
    file-derived values, but nothing else, filled in.  This calls
    :meth:`yakonfig.configurable.Configurable.discover_config` on
    every configuration module.  It is expect that this method will
    modify the passed-in configuration dictionaries in place.

    :param dict config: configuration tree to update
    :param modules: modules or Configurable instances to use
    :type modules: iterable of :class:`~yakonfig.configurable.Configurable`
    :return: `config`

def do_config_discovery(config, modules):
    '''Let modules detect additional configuration values.

    `config` is the initial dictionary with command-line and
    file-derived values, but nothing else, filled in.  This calls
    :meth:`yakonfig.configurable.Configurable.discover_config` on
    every configuration module.  It is expect that this method will
    modify the passed-in configuration dictionaries in place.

    :param dict config: configuration tree to update
    :param modules: modules or Configurable instances to use
    :type modules: iterable of :class:`~yakonfig.configurable.Configurable`
    :return: `config`

    '''
    def work_in(config, module, name):
        f = getattr(module, 'discover_config', None)
        if f:
            f(config, name)
    return _walk_config(config, modules, work_in)