def apply_config_file(
        command_function: Union[click.Command, click.Group],
        cli_params: Dict[str, Any],
        ctx,
        config_file_option_name='config_file',
):
    """ Applies all options set in the config file to `cli_params` """
    paramname_to_param = {param.name: param for param in command_function.params}
    path_params = {
        param.name
        for param in command_function.params
        if isinstance(param.type, (click.Path, click.File))
    }

    config_file_path = Path(cli_params[config_file_option_name])
    config_file_values = dict()
    try:
        with config_file_path.open() as config_file:
            config_file_values = load(config_file)
    except OSError as ex:
        # Silently ignore if 'file not found' and the config file path is the default
        config_file_param = paramname_to_param[config_file_option_name]
        config_file_default_path = Path(
            config_file_param.type.expand_default(config_file_param.get_default(ctx), cli_params),
        )
        default_config_missing = (
            ex.errno == errno.ENOENT and
            config_file_path.resolve() == config_file_default_path.resolve()
        )
        if default_config_missing:
            cli_params['config_file'] = None
        else:
            click.secho(f"Error opening config file: {ex}", fg='red')
            sys.exit(1)
    except TomlError as ex:
        click.secho(f'Error loading config file: {ex}', fg='red')
        sys.exit(1)

    for config_name, config_value in config_file_values.items():
        config_name_int = config_name.replace('-', '_')

        if config_name_int not in paramname_to_param:
            click.secho(
                f"Unknown setting '{config_name}' found in config file - ignoring.",
                fg='yellow',
            )
            continue

        if config_name_int in path_params:
            # Allow users to use `~` in paths in the config file
            config_value = os.path.expanduser(config_value)

        if config_name_int == LOG_CONFIG_OPTION_NAME:
            # Uppercase log level names
            config_value = {k: v.upper() for k, v in config_value.items()}
        else:
            # Pipe config file values through cli converter to ensure correct types
            # We exclude `log-config` because it already is a dict when loading from toml
            try:
                config_value = paramname_to_param[config_name_int].type.convert(
                    config_value,
                    paramname_to_param[config_name_int],
                    ctx,
                )
            except click.BadParameter as ex:
                click.secho(f"Invalid config file setting '{config_name}': {ex}", fg='red')
                sys.exit(1)

        # Use the config file value if the value from the command line is the default
        if cli_params[config_name_int] == paramname_to_param[config_name_int].get_default(ctx):
            cli_params[config_name_int] = config_value
Applies all options set in the config file to `cli_params`