Configuration files¶

The structure of the configuration file is automatically derived from the parameters of the CLI and their types. There is no need to manually produce a configuration data structure to mirror the CLI.

Standalone option¶

The @config_option decorator provided by Click Extra can be used as-is with vanilla Click:

from click import group, option, echo
from click_extra import config_option

@group(context_settings={"show_default": True})
@option("--dummy-flag/--no-flag")
@option("--my-list", multiple=True)
@config_option
def my_cli(dummy_flag, my_list):
    echo(f"dummy_flag    is {dummy_flag!r}")
    echo(f"my_list       is {my_list!r}")

@my_cli.command
@option("--int-param", type=int, default=10)
def subcommand(int_param):
    echo(f"int_parameter is {int_param!r}")

The code above is saved into a file named my_cli.py.

It produces the following help screen:

$ my-cli --help
Usage: my-cli [OPTIONS] COMMAND [ARGS]...

Options:
  --dummy-flag / --no-flag  [default: no-flag]
  --my-list TEXT
  --config CONFIG_PATH      Location of the configuration file. Supports local
                            path with glob patterns or remote URL.  [default:
                            ~/.config/my-cli/*.toml|*.yaml|*.yml|*.json|*.json5|
                            *.jsonc|*.hjson|*.ini|*.xml]
  --help                    Show this message and exit.

Commands:
  subcommand

See in the result above, there is an explicit mention of the default location of the configuration file ([default: ~/.config/my-cli/*.toml|*.yaml|*.yml|*.json|*.json5|*.jsonc|*.hjson|*.ini|*.xml]). This improves discoverability, and makes sysadmins happy, especially those not familiar with your CLI.

A bare call returns:

$ my-cli subcommand
dummy_flag    is False
my_list       is ()
int_parameter is 10

With a simple TOML file in the application folder, we will change the CLI’s default output.

Here is what ~/.config/my-cli/config.toml contains:

~/.config/my-cli/config.toml¶
# My default configuration file.
top_level_param = "is_ignored"

[my-cli]
extra_value = "is ignored too"
dummy_flag = true                                  # New boolean default.
my_list = ["item 1", "item #2", "Very Last Item!"]

[garbage]
# An empty random section that will be skipped.

[my-cli.subcommand]
int_param = 3
random_stuff = "will be ignored"

In the file above, pay attention to:

  • the default configuration base path, which is OS-dependant (the ~/.config/my-cli/ path here is for Linux) ;

  • the app’s folder (/my-cli/) which is built from the script’s name (my_cli.py);

  • the top-level config section ([my-cli]), based on the CLI’s group ID (def my_cli());

  • all the extra comments, sections and values that will be silently ignored.

Now we can verify the configuration file is properly read and change the defaults:

$ my-cli subcommand
dummy_flag    is True
my_list       is ('item 1', 'item #2', 'Very Last Item!')
int_parameter is 3

Precedence¶

The configuration loader fetch values according the following precedence:

  • CLI parameters

    • ↖ Configuration file

      • ↖ Environment variables

        • ↖ Defaults

The parameter will take the first value set in that chain.

See how inline parameters takes priority on defaults from the previous example:

$ my-cli subcommand --int-param 555
dummy_flag    is True
my_list       is ('item 1', 'item #2', 'Very Last Item!')
int_parameter is 555

Get configuration values¶

After gathering all the configuration from the different sources, and assembling them together following the precedence rules above, the configuration values are merged back into the Context’s default_map. But only the values that are matching the CLI’s parameters are kept and passed as defaults. All others are silently ignored.

You can still access the full configuration by looking into the context’s meta attribute:

from click_extra import option, echo, pass_context, command, config_option


@command
@option("--int-param", type=int, default=10)
@config_option
@pass_context
def my_cli(ctx, int_param):
    echo(f"Configuration location: {ctx.meta['click_extra.conf_source']}")
    echo(f"Full configuration: {ctx.meta['click_extra.conf_full']}")
    echo(f"Default values: {ctx.default_map}")
    echo(f"int_param is {int_param!r}")
./conf.toml¶
[my-cli]
int_param = 3
random_stuff = "will be ignored"

[garbage]
dummy_flag = true
$ my-cli --config ./conf.toml --int-param 999
Load configuration matching ./conf.toml
Configuration location: /home/me/conf.toml
Full configuration: {'my-cli': {'int_param': 3, 'random_stuff': 'will be ignored'}, 'garbage': {'dummy_flag': True}}
Default values: {'int_param': 3}
int_parameter is 999

Hint

Variables in meta are presented in their original Python type:

  • click_extra.conf_source is either a normalized Path or URL object

  • click_extra.conf_full is a dict whose values are either str or richer types, depending on the capabilities of each format

Strictness¶

As you can see in the first example above, all unrecognized content is ignored.

If for any reason you do not want to allow any garbage in configuration files provided by the user, you can use the strict argument.

Given this cli.toml file:

cli.toml¶
[cli]
int_param = 3
random_param = "forbidden"

The use of strict=True parameter in the CLI below:

from click import command, option, echo

from click_extra import config_option

@command
@option("--int-param", type=int, default=10)
@config_option(strict=True)
def cli(int_param):
    echo(f"int_parameter is {int_param!r}")

Will raise an error and stop the CLI execution on unrecognized random_param value:

$ cli --config "cli.toml"
Load configuration matching cli.toml
(...)
ValueError: Parameter 'random_param' is not allowed in configuration file.

Excluding parameters¶

The excluded_params argument allows you to block some of your CLI options to be loaded from configuration. By setting this argument, you will prevent your CLI users to set these parameters in their configuration file.

It defaults to the value of DEFAULT_EXCLUDED_PARAMS.

You can set your own list of option to ignore with the excluded_params argument:

from click import command, option, echo

from click_extra import config_option

@command
@option("--int-param", type=int, default=10)
@config_option(excluded_params=["my-cli.non_configurable_option", "my-cli.dangerous_param"])
def my_cli(int_param):
    echo(f"int_parameter is {int_param!r}")

Hint

You need to provide the fully-qualified ID of the option you’re looking to block. I.e. the dot-separated ID that is prefixed by the CLI name. That way you can specify an option to ignore at any level, including subcommands.

If you have difficulties identifying your options and their IDs, run your CLI with the --show-params option for introspection.

Formats¶

Several dialects are supported:

Format

Extensions

Description

Enabled by default

TOML

*.toml

-

✅

YAML

*.yaml, *.yml

-

❌

JSON

*.json

-

✅

JSON5

*.json5

A superset of JSON made for configuration file

❌

JSONC

*.jsonc

Like JSON, but with comments and trailing commas

❌

HJSON

*.hjson

Another flavor of a user-friendly JSON

❌

INI

*.ini

With extended interpolation, multi-level sections and non-native types (list, set, 
)

✅

XML

*.xml

-

❌

Formats depending on third-party packages are not enabled by default. You need to install Click Extra with the corresponding extra dependency group to enable them.

TOML¶

See the example in the top of this page.

YAML¶

Important

YAML support requires additional packages. You need to install click-extra[yaml] extra dependency group to enable it.

The example above, given for a TOML configuration file, is working as-is with YAML.

Just replace the TOML file with the following configuration at ~/.config/my-cli/config.yaml:

~/.config/my-cli/config.yaml¶
# My default configuration file.
top_level_param: is_ignored

my-cli:
  extra_value: is ignored too
  dummy_flag: true   # New boolean default.
  my_list:
    - point 1
    - 'point #2'
    - Very Last Point!

  subcommand:
    int_param: 77
    random_stuff: will be ignored

garbage: >
  An empty random section that will be skipped
$ my-cli --config "~/.config/my-cli/config.yaml" subcommand
dummy_flag    is True
my_list       is ('point 1', 'point #2', 'Very Last Point!')
int_parameter is 77

JSON¶

Again, same for JSON:

~/.config/my-cli/config.json¶
{
  "top_level_param": "is_ignored",
  "garbage": {},
  "my-cli": {
    "dummy_flag": true,
    "extra_value": "is ignored too",
    "my_list": [
      "item 1",
      "item #2",
      "Very Last Item!"
    ],
    "subcommand": {
      "int_param": 65,
      "random_stuff": "will be ignored"
    }
  }
}
$ my-cli --config "~/.config/my-cli/config.json" subcommand
dummy_flag    is True
my_list       is ('item 1', 'item #2', 'Very Last Item!')
int_parameter is 65

JSON5¶

Important

JSON5 support requires additional packages. You need to install click-extra[json5] extra dependency group to enable it.

Todo

Write example.

JSONC¶

Important

JSONC support requires additional packages. You need to install click-extra[jsonc] extra dependency group to enable it.

Todo

Write example.

HJSON¶

Important

HJSON support requires additional packages. You need to install click-extra[hjson] extra dependency group to enable it.

Todo

Write example.

INI¶

INI configuration files are allowed to use ExtendedInterpolation by default.

Todo

Write example.

XML¶

Important

XML support requires additional packages. You need to install click-extra[xml] extra dependency group to enable it.

Todo

Write example.

Search pattern¶

The configuration file is searched with a wildcard-based glob pattern.

There is multiple stages to locate and parse the configuration file:

  1. Locate all files matching the search pattern

  2. Match each file against the supported formats, in order, until one is successfully parsed

  3. Use the first successfully parsed file as the configuration source

By default, the pattern is <app_dir>/*.toml|*.json|*.ini, where:

Hint

Depending on the formats you enabled in your installation of Click Extra, the default extensions may vary. For example, if you installed Click Extra with all extra dependencies, the default extensions would extended to *.toml|*.yaml|*.yml|*.json|*.json5|*.jsonc|*.hjson|*.ini|*.xml.

Tip

The search process can be hard to follow. To help you see clearly, you can enable debug logging for the click_extra logger to see which files are located, matched, parsed, skipped, and finally used.

Or better, just pass the --verbosity DEBUG option to your CLI if it is powered by Click Extra.

Default folder¶

The configuration file is searched in the default application path, as defined by click.get_app_dir().

To mirror the latter, the @config_option decorator accept a roaming and force_posix argument to alter the default path:

Platform

roaming

force_posix

Folder

macOS (default)

-

False

~/Library/Application Support/Foo Bar

macOS

-

True

~/.foo-bar

Unix (default)

-

False

~/.config/foo-bar

Unix

-

True

~/.foo-bar

Windows (default)

True

-

C:\Users\<user>\AppData\Roaming\Foo Bar

Windows

False

-

C:\Users\<user>\AppData\Local\Foo Bar

Let’s change the default in the following example:

from click import command

from click_extra import config_option

@command(context_settings={"show_default": True})
@config_option(force_posix=True)
def cli():
    pass

See how the default to --config option has been changed to ~/.cli/:

$ cli --help
Usage: cli [OPTIONS]

Options:
  --config CONFIG_PATH  Location of the configuration file. Supports local path
                        with glob patterns or remote URL.  [default: ~/.cli/*.to
                        ml|*.yaml|*.yml|*.json|*.json5|*.jsonc|*.hjson|*.ini|*.x
                        ml]
  --help                Show this message and exit.

See also

The default application folder concept has a long and complicated history in the Unix world.

The oldest reference I can track is from the Where Configurations Live chapter from The Art of Unix Programming.

The XDG base directory specification is the latest iteration of this tradition on Linux. This long-due guidelines brings lots of benefits to the platform. This is what Click Extra is implementing by default.

But there is still a lot of cases for which the XDG doesn’t cut it, like on other platforms (macOS, Windows, 
) or for legacy applications. That’s why Click Extra allows you to customize the way configuration is searched and located.

Custom pattern¶

You can directly provide a customized search pattern to the default argument of the decorator:

from click import command

from click_extra import config_option

@command(context_settings={"show_default": True})
@config_option(default="~/my_special_folder/*.toml|*.conf")
def cli():
    pass
$ cli --help
Usage: cli [OPTIONS]

Options:
  --config CONFIG_PATH  Location of the configuration file. Supports local path
                        with glob patterns or remote URL.  [default:
                        ~/my_special_folder/*.toml|*.conf]
  --help                Show this message and exit.

The rules for the pattern are described in the next section.

Search pattern specifications¶

Patterns provided to @config_option’s default argument:

  • Are based on wcmatch.glob syntax.

  • Should be written with Unix separators (/), even for Windows: the pattern will be normalized to the local platform dialect.

  • Can be absolute or relative paths.

  • Have their default case-sensitivity aligned with the local platform:

    • Windows is insensitive to case,

    • Unix and macOS are case-sensitive.

  • Are setup with the following default flags:

    Flag

    Description

    GLOBSTAR

    Recursive directory search via ** glob notation.

    FOLLOW

    Traverse symlink directories.

    DOTGLOB

    Include file or directory starting with a literal dot (.).

    SPLIT

    Allow multiple patterns separated by `

    GLOBTILDE

    Allow user’s home path ~ to be expanded.

    NODIR

    Restricts results to files.

Important

The NODIR flag is always forced, to optimize the search for files only.

The flags above can be changed via the search_pattern_flags argument of the decorator. So to make the matching case-insensitive, add the IGNORECASE flag:

from wcmatch.glob import (
    GLOBSTAR,
    FOLLOW,
    DOTGLOB,
    SPLIT,
    GLOBTILDE,
    NODIR,
    IGNORECASE
)

@config_option(
    file_pattern_flags=(
        GLOBSTAR | FOLLOW | DOTGLOB | SPLIT | GLOBTILDE | NODIR | IGNORECASE
    )
)

But because of the way flags works, you have to re-specify all flags you want to keep, including the default ones.

See also

This is the same pinciple as file pattern flags.

Multi-format matching¶

The default behavior consist in searching for all files matching the default *.toml|*.json|*.ini pattern. Or more, depending on the extra dependencies installed with Click Extra.

As soon as files are located, they are matched against each supported format, in order, until one is successfully parsed.

The first successfully parsed file is used to feed the CLI’s default values.

The search will only consider matches that:

  • exists,

  • are a file,

  • are not empty,

  • matches file format patterns,

  • can be parsed successfully, and

  • produce a non-empty data structure.

All others are skipped. And the search continues with the next matching file.

To influence which formats are supported, see the next section.

Format selection¶

If you want to limit the formats supported by your CLI, you can use the file_format_patterns argument to specify which formats are allowed:

from click import command, option, echo

from click_extra import config_option, ConfigFormat

@command(context_settings={"show_default": True})
@option("--int-param", type=int, default=10)
@config_option(file_format_patterns=[ConfigFormat.JSON, ConfigFormat.TOML])
def cli(int_param):
    echo(f"int_parameter is {int_param!r}")

Notice how the default search pattern has been restricted to only *.json and *.toml files, and also that the order is reflected in the help:

$ cli --help
Usage: cli [OPTIONS]

Options:
  --int-param INTEGER   [default: 10]
  --config CONFIG_PATH  Location of the configuration file. Supports local path
                        with glob patterns or remote URL.  [default:
                        ~/.config/cli/*.json|*.toml]
  --help                Show this message and exit.

You can also specify a single format:

from click import command, option, echo

from click_extra import config_option, ConfigFormat

@command(context_settings={"show_default": True})
@option("--int-param", type=int, default=10)
@config_option(file_format_patterns=ConfigFormat.XML)
def cli(int_param):
    echo(f"int_parameter is {int_param!r}")
$ cli --help
Usage: cli [OPTIONS]

Options:
  --int-param INTEGER   [default: 10]
  --config CONFIG_PATH  Location of the configuration file. Supports local path
                        with glob patterns or remote URL.  [default:
                        ~/.config/cli/*.xml]
  --help                Show this message and exit.

Custom file format patterns¶

Each format is associated with default file patterns. But you can also change these with the same file_format_patterns argument:

from click import command, option, echo

from click_extra import config_option, ConfigFormat

@command(context_settings={"show_default": True})
@option("--int-param", type=int, default=10)
@config_option(
    file_format_patterns={
        ConfigFormat.TOML: ["*.toml", "my_app.conf"],
        ConfigFormat.JSON: ["settings*.js", "*.json"],
    }
)
def cli(int_param):
    echo(f"int_parameter is {int_param!r}")

Again, this is reflected in the help:

$ cli --help
Usage: cli [OPTIONS]

Options:
  --int-param INTEGER   [default: 10]
  --config CONFIG_PATH  Location of the configuration file. Supports local path
                        with glob patterns or remote URL.  [default:
                        ~/.config/cli/*.toml|my_app.conf|settings*.js|*.json]
  --help                Show this message and exit.

Parsing priority¶

The syntax of file_format_patterns argument allows you to specify either a list of formats, a single format, or a mapping of formats to patterns. And we can even have multiple formats share the same pattern:

from click import command, option, echo

from click_extra import config_option, ConfigFormat

@command(context_settings={"show_default": True})
@option("--int-param", type=int, default=10)
@config_option(
    file_format_patterns={
        ConfigFormat.TOML: "*.toml",
        ConfigFormat.JSON5: "config*.js",
        ConfigFormat.JSON: ["config*.js", "*.js"],
    }
)
def cli(int_param):
    echo(f"int_parameter is {int_param!r}")

Notice how all formats are merged into the same pattern:

$ cli --help
Usage: cli [OPTIONS]

Options:
  --int-param INTEGER   [default: 10]
  --config CONFIG_PATH  Location of the configuration file. Supports local path
                        with glob patterns or remote URL.  [default:
                        ~/.config/cli/*.toml|config*.js|*.js]
  --help                Show this message and exit.

What will happen in this case is that the search will try to parse matching files first as JSON5, then as JSON. The first format that successfully parses the file will be used.

So a file named config123.js containing valid JSON5 syntax will be parsed as such, even if it also contains valid JSON syntax and match the *.js pattern. But if for any reason the JSON5 parsing fails, the search will try to parse it as JSON next, which is the second-best match.

On the other hand, a file named settings.js will only be tried as JSON, since it doesn’t match the JSON5 pattern.

This illustrates the flexibility of this approach, but how the order of formats matter.

File pattern flags¶

The file_pattern_flags argument controls the matching behavior of file patterns.

These flags are defined in wcmatch.fnmatch and default to:

Flag

Description

NEGATE

Adds support of ! negation to define exclusions.

SPLIT

Allow multiple patterns separated by `

Important

The SPLIT flag is always forced, as our multi-pattern design relies on it.

If for example, you want to make the matching case-insensitive, you do that by adding the IGNORECASE flag:

from wcmatch.fnmatch import NEGATE, SPLIT, IGNORECASE

@config_option(file_pattern_flags=NEGATE | SPLIT | IGNORECASE)

But because of the way flags works, you have to re-specify all flags you want to keep, including the default ones.

See also

This is the same pinciple as search pattern specifications.

Excluding files¶

Negation is active by default, which is useful when you want to exclude some files from being considered during the search.

To ignore, for example, all your template files residing alongside real configuration files. Then, to exclude all files starting with template_ in their name, you can do:

@config_option(
    file_format_patterns={
        ConfigFormat.TOML: ["*.toml", "!template_*.toml"],
    }
)

Extension-less files¶

This demonstrate the popular case on Unix-like systems, where the configuration file is an extension-less dotfile in the home directory.

Here is how to set up @config_option for a pre-defined .commandrc file in YAML:

from click import command

from click_extra import config_option, ConfigFormat

@command(context_settings={"show_default": True})
@config_option(
    default="~/*",
    file_format_patterns={ConfigFormat.YAML: ".commandrc"}
)
def cli():
    pass
$ cli --help
Usage: cli [OPTIONS]

Options:
  --config CONFIG_PATH  Location of the configuration file. Supports local path
                        with glob patterns or remote URL.  [default: ~/*]
  --help                Show this message and exit.

Caution

Depending on how you set up your patterns, files starting with a dot (.) may not be matched by default. Make sure to include the DOTMATCH flag in file_pattern_flags if needed.

Remote URL¶

Remote URL can be passed directly to the --config option:

$ my-cli --config "https://example.com/dummy/configuration.yaml" subcommand
dummy_flag    is True
my_list       is ('point 1', 'point #2', 'Very Last Point!')
int_parameter is 77

Warning

URLs do not support multi-format matching. You need to provide a direct link to the configuration file, including its extension.

Glob patterns are also not supported for URLs. Unless you want to let your users download the whole internet


click_extra.config API¶

        classDiagram
  Enum <|-- ConfigFormat
  Enum <|-- Sentinel
  ExtraOption <|-- ConfigOption
  ExtraOption <|-- NoConfigOption
  ParamStructure <|-- ConfigOption
    

Utilities to load parameters and options from a configuration file.

Hint

Why config?

That whole namespace is using the common config short-name to designate configuration files.

Not conf, not cfg, not configuration, not settings. Just config.

A quick survey of existing practices, and poll to my friends informed me that config is more explicit and less likely to be misunderstood.

After all, is there a chance for it to be misunderstood, in the context of a CLI, for something else? Confirm? Conference? Conflict Confuse?


So yes, config is good enough.

Todo

Add a --dump-config or --export-config option to write down the current configuration (or a template) into a file or <stdout>.

Help message would be: you can use this option with other options or environment variables to have them set in the generated configuration.

Todo

Add a ParameterSource.CONFIG_FILE entry to the ParameterSource enum? Also see: https://github.com/pallets/click/issues/2879

class click_extra.config.ConfigFormat(*values)[source]¶

Bases: Enum

All configuration formats, associated to their support status.

The first element of the tuple is a sequence of file extensions associated to the format. Patterns are fed to wcmatch.glob for matching, and are influenced by the flags set on the ConfigOption instance.

The second element indicates whether the format is supported or not, depending on the availability of the required third-party packages. This evaluation is performed at runtime when this module is imported.

Caution

The order is important for both format members and file patterns. It defines the priority order in which formats are tried when multiple candidate files are found.

Todo

Add support for JWCC / hujson format?

TOML = (('*.toml',), True)¶
YAML = (('*.yaml', '*.yml'), True)¶
JSON = (('*.json',), True)¶
JSON5 = (('*.json5',), True)¶
JSONC = (('*.jsonc',), True)¶
HJSON = (('*.hjson',), True)¶
INI = (('*.ini',), True)¶
XML = (('*.xml',), True)¶
property enabled: bool¶

Returns True if the format is supported, False otherwise.

property patterns: tuple[str]¶

Returns the default file patterns associated to the format.

click_extra.config.CONFIG_OPTION_NAME = 'config'¶

Hardcoded name of the configuration option.

This name is going to be shared by both the --config and --no-config options below, so they can compete with each other to either set a path pattern or disable the use of any configuration file at all.

click_extra.config.DEFAULT_EXCLUDED_PARAMS = ('config', 'help', 'show_params', 'version')¶

Default parameter IDs to exclude from the configuration file.

Defaults to:

  • --config option, which cannot be used to recursively load another configuration file.

  • --help, as it makes no sense to have the configurable file always forces a CLI to show the help and exit.

  • --show-params flag, which is like --help and stops the CLI execution.

  • --version, which is not a configurable option per-se.

class click_extra.config.Sentinel(*values)[source]¶

Bases: Enum

Enum used to define sentinel values.

Note

This reuse the same pattern as Click._utils.Sentinel.

NO_CONFIG = <object object>¶
click_extra.config.NO_CONFIG = Sentinel.NO_CONFIG¶

Sentinel used to indicate that no configuration file must be used at all.

class click_extra.config.ConfigOption(param_decls=None, metavar='CONFIG_PATH', type=UNPROCESSED, help='Location of the configuration file. Supports local path with glob patterns or remote URL.', is_eager=True, expose_value=False, file_format_patterns=None, file_pattern_flags=4104, roaming=True, force_posix=False, search_pattern_flags=284992, search_parents=False, excluded_params=None, strict=False, **kwargs)[source]¶

Bases: ExtraOption, ParamStructure

A pre-configured option adding --config CONFIG_PATH.

Takes as input a path to a file or folder, a glob pattern, or an URL.

  • is_eager is active by default so the callback gets the opportunity to set the default_map of the CLI before any other parameter is processed.

  • default is set to the value returned by self.default_pattern(), which is a pattern combining the default configuration folder for the CLI (as returned by click.get_app_dir()) and all supported file formats.

    Attention

    Default search pattern must follow the syntax of wcmatch.glob.

  • excluded_params are parameters which, if present in the configuration file, will be ignored and not applied to the CLI. Items are expected to be the fully-qualified ID of the parameter, as produced in the output of --show-params. Will default to the value of DEFAULT_EXCLUDED_PARAMS.

file_format_patterns: dict[ConfigFormat, tuple[str, ...]]¶

Mapping of ConfigFormat to their associated file patterns.

Can be a string or a sequence of strings. This defines which configuration file formats are supported, and which file patterns are used to search for them.

Note

All formats depending on third-party dependencies that are not installed will be ignored.

Attention

File patterns must follow the syntax of wcmatch.fnmatch.

file_pattern_flags¶

Flags provided to all calls of wcmatch.fnmatch.

Applies to the matching of file names against supported format patterns specified in file_format_patterns.

Important

The SPLIT flag is always forced, as our multi-pattern design relies on it.

force_posix¶

Configuration for default folder search.

roaming and force_posix are fed to click.get_app_dir() to determine the location of the default configuration folder.

search_pattern_flags¶

Flags provided to all calls of wcmatch.glob.

Applies to both the default pattern and any user-provided pattern.

Important

The NODIR flag is always forced, to optimize the search for files only.

search_parents¶

Indicates whether to walk back the tree of parent folders when searching for configuration files.

type: types.ParamType¶
is_flag: bool¶
is_bool_flag: bool¶
flag_value: t.Any¶
name: str | None¶
opts: list[str]¶
secondary_opts: list[str]¶
default: t.Any | t.Callable[[], t.Any] | None¶
strict¶

Defines the strictness of the configuration loading.

  • If True, raise an error if the configuration file contain parameters not recognized by the CLI.

  • If False, silently ignore unrecognized parameters.

property excluded_params: frozenset[str][source]¶

Generates the default list of fully-qualified IDs to exclude.

Danger

It is only called once to produce the default exclusion list if the user did not provided its own.

It was not implemented in the constructor but made as a property, to allow for a just-in-time call within the current context. Without this trick we could not have fetched the CLI name.

property file_pattern: str[source]¶

Compile all file patterns from the supported formats.

Use | split notation to combine multiple patterns.

Returns a single pattern string.

default_pattern()[source]¶

Returns the default pattern used to search for the configuration file.

Defaults to <app_dir>/*.toml|*.json|*.ini. Where <app_dir> is produced by the clickget_app_dir() method. The result depends on OS and is influenced by the roaming and force_posix properties.

Todo

Use platformdirs for more advanced configuration folder detection?

Return type:

str

get_help_extra(ctx)[source]¶

Replaces the default value of the configuration option.

Display a pretty path that is relative to the user’s home directory:

~/folder/my_cli/*.toml|*.json|*.ini

Instead of the full absolute path:

/home/user/folder/my_cli/*.toml|*.json|*.ini

Caution

This only applies when the GLOBTILDE flag is set in search_pattern_flags.

Return type:

OptionHelpExtra

parent_patterns(pattern)[source]¶

Generate patterns for parent directories lookup.

Yields patterns for each parent directory of the given pattern.

The first yielded pattern is the original one.

Stops when reaching the root folder.

Return type:

Iterable[str]

search_and_read_file(pattern)[source]¶

Search filesystem or URL for files matching the pattern.

If pattern is an URL, download its content. A pattern is considered an URL only if it validates as one and starts with http:// or https://. All other patterns are considered glob patterns for local filesystem search.

Returns an iterator of the normalized location and its raw content, for each one matching the pattern. Only files are returned, directories are silently skipped.

This method returns the raw content of all matching patterns, without trying to parse them. If the content is empty, it is still returned as-is.

Also includes lookups into parents directories if self.search_parents is True.

Raises FileNotFoundError if no file was found after searching all locations.

Return type:

Iterable[tuple[Path | URL, str]]

parse_conf(content, formats)[source]¶

Parse the content with the given formats.

Tries to parse the given raw content string with each of the given formats, in order. Yields the resulting data structure for each successful parse.

Attention

Formats whose parsing raises an exception or does not return a dict are considered a failure and are skipped.

This follows the parse, don’t validate principle.

Return type:

Iterable[dict[str, Any] | None]

read_and_parse_conf(pattern)[source]¶

Search for a parseable configuration file.

Returns the location and data structure of the first configuration matching the pattern.

Only return the first match that:

  • exists,

  • is a file,

  • is not empty,

  • match file format patterns,

  • can be parsed successfully, and

  • produce a non-empty data structure.

Raises FileNotFoundError if no configuration file was found matching the criteria above.

Returns (None, None) if files were found but none could be parsed.

Return type:

tuple[Path | URL, dict[str, Any]] | tuple[None, None]

load_ini_config(content)[source]¶

Utility method to parse INI configuration file.

Internal convention is to use a dot (., as set by self.SEP) in section IDs as a separator between levels. This is a workaround the limitation of INI format which doesn’t allow for sub-sections.

Returns a ready-to-use data structure.

Return type:

dict[str, Any]

merge_default_map(ctx, user_conf)[source]¶

Save the user configuration into the context’s default_map.

Merge the user configuration into the pre-computed template structure, which will filter out all unrecognized options not supported by the command. Then cleans up blank values and update the context’s default_map.

Return type:

None

load_conf(ctx, param, path_pattern)[source]¶

Fetch parameters values from configuration file and sets them as defaults.

User configuration is merged to the context’s default_map, like Click does.

By relying on Click’s default_map, we make sure that precedence is respected. And direct CLI parameters, environment variables or interactive prompts takes precedence over any values from the config file.

Return type:

None

class click_extra.config.NoConfigOption(param_decls=None, type=UNPROCESSED, help='Ignore all configuration files and only use command line parameters and environment variables.', is_flag=True, flag_value=Sentinel.NO_CONFIG, is_eager=True, expose_value=False, **kwargs)[source]¶

Bases: ExtraOption

A pre-configured option adding --no-config.

This option is supposed to be used alongside the --config option (ConfigOption) to allow users to explicitly disable the use of any configuration file.

This is especially useful to debug side-effects caused by autodetection of configuration files.

See also

An alternative implementation of this class would be to create a custom click.ParamType instead of a custom Option subclass. Here is for example.

check_sibling_config_option(ctx, param, value)[source]¶

Ensure that this option is used alongside a ConfigOption instance.

Return type:

None