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 thanln_split
is long if the line ends on a space or a comment and the cursor is behind/in that space/comment. In that casein_between
is true.
- i0: int
The index in
line
where the argument having the cursor starts (inclusive) or the start of the next argument ifin_between
is true
- i1: int
The index in
line
where the current word ends (exclusive) or the end of the previous argument ifin_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, show_line_always: bool = True)
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. AMessage
with a priority lower than this value is not passed to the callback registered withset_ui_callback()
.appname¶ – The name of the application, required for generating the path of the config file if you use
load()
orsave()
and as prefix of environment variable namesauthorname¶ – The name of the developer of the application, on MS Windows useful for generating the path of the config file if you use
load()
orsave()
config_instances¶ – The Config instances to load or save, defaults to
Config.instances
commands¶ – The commands (as subclasses of
ConfigFileCommand
orConfigFileArgparseCommand
) allowed in this config file, if this isNone
: use the return value ofConfigFileCommand.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 aParseException
if the config id is invalid.enable_config_ids¶ – see
enable_config_ids
. If None: Choose True or False automatically based oncheck_config_id
and the existence ofMultiConfig
/MultiDictConfig
show_line_always¶ – If false: when calling
UiNotifier.show()
context_line
andcontext_line_number
are concatenated to the message if both are set. Ifcontext_line_number
is not set it is assumed that the line comes from a command line interface where the user just entered it and it is still visible so there is no need to print it again. Ifshow_line_always
is true (the default)context_line
is concatenated even ifcontext_line_number
is not set. That is useful when you useparse_line()
to parse a command which has been assigned to a keyboard shortcut.
- COMMENT = '#'
- COMMENT_PREFIXES = ('"', '#')
- ENTER_GROUP_PREFIX = '['
- ENTER_GROUP_SUFFIX = ']'
- ITEM_SEP = ','
How to separete several element in a collection (list, set, dict)
- KEY_SEP = ':'
How to separate key and value in a dict
- command_dict: dict[str, confattr.configfile.ConfigFileCommand]
A mapping from the name to the object for all commands that are available in this config file. If a command has
aliases
every alias appears in this mapping, too. Usecommands
instead if you want to iterate over all available commands. This is generated in the constructor based oncommands
if it is given or based on the return value ofConfigFileCommand.get_command_types()
otherwise. Note that you are passing a sequence of types as argument but this attribute contains the instantiated objects.
- commands: list[confattr.configfile.ConfigFileCommand]
A list of all commands that are available in this config file. This is generated in the constructor based on
commands
if it is given or based on the return value ofConfigFileCommand.get_command_types()
otherwise. Note that you are passing a sequence of types as argument but this attribute contains the instantiated objects. In contrast tocommand_dict
this list contains every command only once.
- config_directory: str | None = None
Override the config directory which is returned by
iter_user_site_config_paths()
. You should set either this attribute orconfig_path
in your tests withmonkeypatch.setattr()
. If the environment variableAPPNAME_CONFIG_DIRECTORY
is set this attribute is set to it’s value in the constructor (whereAPPNAME
is the value which is passed asappname
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 inload_file()
.
- config_name = 'config'
The name of the config file used by
iter_config_paths()
. Can be changed with the environment variableAPPNAME_CONFIG_NAME
(whereAPPNAME
is the value which is passed asappname
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 orconfig_directory
in your tests withmonkeypatch.setattr()
. If the environment variableAPPNAME_CONFIG_PATH
is set this attribute is set to it’s value in the constructor (whereAPPNAME
is the value which is passed asappname
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 isNone
ifparse_line()
is called directly (e.g. the input from a command line is parsed).
- context_line_number: int | None = None
The number of the line which is currently parsed. This is
None
ifcontext_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 forMultiConfig
instances can be set)
- enter_group(line: str) bool
Check if
line
starts a new group and setconfig_id
if it does. Callparse_error()
ifcheck_config_id()
raises aParseException
.
- env_variables: list[str]
Contains the names of the environment variables for
config_path
,config_directory
andconfig_name
—in capital letters and prefixed withenvprefix
.
- 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 ofappname
toget_env_name()
and appending an underscore.
- expand_config_match(m: Match[str]) str
- Parameters:
m¶ – A match of
reo_config
, group 1 is theConfig.key
possibly including a!conversion
or a:format_spec
- Returns:
The expanded form of the setting or
'%'
if group 1 is empty- Raises:
ParseException – If
key
,!conversion
or:format_spec
is invalid
This is based on the Python Format String Syntax.
field_name
is thekey
.!conversion
is one of::format_spec
depends on theConfig.type
, see the Python Format Specification Mini-Language.List()
,Set()
andDict()
implementexpand_value()
so that you can access specific items. Ifexpand_value()
raises anException
it is caught and reraised as aParseException
.
- expand_env_match(m: Match[str]) str
- Parameters:
m¶ – A match of
reo_env
, group 1 is the name of the environment variable possibly including one of the following expansion features- Returns:
The expanded form of the environment variable
Supported are the following parameter expansion features as defined by POSIX, except that word is not expanded:
${parameter:-word}
/${parameter-word}
: Use Default Values. If parameter is unset (or empty), word shall be substituted; otherwise, the value of parameter shall be substituted.${parameter:=word}
/${parameter=word}
: Assign Default Values. If parameter is unset (or empty), word shall be assigned to parameter. In all cases, the final value of parameter shall be substituted.${parameter:?[word]}
/${parameter?[word]}
: Indicate Error If Unset (or Empty). If parameter is unset (or empty), aParseException
shall be raised with word as message or a default error message if word is omitted. Otherwise, the value of parameter shall be substituted.${parameter:+word}
/${parameter+word}
: Use Alternative Value. If parameter is unset (or empty), empty shall be substituted; otherwise, the expansion of word shall be substituted.
In the patterns above, if you use a
:
it is checked whether parameter is unset or empty. If:
is not used the check is only true if parameter is unset, empty is treated as a valid value.
- find_arg(line: str, ln_split: list[str], cursor_pos: int) ArgPos
This is an internal method used by
get_completions_command()
- format_any_value(type: AbstractFormatter[T2], value: T2) str
- 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 beNone
for a normalConfig
instance
- Returns:
A str representation to be written to the config file
Convert the value of the
Config
instance into a str withformat_any_value()
.
- 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
andXDG_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:
- 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 fromline
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 fromline
and will prepend it to the first item of the return value.
- get_completions_for_expand(start: str, *, start_of_line: str, end_of_line: str) tuple[bool, str, list[str], str]
- get_completions_for_expand_config(start: str, *, start_of_line: str, end_of_line: str) tuple[bool, str, list[str], str]
- get_completions_for_expand_env(start: str, *, start_of_line: str, end_of_line: str) tuple[bool, str, list[str], str]
- get_completions_for_file_name(start: str, *, relative_to: str, include: ~collections.abc.Callable[[str, str], bool] | None = None, exclude: str | None = None, match: ~collections.abc.Callable[[str, str, str], bool] = <function ConfigFile.<lambda>>, 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 directoryexclude¶ – A regular expression. The default value
None
is interpreted differently depending on theplatform.platform()
. ForWindows
it’s$none
so that nothing is excluded. For others it’s^\.
so that hidden files and directories are excluded.include¶ – A function which takes the path and file name as arguments and returns whether this file/directory is a valid completion.
match¶ – A callable to decide if a completion fits for the given start. It takes three arguments: the parent directory, the file/directory name and the start. If it returns true the file/direcotry is added to the list of possible completions. The default is
lambda path, name, start: name.startswith(start)
.
- Returns:
All files and directories that start with
start
and do not matchexclude
. Directories are appended withos.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_env_name(key: str) str
Convert the key of a setting to the name of the corresponding environment variable.
- 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 withinspect.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.
- 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()
withConfigFile.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()
unlessconfig_directory
has been set. Ifconfig_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 inenv_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 callset_ui_callback()
after this method without loosing any messages.- Parameters:
fn¶ – The file name of the config file (absolute or relative path)
- 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
orMultipleParseExceptions
is caught. This method compiles the given information into an error message and callsself.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 anyParseException
orMultipleParseExceptions
is raised catch it and callparse_error()
.- Returns:
False if a
ParseException
orMultipleParseExceptions
has been caught, True if no exception has been caught
- parse_value(instance: Config[T2], value: str, *, raw: bool) T2
- Parameters:
Parse a value to the data type of a given setting by calling
parse_value_part()
- parse_value_part(config: Config[Any], t: AbstractFormatter[T2], value: str) T2
Parse a value to the given data type.
- quote(val: str) str
Quote a value if necessary so that it will be interpreted as one argument.
The default implementation calls
readable_quote()
.
- reo_config = re.compile('%([^%]*)%')
- reo_env = re.compile('\\$\\{([^{}]*)\\}')
- save(if_not_existing: bool = False, **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 aset
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.
if_not_existing¶ – Do not overwrite the file if it is already existing.
- 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 callingsave_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 allConfigFileCommand
objects incommands
and do for each of them:set
should_write_heading
toTrue
ifgetattr(cmd.save, 'implemented', True)
is true for two or more of those commands or toFalse
otherwisecall
save()
- 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
- show_line_always: bool
If this is true
ui_notifier.show()
concatenatescontext_line
to the message even ifcontext_line_number
is not set.
- 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 usesargparse
to make parsing and providing help easier.You must implement the class method
init_parser()
to add the arguments toparser
. Instead ofrun()
you must implementrun_parsed()
. You don’t need to add a usage or the possible arguments to the doc string asargparse
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
andConfigFileCommand.save()
like forConfigFileCommand
.- 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_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 casein_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 likekey=value
you can appendkey=
to this value and return only completions ofvalue
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.
- 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
format_help()
onparser
. The return value ofget_help_attr_or_doc_str()
has been passed asdescription
to the constructor ofArgumentParser
, thereforehelp
/the doc string are included as well.
- 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
-
This is an abstract method which must be implemented by subclasses. Use
ArgumentParser.add_argument()
to add arguments toparser
.
- parser: ArgumentParser
The argument parser which is passed to
init_parser()
for adding arguments and which is used inrun()
- run(cmd: Sequence[str]) None
Process one line which has been read from a config file
- Raises:
ParseException – if there is an error in the line (e.g. invalid syntax)
MultipleParseExceptions – if there are several errors in the same line
- 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 whenConfigFile
is loading a file. Subclasses should contain a doc string so thatget_help()
can provide a description to the user. Subclasses may set thename
andaliases
attributes to change the output ofget_name()
andget_names()
.All subclasses are remembered and can be retrieved with
get_command_types()
. They are instantiated in the constructor ofConfigFile
.- add_help_to(formatter: HelpFormatterWrapper) None
Add the return value of
get_help_attr_or_doc_str()
toformatter
.
- config_file: ConfigFile
The
ConfigFile
that has been passed to the constructor. It determines for example thenotification_level
and the availablecommands
.
- create_formatter() HelpFormatterWrapper
- classmethod delete_command_type(cmd_type: type[confattr.configfile.ConfigFileCommand]) None
Delete
cmd_type
so that it is not returned anymore byget_command_types()
and that it’s name can be used by another command. Do nothing ifcmd_type
has already been deleted.
- classmethod get_command_types() tuple[type[confattr.configfile.ConfigFileCommand], ...]
- Returns:
All subclasses of
ConfigFileCommand
which have not been deleted withdelete_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 casein_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 likekey=value
you can appendkey=
to this value and return only completions ofvalue
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.
- 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 withadd_help_to()
and stripping trailing new line characters from the result ofHelpFormatterWrapper.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 ifhelp
has not been set, cleaned up withinspect.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()
. Ifaliases
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.
- abstract run(cmd: Sequence[str]) None
Process one line which has been read from a config file
- Raises:
ParseException – if there is an error in the line (e.g. invalid syntax)
MultipleParseExceptions – if there are several errors in the same line
- 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')
ifshould_write_heading
is true. If this command writes several sections then write a heading for every section regardless ofshould_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 withwriter.write_lines('...')
.There is the
config_file
attribute (which was passed to the constructor) which you can use to:quote arguments with
ConfigFile.quote()
You probably don’t need the comment character
ConfigFile.COMMENT
becausewriter
automatically comments out everything except forFormattedWriter.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 thesave()
method. If you implementsave()
and this attribute is set thensave()
should write a section header. Ifsave()
writes several sections it should always write the headings regardless of this attribute.
- ui_notifier: UiNotifier
The
UiNotifier
ofconfig_file
- class confattr.configfile.ConfigFileWriter(f: TextIO | None, prefix: str)
Bases:
TextIOWriter
- 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 useargparse.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.
- confattr.configfile.DEFAULT_COMMAND = ''
If the name or an alias of
ConfigFileCommand
is this value that command is used byConfigFile.parse_split_line()
if an undefined command is encountered.
- class confattr.configfile.Echo(config_file: ConfigFile)
Bases:
ConfigFileArgparseCommand
Display a message.
Settings and environment variables are expanded like in the value of a set command.
- 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 casein_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 likekey=value
you can appendkey=
to this value and return only completions ofvalue
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.
- init_parser(parser: ArgumentParser) None
-
This is an abstract method which must be implemented by subclasses. Use
ArgumentParser.add_argument()
to add arguments toparser
.
- class confattr.configfile.FormattedWriter
Bases:
ABC
- 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 useargparse.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.
- class confattr.configfile.Help(config_file: ConfigFile)
Bases:
ConfigFileArgparseCommand
Display help.
- get_completions_for_action(action: Action | None, start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
- init_parser(parser: ArgumentParser) None
-
This is an abstract method which must be implemented by subclasses. Use
ArgumentParser.add_argument()
to add arguments toparser
.
- class confattr.configfile.HelpWriter(f: TextIO | None)
Bases:
TextIOWriter
- 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 useargparse.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.
- 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().
- get_completions_for_action(action: Action | None, start: str, *, start_of_line: str, end_of_line: str) tuple[str, list[str], str]
- 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
-
This is an abstract method which must be implemented by subclasses. Use
ArgumentParser.add_argument()
to add arguments toparser
.
- class confattr.configfile.Message(notification_level: NotificationLevel, message: str | BaseException, file_name: str | None = None, line_number: int | None = None, line: str = '', no_context: bool = False)
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 ofnotification_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 ifConfigFile.parse_line()
is called directly, e.g. when parsing the input from a command line.
- format_file_name_msg_line() str
- Returns:
The concatenation of the return values of
format_file_name()
andformat_msg_line()
- format_msg_line() str
The return value includes the attributes
message
,line_number
andline
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 thenotification_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 inConfigFile
.
- class confattr.configfile.NotificationLevel(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Bases:
SortedEnum
- ERROR = 'error'
- INFO = 'info'
- exception confattr.configfile.ParseException
Bases:
Exception
This is raised by
ConfigFileCommand
implementations and functions passed tocheck_config_id
in order to communicate an error in the config file like invalid syntax or an invalid value. Is caught inConfigFile
.
- class confattr.configfile.SectionLevel(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
Bases:
SortedEnum
- SECTION = 'section'
Is used to separate different commands in
ConfigFile.write_help()
andConfigFileCommand.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
- class confattr.configfile.Set(config_file: ConfigFile)
Bases:
ConfigFileCommand
- usage: set [–raw] key1=val1 [key2=val2 …] \
set [–raw] 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.
You can use the value of another setting with %other.key% or an environment variable with ${ENV_VAR}. If you want to insert a literal percent character use two of them: %%. You can disable expansion of settings and environment variables with the –raw flag.
- FLAGS_RAW = ('-r', '--raw')
- 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()
toformatter
.
- 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 casein_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 likekey=value
you can appendkey=
to this value and return only completions ofvalue
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.
- 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 thehelp
attribute of the type orPrimitive.get_help()
. The help is cleaned up withinspect.cleandoc()
.
- 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 byset_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 byset_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]]
-
Iterate over all given
config_instances
and expand allDictConfig
instances into theConfig
instances they consist of. Sort the resulting list ifconfig_instances
is not alist
or atuple
. Yield allConfig
instances which are not (directly or indirectly) contained inignore
and whereConfig.wants_to_be_exported()
returns true.
- last_name: str | None
A temporary variable used in
write_config_help()
to prevent repeating the help of severalConfig
instances belonging to the sameDictConfig
. It is reset insave()
.
- parse_key_and_set_value(key: str, value: str) None
Find the corresponding
Config
instance forkey
and callset_value()
with the return value ofconfig_file.parse_value()
.- Raises:
ParseException – if key is invalid or if
config_file.parse_value()
orset_value()
raises aValueError
- raw = False
- run(cmd: Sequence[str]) None
Call
set_multiple()
if the first argument containsKEY_VAL_SEP
otherwiseset_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 normalConfig
instances and only write their default value. If false: SeparateMultiConfig
instances and print them once for everyMultiConfig.config_ids
.comments¶ (bool) – If false: don’t write help for data types
Iterate over all
Config
instances withiter_config_instances_to_be_saved()
, split them into normalConfig
andMultiConfig
and write them withsave_config_instance()
. But before that setlast_name
to None (which is used bywrite_config_help()
) and write help for data types based onget_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 beNone
for a normalConfig
instancecomments¶ (bool) – If true: call
write_config_help()
Convert the
Config
instance into a value str withconfig_file.format_value()
, wrap it in quotes if necessary withconfig_file.quote()
and write it towriter
.
- 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 callingConfig.set_value()
withConfigFile.config_id
ofconfig_file
. Afterwards callUiNotifier.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)
- write_config_help(writer: FormattedWriter, instance: Config[Any], *, group_dict_configs: bool = True) None
-
Write a comment which explains the meaning and usage of this setting based on
instance.type.get_description()
andConfig.help
.Use
last_name
to write the help only once for allConfig
instances belonging to the sameDictConfig
instance.
- class confattr.configfile.TextIOWriter(f: TextIO | None)
Bases:
FormattedWriter
- 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 callset_ui_callback()
the stored messages will be forwarded and cleared.This object can also filter the messages.
ConfigFile
callsshow_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 ofNotificationLevel.INFO
by default. Passnotification_level
to the constructor if you don’t want that.- Parameters:
config_file¶ – Is used to add context information to messages, to which file and to which line a message belongs.
notification_level¶ – Messages which are less important than this notification level will be ignored. I recommend to pass a
Config
instance so that users can decide themselves what they want to see.
- 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 byshow()
and clear all saved messages afterwards. Savecallback
forshow()
to call.
- show(notification_level: NotificationLevel, msg: str | BaseException, *, ignore_filter: bool = False, no_context: 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 thatset_ui_callback()
can forward the message whenset_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 theUiNotifier.notification_level
.no_context¶ – If true: don’t show line and line number.
- show_error(msg: str | BaseException, *, ignore_filter: bool = False) None
Call
show()
withNotificationLevel.ERROR
.
- 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:
ParseException – if there is an error in the line (e.g. invalid syntax)
MultipleParseExceptions – if there are several errors in the same line