Validate the configuration of an object within this.

    This calls :meth:`Configurable.check_config` or equivalent on `sub`.
    A dictionary configuration for `sub` is required in `config`.

    >>> def check_config(config, name):
    ...     for sub in sub_modules:
    ...         check_subconfig(config, name, sub)

    :param dict config: parent configuration
    :param str name: name of the parent configuration block
    :param sub: Configurable-like subobject to check
    :raise yakonfig.ConfigurationError: if there is no
      configuration for `sub`, or it is not a dictionary

def check_subconfig(config, name, sub):
    """Validate the configuration of an object within this.

    This calls :meth:`Configurable.check_config` or equivalent on `sub`.
    A dictionary configuration for `sub` is required in `config`.

    >>> def check_config(config, name):
    ...     for sub in sub_modules:
    ...         check_subconfig(config, name, sub)

    :param dict config: parent configuration
    :param str name: name of the parent configuration block
    :param sub: Configurable-like subobject to check
    :raise yakonfig.ConfigurationError: if there is no
      configuration for `sub`, or it is not a dictionary

    """
    subname = sub.config_name
    subconfig = config.setdefault(subname, {})
    if not isinstance(subconfig, collections.Mapping):
        raise ProgrammerError('configuration for {0} in {1} must be a mapping'
                              .format(subname, name))
    checker = getattr(sub, 'check_config', None)
    if checker is not None:
        checker(subconfig, '{0}.{1}'.format(name, subname))