Configuration file support for Click command-line applications through a simple decorator-based approach.
npx @tessl/cli install tessl/pypi-click-config-file@0.6.0Configuration file support for Click command-line applications through a simple decorator-based approach. This package enables developers to add configuration file capabilities to their Click applications with a single @configuration_option() decorator without mandatory arguments, supporting sensible defaults and proper resolution order (CLI > Environment > Config file > Default).
pip install click-config-fileimport click_config_fileFor typical usage:
from click_config_file import configuration_option, configobj_providerimport click
import click_config_file
@click.command()
@click.option('--name', default='World', help='Who to greet.')
@click_config_file.configuration_option()
def hello(name):
click.echo('Hello {}!'.format(name))
if __name__ == '__main__':
hello()With a configuration file named config in the application directory:
name="Universe"Running the command will use the configuration file value:
$ hello
Hello Universe!Command line arguments override configuration file values:
$ hello --name Multiverse
Hello Multiverse!The primary decorator that adds configuration file support to Click commands.
def configuration_option(*param_decls, **attrs):
"""
Adds configuration file support to a click application.
This creates an option of type click.Path expecting the path to a
configuration file. When specified, it overwrites the default values
for all other click arguments or options with corresponding values
from the configuration file.
Parameters:
- *param_decls: Parameter declarations (default: ('--config',))
- cmd_name (str, optional): Command name for configuration directory.
Default: ctx.info_name
- config_file_name (str, optional): Name of configuration file.
Default: 'config'
- implicit (bool, optional): Whether to implicitly create configuration
option value. Default: True
- provider (callable, optional): Configuration file parser.
Default: configobj_provider()
- exists (bool, optional): Whether config file must exist. Default: False
- file_okay (bool, optional): Whether files are allowed. Default: True
- dir_okay (bool, optional): Whether directories are allowed. Default: False
- writable (bool, optional): Whether file must be writable. Default: False
- readable (bool, optional): Whether file must be readable. Default: True
- resolve_path (bool, optional): Whether to resolve path. Default: False
- **attrs: All other standard click.option() arguments
Returns:
Decorator function for Click commands
Raises:
click.BadOptionUsage: If configuration file cannot be read or parsed
"""Parser for configobj configuration files with support for sections and unrepr mode.
class configobj_provider:
"""
A parser for configobj configuration files.
Parameters:
- unrepr (bool, optional): Controls whether file parsed using
configobj's unrepr mode. Default: True
- section (str, optional): If set, looks for corresponding section
inside configuration file and returns only values from that section.
Default: None
"""
def __init__(self, unrepr=True, section=None):
"""Initialize the configobj provider."""
def __call__(self, file_path, cmd_name):
"""
Parse and return the configuration parameters.
Parameters:
- file_path (str): Path to the configuration file or file-like object
- cmd_name (str): Name of the click command
Returns:
dict: Dictionary containing the configuration parameters,
or empty dict if specified section doesn't exist
Raises:
configobj.ParseError: If configuration file has syntax errors
py.error.ENOENT: If configuration file doesn't exist
"""You can create custom configuration providers for different file formats:
import json
import click
import click_config_file
def json_provider(file_path, cmd_name):
"""Custom provider for JSON configuration files."""
with open(file_path) as config_data:
return json.load(config_data)
@click.command()
@click.option('--name', default='World')
@click_config_file.configuration_option(provider=json_provider)
def hello(name):
click.echo('Hello {}!'.format(name))For shared configuration files with command-specific sections:
import click
import click_config_file
provider = click_config_file.configobj_provider(section='mycommand')
@click.command()
@click.option('--name', default='World')
@click_config_file.configuration_option(provider=provider)
def hello(name):
click.echo('Hello {}!'.format(name))Configuration file format:
[mycommand]
name = "From Section"
[othercommand]
name = "Other Value"Disable implicit configuration file discovery:
@click.command()
@click.option('--name', default='World')
@click_config_file.configuration_option(implicit=False)
def hello(name):
click.echo('Hello {}!'.format(name))@click.command()
@click.option('--name', default='World')
@click_config_file.configuration_option(
cmd_name='myapp',
config_file_name='settings.conf'
)
def hello(name):
click.echo('Hello {}!'.format(name))The library supports both Click options and arguments from configuration files:
@click.command()
@click.argument('input_file')
@click.option('--output', default='output.txt')
@click_config_file.configuration_option()
def process(input_file, output):
"""Process files with config support for both arguments and options."""
click.echo(f'Processing {input_file} -> {output}')Configuration file:
input_file = "data.txt"
output = "processed.txt"For multi-value arguments:
@click.command()
@click.argument('files', nargs=-1)
@click_config_file.configuration_option()
def process_multiple(files):
for file in files:
click.echo(f'Processing {file}')Configuration file:
files = ["file1.txt", "file2.txt", "file3.txt"]Configuration files can be passed as file handles instead of paths:
@click.command()
@click.argument('data')
@click_config_file.configuration_option(type=click.File())
def process_with_handle(data):
click.echo(f'Data: {data}')The default provider supports ConfigObj format with unrepr mode:
# Simple key-value pairs
name = "World"
count = 42
enabled = True
# Lists
items = ["item1", "item2", "item3"]
# Nested sections
[database]
host = "localhost"
port = 5432Configuration files support Click's multi-value options:
# For options like: @click.option('--item', multiple=True)
item = ["value1", "value2", "value3"]Configuration values are resolved in the following priority order:
This ensures command line arguments always override configuration file settings, maintaining expected CLI behavior.
The library handles configuration file errors gracefully:
py.error.ENOENT when file specified explicitlyconfigobj.ParseError is caught and re-raised as click.BadOptionUsage with descriptive error message# Import required for exception handling
import click
import configobj
# Exceptions that may be raised:
click.BadOptionUsage: # Configuration file parsing or reading errors
configobj.ParseError: # Configuration file syntax errors (wrapped in BadOptionUsage)
py.error.ENOENT: # Missing configuration file (in explicit mode)# Main exports available via __all__
from click_config_file import configuration_option, configobj_provider
class configobj_provider:
"""Configuration file parser for configobj format files."""
def __init__(self, unrepr=True, section=None):
"""
Initialize configobj provider.
Parameters:
- unrepr (bool): Whether to use unrepr mode for evaluation. Default: True
- section (str, optional): Section name to extract from config. Default: None
"""
def __call__(self, file_path, cmd_name):
"""
Parse configuration file and return parameters.
Parameters:
- file_path (str or file-like): Path to config file or file handle
- cmd_name (str): Click command name (for context)
Returns:
dict: Configuration parameters, empty dict if section not found
Raises:
configobj.ParseError: If config file has syntax errors
py.error.ENOENT: If config file doesn't exist
"""
def configuration_option(*param_decls, **attrs):
"""
Decorator that adds configuration file support to Click commands.
Parameters:
- *param_decls: Parameter declarations, default: ('--config',)
- implicit (bool): Whether to create implicit config value. Default: True
- cmd_name (str, optional): Command name for config directory. Default: ctx.info_name
- config_file_name (str): Config file name. Default: 'config'
- provider (callable): Config parser function. Default: configobj_provider()
- **attrs: All click.option() and click.Path() parameters
Returns:
callable: Click decorator function
Raises:
click.BadOptionUsage: If config file cannot be read or parsed
"""