confattr.configfile module

This module defines the ConfigFile class which can be used to load and save config files.

class confattr.configfile.ArgPos

Bases: object

This is an internal class, the return type of ConfigFile.find_arg()

argument_pos: int

The index of the argument in ln_split where the cursor is located and which shall be completed. Please note that this can be one bigger than ln_split is long if the line ends on a space and the cursor is behind that space. In that case in_between is true.

i0: int

The index in line where the argument having the cursor starts (inclusive) or the start of the next argument if in_between is true

i1: int

The index in line where the current word ends (exclusive) or the end of the previous argument if in_between is true

in_between: bool

If true: The cursor is between two arguments, before the first argument or after the last argument. argument_pos refers to the next argument, argument_pos-1 to the previous argument. i0 is the start of the next argument, i1 is the end of the previous argument.

class confattr.configfile.ArgumentParser(prog=None, usage=None, description=None, epilog=None, parents=[], formatter_class=<class 'argparse.HelpFormatter'>, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True, allow_abbrev=True, exit_on_error=True)

Bases: ArgumentParser

error(message: str) NoReturn

Raise a ParseException.

class confattr.configfile.ConfigFile(*, notification_level: ~confattr.config.Config[~confattr.configfile.NotificationLevel] = NotificationLevel.ERROR, appname: str, authorname: str | None = None, config_instances: dict[str, confattr.config.Config[typing.Any]] = {}, commands: ~collections.abc.Sequence[type[confattr.configfile.ConfigFileCommand]] | None = None, formatter_class: type[argparse.HelpFormatter] = <class 'confattr.utils.HelpFormatter'>, check_config_id: ~collections.abc.Callable[[~confattr.config.ConfigId], None] | None = None, enable_config_ids: bool | None = None)

Bases: object

Read or write a config file.

Parameters:
  • notification_level – A Config which the users of your application can set to choose whether they want to see information which might be interesting for debugging a config file. A Message with a priority lower than this value is not passed to the callback registered with set_ui_callback().

  • appname – The name of the application, required for generating the path of the config file if you use load() or save() and as prefix of environment variable names

  • authorname – The name of the developer of the application, on MS Windows useful for generating the path of the config file if you use load() or save()

  • config_instances – The Config instances to load or save, defaults to Config.instances

  • commands – The commands (as subclasses of ConfigFileCommand or ConfigFileArgparseCommand) allowed in this config file, if this is None: use the return value of ConfigFileCommand.get_command_types()

  • formatter_class – Is used to clean up doc strings and wrap lines in the help

  • check_config_id – Is called every time a configuration group is opened (except for Config.default_config_id—that is always allowed). The callback should raise a ParseException if the config id is invalid.

  • enable_config_ids – see enable_config_ids. If None: Choose True or False automatically based on check_config_id and the existence of MultiConfig/MultiDictConfig

COMMENT = '#'
COMMENT_PREFIXES = ('"', '#')
ENTER_GROUP_PREFIX = '['
ENTER_GROUP_SUFFIX = ']'
config_directory: str | None = None

Override the config directory which is returned by iter_user_site_config_paths(). You should set either this attribute or config_path in your tests with monkeypatch.setattr. If the environment variable APPNAME_CONFIG_DIRECTORY is set this attribute is set to it’s value in the constructor (where APPNAME is the value which is passed as appname to the constructor but in all upper case letters and hyphens and spaces replaced by underscores.)

config_id: ConfigId | None

While loading a config file: The group that is currently being parsed, i.e. an identifier for which object(s) the values shall be set. This is set in enter_group() and reset in load_file().

config_instances: dict[str, confattr.config.Config[Any]]

The Config instances to load or save

config_name = 'config'

The name of the config file used by iter_config_paths(). Can be changed with the environment variable APPNAME_CONFIG_NAME (where APPNAME is the value which is passed as appname to the constructor but in all upper case letters and hyphens and spaces replaced by underscores.).

config_path: str | None = None

Override the config file which is returned by iter_config_paths(). You should set either this attribute or config_directory in your tests with monkeypatch.setattr. If the environment variable APPNAME_CONFIG_PATH is set this attribute is set to it’s value in the constructor (where APPNAME is the value which is passed as appname to the constructor but in all upper case letters and hyphens and spaces replaced by underscores.)

context_file_name: str | None = None

The name of the file which is currently loaded. If this equals Message.ENVIRONMENT_VARIABLES it is no file name but an indicator that environment variables are loaded. This is None if parse_line() is called directly (e.g. the input from a command line is parsed).

context_line: str = ''

The line which is currently parsed.

context_line_number: int | None = None

The number of the line which is currently parsed. This is None if context_file_name is not a file name.

create_formatter() HelpFormatterWrapper
enable_config_ids: bool

If true: [config-id] syntax is allowed in config file, config ids are included in help, config id related options are available for include. If false: It is not possible to set different values for different objects (but default values for MultiConfig instances can be set)

enter_group(line: str) bool

Check if line starts a new group and set config_id if it does. Call parse_error() if check_config_id raises a ParseException.

Parameters:

line – The current line

Returns:

True if line starts a new group

env_variables: list[str]

Contains the names of the environment variables for config_path, config_directory and config_name—in capital letters and prefixed with envprefix.

envprefix: str

A prefix that is prepended to the name of environment variables in get_env_name(). It is set in the constructor by first setting it to an empty str and then passing the value of appname to get_env_name() and appending an underscore.

find_arg(line: str, ln_split: list[str], cursor_pos: int) ArgPos

This is an internal method used by get_completions_command()

get_app_dirs() AppDirs

Create or get a cached AppDirs instance with multipath support enabled.

When creating a new instance, platformdirs, xdgappdirs and appdirs are tried, in that order. The first one installed is used. appdirs, the original of the two forks and the only one of the three with type stubs, is specified in pyproject.toml as a hard dependency so that at least one of the three should always be available. I am not very familiar with the differences but if a user finds that appdirs does not work for them they can choose to use an alternative with pipx inject appname xdgappdirs|platformdirs.

These libraries should respect the environment variables XDG_CONFIG_HOME and XDG_CONFIG_DIRS.

get_command(ln_split: Sequence[str]) ConfigFileCommand
get_completions(line: str, cursor_pos: int) tuple[str, list[str], str]

Provide an auto completion for commands that can be executed with parse_line().

Parameters:
  • line – The entire line that is currently in the text input field

  • cursor_pos – The position of the cursor

Returns:

start of line, completions, end of line. completions is a list of possible completions for the word where the cursor is located. If completions is an empty list there are no completions available and the user input should not be changed. If completions is not empty it should be displayed by a user interface in a drop down menu. The start of line is everything on the line before the completions. The end of line is everything on the line after the completions. In the likely case that the cursor is at the end of the line the end of line is an empty str. start of line and end of line should be the beginning and end of line but they may contain minor changes in order to keep quoting feasible.

get_completions_command(line: str, cursor_pos: int) tuple[str, list[str], str]

For a description of parameters and return type see get_completions().

get_completions() has stripped any indentation from line and will prepend it to the first item of the return value.

get_completions_command_name(line: str, cursor_pos: int, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
get_completions_enter_group(line: str, cursor_pos: int) tuple[str, list[str], str]

For a description of parameters and return type see get_completions().

get_completions() has stripped any indentation from line and will prepend it to the first item of the return value.

get_env_name(key: str) str

Convert the key of a setting to the name of the corresponding environment variable.

Returns:

An all upper case version of key with all hyphens, dots and spaces replaced by underscores and envprefix prepended to the result.

get_help() str

A convenience wrapper around write_help() to return the help as a str instead of writing it to a file.

This uses HelpWriter.

get_help_config_id() str
Returns:

A help how to use MultiConfig. The return value still needs to be cleaned with inspect.cleandoc().

get_save_path() str
Returns:

The first existing and writable file returned by iter_config_paths() or the first path if none of the files are existing and writable.

is_comment(line: str) bool

Check if line is a comment.

Parameters:

line – The current line

Returns:

True if line is a comment

iter_config_paths() Iterator[str]

Iterate over all paths which are checked for config files, user specific first.

Use this method if you want to tell the user where the application is looking for it’s config file. The first existing file yielded by this method is used by load().

The paths are generated by joining the directories yielded by iter_user_site_config_paths() with ConfigFile.config_name.

If config_path has been set this method yields that path instead and no other paths.

iter_user_site_config_paths() Iterator[str]

Iterate over all directories which are searched for config files, user specific first.

The directories are based on get_app_dirs() unless config_directory has been set. If config_directory has been set it’s value is yielded and nothing else.

load(*, env: bool = True) None

Load the first existing config file returned by iter_config_paths().

If there are several config files a user specific config file is preferred. If a user wants a system wide config file to be loaded, too, they can explicitly include it in their config file. :param _sphinx_paramlinks_confattr.configfile.ConfigFile.load.env: If true: call load_env() after loading the config file.

load_env() None

Load settings from environment variables. The name of the environment variable belonging to a setting is generated with get_env_name().

Environment variables not matching a setting or having an invalid value are reported with self.ui_notifier.show_error().

Raises:

ValueError – if two settings have the same environment variable name (see get_env_name()) or the environment variable name for a setting collides with one of the standard environment variables listed in env_variables

load_file(fn: str) None

Load a config file and change the Config objects accordingly.

Use set_ui_callback() to get error messages which appeared while loading the config file. You can call set_ui_callback() after this method without loosing any messages.

Parameters:

fn – The file name of the config file (absolute or relative path)

load_without_resetting_config_id(fn: str) None
parse_error(msg: str) None

Is called if something went wrong while trying to load a config file.

This method is called when a ParseException or MultipleParseExceptions is caught. This method compiles the given information into an error message and calls self.ui_notifier.show_error().

Parameters:

msg – The error message

parse_line(line: str) bool
Parameters:

line – The line to be parsed

Returns:

True if line is valid, False if an error has occurred

parse_error() is called if something goes wrong (i.e. if the return value is False), e.g. invalid key or invalid value.

parse_split_line(ln_split: Sequence[str]) bool

Call the corresponding command in command_dict. If any ParseException or MultipleParseExceptions is raised catch it and call parse_error().

Returns:

False if a ParseException or MultipleParseExceptions has been caught, True if no exception has been caught

quote(val: str) str

Quote a value if necessary so that it will be interpreted as one argument.

The default implementation calls readable_quote().

save(**kw: Unpack[SaveKwargs]) str

Save the current values of all settings to the file returned by get_save_path(). Directories are created as necessary.

Parameters:
  • config_instances – Do not save all settings but only those given. If this is a list they are written in the given order. If this is a set they are sorted by their keys.

  • ignore – Do not write these settings to the file.

  • no_multi – Do not write several sections. For MultiConfig instances write the default values only.

  • comments – Write comments with allowed values and help.

Returns:

The path to the file which has been written

save_file(fn: str, **kw: Unpack[SaveKwargs]) None

Save the current values of all settings to a specific file.

Parameters:

fn – The name of the file to write to. If this is not an absolute path it is relative to the current working directory.

Raises:

FileNotFoundError – if the directory does not exist

For an explanation of the other parameters see save().

save_to_open_file(f: TextIO, **kw: Unpack[SaveKwargs]) None

Save the current values of all settings to a file-like object by creating a ConfigFileWriter object and calling save_to_writer().

Parameters:

f – The file to write to

For an explanation of the other parameters see save().

save_to_writer(writer: FormattedWriter, **kw: Unpack[SaveKwargs]) None

Save the current values of all settings.

Ensure that all keyword arguments are passed with set_save_default_arguments(). Iterate over all ConfigFileCommand objects in self.commands and do for each of them:

set_save_default_arguments(kw: SaveKwargs) None

Ensure that all arguments are given in kw.

set_ui_callback(callback: Callable[[Message], None]) None

Register a callback to a user interface in order to show messages to the user like syntax errors or invalid values in the config file.

Messages which occur before this method is called are stored and forwarded as soon as the callback is registered.

Parameters:

ui_callback – A function to display messages to the user

split_line(line: str) list[str]
split_line_ignore_errors(line: str) list[str]
write_config_id(writer: FormattedWriter, config_id: ConfigId) None

Start a new group in the config file so that all following commands refer to the given config_id.

write_help(writer: FormattedWriter) None
class confattr.configfile.ConfigFileArgparseCommand(config_file: ConfigFile)

Bases: ConfigFileCommand

An abstract subclass of ConfigFileCommand which uses argparse to make parsing and providing help easier.

You must implement the class method init_parser() to add the arguments to parser. Instead of run() you must implement run_parsed(). You don’t need to add a usage or the possible arguments to the doc string as argparse will do that for you. You should, however, still give a description what this command does in the doc string.

You may specify ConfigFileCommand.name, ConfigFileCommand.aliases and ConfigFileCommand.save() like for ConfigFileCommand.

after_positional_argument_marker(cmd: Sequence[str], argument_pos: int) bool
Returns:

true if this can only be a positional argument. False means it can be both, option or positional argument.

get_action_for_option(option_name: str) Action | None
get_action_for_positional_argument(argument_pos: int) Action | None
get_completions(cmd: Sequence[str], argument_pos: int, cursor_pos: int, *, in_between: bool, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
Parameters:
  • cmd – The line split into arguments (including the name of this command as cmd[0])

  • argument_pos – The index of the argument which shall be completed. Please note that this can be one bigger than cmd is long if the line ends on a space and the cursor is behind that space. In that case in_between is true.

  • cursor_pos – The index inside of the argument where the cursor is located. This is undefined and should be ignored if in_between is true. The input from the start of the argument to the cursor should be used to filter the completions. The input after the cursor can be ignored.

  • in_between – If true: The cursor is between two arguments, before the first argument or after the last argument. argument_pos refers to the next argument, argument_pos-1 to the previous argument. cursor_pos is undefined.

  • start_of_line – The first return value. If cmd[argument_pos] has a pattern like key=value you can append key= to this value and return only completions of value as second return value.

  • end_of_line – The third return value.

Returns:

start of line, completions, end of line. completions is a list of possible completions for the word where the cursor is located. If completions is an empty list there are no completions available and the user input should not be changed. This should be displayed by a user interface in a drop down menu. The start of line is everything on the line before the completions. The end of line is everything on the line after the completions. In the likely case that the cursor is at the end of the line the end of line is an empty str. start of line and end of line should be the beginning and end of line but they may contain minor changes in order to keep quoting feasible.

get_completions_for_action(action: Action | None, start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
get_completions_for_option_argument(option_name: str, start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
get_completions_for_option_name(start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
get_completions_for_positional_argument(position: int, start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
get_help() str

Creates a help text which can be presented to the user by calling parser.format_help(). The return value of ConfigFileCommand.write_help() has been passed as description to the constructor of ArgumentParser, therefore help/the doc string are included as well.

get_option_name_if_it_takes_an_argument(cmd: Sequence[str], argument_pos: int) str | None
get_position(cmd: Sequence[str], argument_pos: int) int
Returns:

the position of a positional argument, not counting options and their arguments

abstract init_parser(parser: ArgumentParser) None
Parameters:

parser – The parser to add arguments to. This is the same object like parser.

This is an abstract method which must be implemented by subclasses. Use ArgumentParser.add_argument() to add arguments to parser.

is_option_start(start: str) bool
run(cmd: Sequence[str]) None

Process one line which has been read from a config file

Raises:
abstract run_parsed(args: Namespace) None

This is an abstract method which must be implemented by subclasses.

class confattr.configfile.ConfigFileCommand(config_file: ConfigFile)

Bases: ABC

An abstract base class for commands which can be used in a config file.

Subclasses must implement the run() method which is called when ConfigFile is loading a file. Subclasses should contain a doc string so that get_help() can provide a description to the user. Subclasses may set the name and aliases attributes to change the output of get_name() and get_names().

All subclasses are remembered and can be retrieved with get_command_types(). They are instantiated in the constructor of ConfigFile.

add_help_to(formatter: HelpFormatterWrapper) None

Add the return value of get_help_attr_or_doc_str() to formatter.

aliases: tuple[str, ...] | list[str]

Alternative names which can be used in the config file.

config_file: ConfigFile

The ConfigFile that has been passed to the constructor. It determines for example the notification_level and the available commands.

create_formatter() HelpFormatterWrapper
classmethod delete_command_type(cmd_type: type[confattr.configfile.ConfigFileCommand]) None

Delete cmd_type so that it is not returned anymore by get_command_types() and that it’s name can be used by another command. Do nothing if cmd_type has already been deleted.

classmethod get_command_types() tuple[type[confattr.configfile.ConfigFileCommand], ...]
Returns:

All subclasses of ConfigFileCommand which have not been deleted with delete_command_type()

get_completions(cmd: Sequence[str], argument_pos: int, cursor_pos: int, *, in_between: bool, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
Parameters:
  • cmd – The line split into arguments (including the name of this command as cmd[0])

  • argument_pos – The index of the argument which shall be completed. Please note that this can be one bigger than cmd is long if the line ends on a space and the cursor is behind that space. In that case in_between is true.

  • cursor_pos – The index inside of the argument where the cursor is located. This is undefined and should be ignored if in_between is true. The input from the start of the argument to the cursor should be used to filter the completions. The input after the cursor can be ignored.

  • in_between – If true: The cursor is between two arguments, before the first argument or after the last argument. argument_pos refers to the next argument, argument_pos-1 to the previous argument. cursor_pos is undefined.

  • start_of_line – The first return value. If cmd[argument_pos] has a pattern like key=value you can append key= to this value and return only completions of value as second return value.

  • end_of_line – The third return value.

Returns:

start of line, completions, end of line. completions is a list of possible completions for the word where the cursor is located. If completions is an empty list there are no completions available and the user input should not be changed. This should be displayed by a user interface in a drop down menu. The start of line is everything on the line before the completions. The end of line is everything on the line after the completions. In the likely case that the cursor is at the end of the line the end of line is an empty str. start of line and end of line should be the beginning and end of line but they may contain minor changes in order to keep quoting feasible.

get_completions_for_file_name(start: str, *, relative_to: str, exclude: str | None = None, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
Parameters:
  • start – The start of the path to be completed

  • relative_to – If start is a relative path it’s relative to this directory

  • exclude – A regular expression. The default value None is interpreted differently depending on the platform.platform(). For Windows it’s $none so that nothing is excluded. For others it’s ^\. so that hidden files and directories are excluded.

Returns:

All files and directories that start with start and do not match exclude. Directories are appended with os.path.sep. os.path.sep is appended after quoting so that it can be easily stripped if undesired (e.g. if the user interface cycles through all possible completions instead of completing the longest common prefix).

get_help() str
Returns:

A help text which can be presented to the user.

This is generated by creating a formatter with create_formatter(), adding the help to it with add_help_to() and stripping trailing new line characters from the result of HelpFormatterWrapper.format_help().

Most likely you don’t want to override this method but add_help_to() instead.

get_help_attr_or_doc_str() str
Returns:

The help attribute or the doc string if help has not been set, cleaned up with inspect.cleandoc().

classmethod get_name() str
Returns:

The name which is used in config file to call this command.

If name is set it is returned as it is. Otherwise a name is generated based on the class name.

classmethod get_names() Iterator[str]
Returns:

Several alternative names which can be used in a config file to call this command.

The first one is always the return value of get_name(). If aliases is set it’s items are yielded afterwards.

If one of the returned items is the empty string this class is the default command and run() will be called if an undefined command is encountered.

help: str

A description which may be used by an in-app help. If this is not set get_help() uses the doc string instead.

name: str

The name which is used in the config file to call this command. Use an empty string to define a default command which is used if an undefined command is encountered. If this is not set get_name() returns the name of this class in lower case letters and underscores replaced by hyphens.

quote_path(path: str) str
abstract run(cmd: Sequence[str]) None

Process one line which has been read from a config file

Raises:
save(writer: FormattedWriter, **kw: Unpack[SaveKwargs]) None

Implement this method if you want calls to this command to be written by ConfigFile.save().

If you implement this method write a section heading with writer.write_heading('Heading') if should_write_heading is true. If this command writes several sections then write a heading for every section regardless of should_write_heading.

Write as many calls to this command as necessary to the config file in order to create the current state with writer.write_command('...'). Write comments or help with writer.write_lines('...').

There is the config_file attribute (which was passed to the constructor) which you can use to:

You probably don’t need the comment character ConfigFile.COMMENT because writer automatically comments out everything except for FormattedWriter.write_command().

The default implementation does nothing.

should_write_heading: bool = False

If a config file contains only a single section it makes no sense to write a heading for it. This attribute is set by ConfigFile.save_to_writer() if there are several commands which implement the save() method. If you implement save() and this attribute is set then save() should write a section header. If save() writes several sections it should always write the headings regardless of this attribute.

ui_notifier: UiNotifier

The UiNotifier of config_file

class confattr.configfile.ConfigFileWriter(f: TextIO | None, prefix: str)

Bases: TextIOWriter

write_command(cmd: str) None

Write a config file command.

write_heading(lvl: SectionLevel, heading: str) None

Write a heading.

This object should not add an indentation depending on the section because if the indentation is increased the line width should be decreased in order to keep the line wrapping consistent. Wrapping lines is handled by confattr.utils.HelpFormatter, i.e. before the text is passed to this object. It would be possible to use argparse.RawTextHelpFormatter instead and handle line wrapping on a higher level but that would require to understand the help generated by argparse in order to know how far to indent a broken line. One of the trickiest parts would probably be to get the indentation of the usage right. Keep in mind that the term “usage” can differ depending on the language settings of the user.

Parameters:
  • lvl – How to format the heading

  • heading – The heading

write_line(line: str) None

Write a single line of documentation. line may not contain a newline. If line is empty it does not need to be prefixed with a comment character. Empty lines should be dropped if no other lines have been written before.

confattr.configfile.DEFAULT_COMMAND = ''

If the name or an alias of ConfigFileCommand is this value that command is used by ConfigFile.parse_split_line() if an undefined command is encountered.

class confattr.configfile.FormattedWriter

Bases: ABC

abstract write_command(cmd: str) None

Write a config file command.

abstract write_heading(lvl: SectionLevel, heading: str) None

Write a heading.

This object should not add an indentation depending on the section because if the indentation is increased the line width should be decreased in order to keep the line wrapping consistent. Wrapping lines is handled by confattr.utils.HelpFormatter, i.e. before the text is passed to this object. It would be possible to use argparse.RawTextHelpFormatter instead and handle line wrapping on a higher level but that would require to understand the help generated by argparse in order to know how far to indent a broken line. One of the trickiest parts would probably be to get the indentation of the usage right. Keep in mind that the term “usage” can differ depending on the language settings of the user.

Parameters:
  • lvl – How to format the heading

  • heading – The heading

abstract write_line(line: str) None

Write a single line of documentation. line may not contain a newline. If line is empty it does not need to be prefixed with a comment character. Empty lines should be dropped if no other lines have been written before.

write_lines(text: str) None

Write one or more lines of documentation.

class confattr.configfile.HelpWriter(f: TextIO | None)

Bases: TextIOWriter

write_command(cmd: str) None

Write a config file command.

write_heading(lvl: SectionLevel, heading: str) None

Write a heading.

This object should not add an indentation depending on the section because if the indentation is increased the line width should be decreased in order to keep the line wrapping consistent. Wrapping lines is handled by confattr.utils.HelpFormatter, i.e. before the text is passed to this object. It would be possible to use argparse.RawTextHelpFormatter instead and handle line wrapping on a higher level but that would require to understand the help generated by argparse in order to know how far to indent a broken line. One of the trickiest parts would probably be to get the indentation of the usage right. Keep in mind that the term “usage” can differ depending on the language settings of the user.

Parameters:
  • lvl – How to format the heading

  • heading – The heading

write_line(line: str) None

Write a single line of documentation. line may not contain a newline. If line is empty it does not need to be prefixed with a comment character. Empty lines should be dropped if no other lines have been written before.

class confattr.configfile.Include(config_file: ConfigFile)

Bases: ConfigFileArgparseCommand

Load another config file.

This is useful if a config file is getting so big that you want to split it up or if you want to have different config files for different use cases which all include the same standard config file to avoid redundancy or if you want to bind several commands to one key which executes one command with ConfigFile.parse_line().

aliases: tuple[str, ...] | list[str]

Alternative names which can be used in the config file.

config_file: ConfigFile

The ConfigFile that has been passed to the constructor. It determines for example the notification_level and the available commands.

get_completions_for_action(action: Action | None, start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
help: str

A description which may be used by an in-app help. If this is not set get_help() uses the doc string instead.

help_config_id = '\n\tBy default the loaded config file starts with which ever config id is currently active.\n\tThis is useful if you want to use the same values for several config ids:\n\tWrite the set commands without a config id to a separate config file and include this file for every config id where these settings shall apply.\n\n\tAfter the include the config id is reset to the config id which was active at the beginning of the include\n\tbecause otherwise it might lead to confusion if the config id is changed in the included config file.\n\t'
init_parser(parser: ArgumentParser) None
Parameters:

parser – The parser to add arguments to. This is the same object like parser.

This is an abstract method which must be implemented by subclasses. Use ArgumentParser.add_argument() to add arguments to parser.

name: str

The name which is used in the config file to call this command. Use an empty string to define a default command which is used if an undefined command is encountered. If this is not set get_name() returns the name of this class in lower case letters and underscores replaced by hyphens.

run_parsed(args: Namespace) None

This is an abstract method which must be implemented by subclasses.

ui_notifier: UiNotifier

The UiNotifier of config_file

class confattr.configfile.Message(notification_level: NotificationLevel, message: str | BaseException, file_name: str | None = None, line_number: int | None = None, line: str = '')

Bases: object

A message which should be displayed to the user. This is passed to the callback of the user interface which has been registered with ConfigFile.set_ui_callback().

If you want full control how to display messages to the user you can access the attributes directly. Otherwise you can simply convert this object to a str, e.g. with str(msg). I recommend to use different colors for different values of notification_level.

ENVIRONMENT_VARIABLES = 'environment variables'

The value of file_name while loading environment variables.

file_name: str | None

The name of the config file which has caused this message. If this equals ENVIRONMENT_VARIABLES it is not a file but the message has occurred while reading the environment variables. This is None if ConfigFile.parse_line() is called directly, e.g. when parsing the input from a command line.

format_file_name() str
Returns:

A header including the file_name if the file_name is different from the last time this function has been called or an empty string otherwise

format_file_name_msg_line() str
Returns:

The concatenation of the return values of format_file_name() and format_msg_line()

format_msg_line() str

The return value includes the attributes message, line_number and line if they are set.

line: str

The line where the message occurred. This is an empty str if there is no line, e.g. when loading environment variables.

line_number: int | None

The number of the line in the config file. This is None if file_name is not a file name.

property lvl: NotificationLevel

An abbreviation for notification_level

message: str | BaseException

The string or exception which should be displayed to the user

notification_level: NotificationLevel

The importance of this message. I recommend to display messages of different importance levels in different colors. ConfigFile does not output messages which are less important than the notification_level setting which has been passed to it’s constructor.

classmethod reset() None

If you are using format_file_name_msg_line() or __str__() you must call this method when the widget showing the error messages is cleared.

exception confattr.configfile.MultipleParseExceptions(exceptions: Sequence[ParseException])

Bases: Exception

This is raised by ConfigFileCommand implementations in order to communicate that multiple errors have occured on the same line. Is caught in ConfigFile.

class confattr.configfile.NotificationLevel(value)

Bases: SortedEnum

An enumeration.

ERROR = 'error'
INFO = 'info'
descending: bool = False
exception confattr.configfile.ParseException

Bases: Exception

This is raised by ConfigFileCommand implementations and functions passed to check_config_id in order to communicate an error in the config file like invalid syntax or an invalid value. Is caught in ConfigFile.

class confattr.configfile.SaveKwargs

Bases: TypedDict

comments: bool
config_instances: Iterable[Config[Any] | DictConfig[Any, Any]]
ignore: Iterable[Config[Any] | DictConfig[Any, Any]] | None
no_multi: bool
class confattr.configfile.SectionLevel(value)

Bases: SortedEnum

An enumeration.

SECTION = 'section'

Is used to separate different commands in ConfigFile.write_help() and ConfigFileCommand.save()

SUB_SECTION = 'sub-section'

Is used for subsections in ConfigFileCommand.save() such as the “data types” section in the help of the set command

descending: bool = False
class confattr.configfile.Set(config_file: ConfigFile)

Bases: ConfigFileCommand

usage: set key1=val1 [key2=val2 …] \

set key [=] val

Change the value of a setting.

In the first form set takes an arbitrary number of arguments, each argument sets one setting. This has the advantage that several settings can be changed at once. That is useful if you want to bind a set command to a key and process that command with ConfigFile.parse_line() if the key is pressed.

In the second form set takes two arguments, the key and the value. Optionally a single equals character may be added in between as third argument. This has the advantage that key and value are separated by one or more spaces which can improve the readability of a config file.

KEY_VAL_SEP = '='

The separator which is used between a key and it’s value

add_config_help(formatter: HelpFormatterWrapper, instance: Config[Any]) None
add_help_for_data_types(formatter: HelpFormatterWrapper, config_instances: Iterable[Config[object]]) None
add_help_to(formatter: HelpFormatterWrapper) None

Add the return value of get_help_attr_or_doc_str() to formatter.

aliases: tuple[str, ...] | list[str]

Alternative names which can be used in the config file.

config_file: ConfigFile

The ConfigFile that has been passed to the constructor. It determines for example the notification_level and the available commands.

format_value(instance: Config[Any], config_id: ConfigId | None) str
Parameters:
  • instance – The config value to be saved

  • config_id – Which value to be written in case of a MultiConfig, should be None for a normal Config instance

Returns:

A str representation to be written to the config file

Convert the value of the Config instance into a str with Config.format_value().

get_completions(cmd: Sequence[str], argument_pos: int, cursor_pos: int, *, in_between: bool, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
Parameters:
  • cmd – The line split into arguments (including the name of this command as cmd[0])

  • argument_pos – The index of the argument which shall be completed. Please note that this can be one bigger than cmd is long if the line ends on a space and the cursor is behind that space. In that case in_between is true.

  • cursor_pos – The index inside of the argument where the cursor is located. This is undefined and should be ignored if in_between is true. The input from the start of the argument to the cursor should be used to filter the completions. The input after the cursor can be ignored.

  • in_between – If true: The cursor is between two arguments, before the first argument or after the last argument. argument_pos refers to the next argument, argument_pos-1 to the previous argument. cursor_pos is undefined.

  • start_of_line – The first return value. If cmd[argument_pos] has a pattern like key=value you can append key= to this value and return only completions of value as second return value.

  • end_of_line – The third return value.

Returns:

start of line, completions, end of line. completions is a list of possible completions for the word where the cursor is located. If completions is an empty list there are no completions available and the user input should not be changed. This should be displayed by a user interface in a drop down menu. The start of line is everything on the line before the completions. The end of line is everything on the line after the completions. In the likely case that the cursor is at the end of the line the end of line is an empty str. start of line and end of line should be the beginning and end of line but they may contain minor changes in order to keep quoting feasible.

get_completions_for_key(start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
get_completions_for_ranger_style_arg(cmd: Sequence[str], argument_pos: int, start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
get_completions_for_value(key: str, start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
get_completions_for_vim_style_arg(cmd: Sequence[str], argument_pos: int, start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
get_data_type_name_to_help_map(config_instances: Iterable[Config[object]]) dict[str, str]
Parameters:

config_instances – All config values to be saved

Returns:

A dictionary containing the type names as keys and the help as values

The returned dictionary contains the help for all data types except enumerations which occur in config_instances. The help is gathered from the help attribute of the type or the str registered with set_help_for_type(). The help is cleaned up with inspect.cleandoc().

get_help_for_data_types(config_instances: Iterable[Config[object]]) str
help: str

A description which may be used by an in-app help. If this is not set get_help() uses the doc string instead.

help_for_types = {<class 'str'>: 'A text. If it contains spaces it must be wrapped in single or double quotes.', <class 'int'>: "\t\t\tAn integer number in python 3 syntax, as decimal (e.g. 42), hexadecimal (e.g. 0x2a), octal (e.g. 0o52) or binary (e.g. 0b101010).\n\t\t\tLeading zeroes are not permitted to avoid confusion with python 2's syntax for octal numbers.\n\t\t\tIt is permissible to group digits with underscores for better readability, e.g. 1_000_000.", <class 'float'>: 'A floating point number in python syntax, e.g. 23, 1.414, -1e3, 3.14_15_93.'}

Help for data types. This is used by get_help_for_data_types(). Change this with set_help_for_type().

is_vim_style(cmd: Sequence[str]) bool

cmd has one of two possible styles: - vim inspired: set takes an arbitrary number of arguments, each argument sets one setting. Is handled by set_multiple(). - ranger inspired: set takes two arguments, the key and the value. Optionally a single equals character may be added in between as third argument. Is handled by set_with_spaces().

Returns:

true if cmd has a vim inspired style, false if cmd has a ranger inspired style

iter_config_instances_to_be_saved(**kw: Unpack[SaveKwargs]) Iterator[Config[object]]
Parameters:
  • config_instances – The settings to consider

  • ignore – Skip these settings

Iterate over all given config_instances and expand all DictConfig instances into the Config instances they consist of. Sort the resulting list if config_instances is not a list or a tuple. Yield all Config instances which are not (directly or indirectly) contained in ignore and where Config.wants_to_be_exported() returns true.

name: str

The name which is used in the config file to call this command. Use an empty string to define a default command which is used if an undefined command is encountered. If this is not set get_name() returns the name of this class in lower case letters and underscores replaced by hyphens.

parse_key_and_set_value(key: str, value: str) None

Find the corresponding Config instance for key and call set_value() with the return value of parse_value().

Raises:

ParseException – if key is invalid or if parse_value() or set_value() raises a ValueError

parse_value(instance: Config[T2], value: str) T2

Parse a value to the data type of a given setting by calling instance.parse_value(value)

run(cmd: Sequence[str]) None

Call set_multiple() if the first argument contains KEY_VAL_SEP otherwise set_with_spaces().

Raises:

ParseException – if something is wrong (no arguments given, invalid syntax, invalid key, invalid value)

save(writer: FormattedWriter, **kw: Unpack[SaveKwargs]) None
Parameters:
  • writer – The file to write to

  • no_multi (bool) – If true: treat MultiConfig instances like normal Config instances and only write their default value. If false: Separate MultiConfig instances and print them once for every MultiConfig.config_ids.

  • comments (bool) – If false: don’t write help for data types

Iterate over all Config instances with iter_config_instances_to_be_saved(), split them into normal Config and MultiConfig and write them with save_config_instance(). But before that set last_name to None (which is used by write_config_help()) and write help for data types based on get_help_for_data_types().

save_config_instance(writer: FormattedWriter, instance: Config[object], config_id: ConfigId | None, **kw: Unpack[SaveKwargs]) None
Parameters:
  • writer – The file to write to

  • instance – The config value to be saved

  • config_id – Which value to be written in case of a MultiConfig, should be None for a normal Config instance

  • comments (bool) – If true: call write_config_help()

Convert the Config instance into a value str with format_value(), wrap it in quotes if necessary with config_file.quote() and write it to writer.

classmethod set_help_for_type(t: type[object], help_text: str) None

get_help_for_data_types() is used by save() and get_help(). Usually it uses the help attribute of the class. But if the class does not have a help attribute or if you want a different help text you can set the help with this method.

Parameters:
set_multiple(cmd: Sequence[str]) None

Process one line of the format set key=value [key2=value2 ...]

Raises:

MultipleParseExceptions – if something is wrong (invalid syntax, invalid key, invalid value)

set_value(instance: Config[T2], value: T2) None

Assign value to :paramref`instance` by calling Config.set_value() with ConfigFile.config_id of config_file. Afterwards call UiNotifier.show_info().

set_with_spaces(cmd: Sequence[str]) None

Process one line of the format set key [=] value

Raises:

ParseException – if something is wrong (invalid syntax, invalid key, invalid value)

ui_notifier: UiNotifier

The UiNotifier of config_file

write_config_help(writer: FormattedWriter, instance: Config[Any], *, group_dict_configs: bool = True) None
Parameters:
  • writer – The output to write to

  • instance – The config value to be saved

Write a comment which explains the meaning and usage of this setting based on Config.format_allowed_values_or_type() and Config.help.

Use last_name to write the help only once for all Config instances belonging to the same DictConfig instance.

class confattr.configfile.TextIOWriter(f: TextIO | None)

Bases: FormattedWriter

write_line_raw(line: str) None
class confattr.configfile.UiNotifier(config_file: ConfigFile, notification_level: Config[NotificationLevel] | NotificationLevel = NotificationLevel.ERROR)

Bases: object

Most likely you will want to load the config file before creating the UI (user interface). But if there are errors in the config file the user will want to know about them. This class takes the messages from ConfigFile and stores them until the UI is ready. When you call set_ui_callback() the stored messages will be forwarded and cleared.

This object can also filter the messages. ConfigFile calls show_info() every time a setting is changed. If you load an entire config file this can be many messages and the user probably does not want to see them all. Therefore this object drops all messages of NotificationLevel.INFO by default. Pass notification_level to the constructor if you don’t want that.

property notification_level: NotificationLevel

Ignore messages that are less important than this level.

set_ui_callback(callback: Callable[[Message], None]) None

Call callback for all messages which have been saved by show() and clear all saved messages afterwards. Save callback for show() to call.

show(notification_level: NotificationLevel, msg: str | BaseException, *, ignore_filter: bool = False) None

If a callback for the user interface has been registered with set_ui_callback() call that callback. Otherwise save the message so that set_ui_callback() can forward the message when set_ui_callback() is called.

Parameters:
  • notification_level – The importance of the message

  • msg – The message to be displayed on the user interface

  • ignore_filter – If true: Show the message even if notification_level is smaller then the UiNotifier.notification_level.

show_error(msg: str | BaseException, *, ignore_filter: bool = False) None

Call show() with NotificationLevel.ERROR.

show_info(msg: str, *, ignore_filter: bool = False) None

Call show() with NotificationLevel.INFO.

class confattr.configfile.UnknownCommand(config_file: ConfigFile)

Bases: ConfigFileCommand

name: str = ''

The name which is used in the config file to call this command. Use an empty string to define a default command which is used if an undefined command is encountered. If this is not set get_name() returns the name of this class in lower case letters and underscores replaced by hyphens.

run(cmd: Sequence[str]) None

Process one line which has been read from a config file

Raises: