zabgrab.adapters.configfiles

Config file discovery, loading and layering.

Layers, lowest to highest priority:

  1. built-in defaults (zabgrab.model.config.BUILTIN_DEFAULTS)

  2. system: /etc/zabgrab/config.toml (Windows: %PROGRAMDATA%)

  3. user: $XDG_CONFIG_HOME/zabgrab/config.toml, default ~/.config/... on Linux and macOS (Windows: %APPDATA% unless XDG_CONFIG_HOME is set)

  4. project: the nearest zabgrab.toml in the working directory or its parents, stopping at the home directory

  5. explicit: --config PATH / $ZABGRAB_CONFIG

--isolated skips layers 2-4.

Merge rules: each key in [defaults] is taken from the highest layer that sets it. Named entries (servers.X, templates.X) are replaced whole by higher layers.

zabgrab.adapters.configfiles.CONFIG_NAME

The file name of system and user config files.

Type:

str

zabgrab.adapters.configfiles.PROJECT_CONFIG_NAME

The file name of project config files.

Type:

str

zabgrab.adapters.configfiles.BUILTIN_SOURCE

The source label of built-in values.

Type:

str

zabgrab.adapters.configfiles.NAMED_SECTIONS

The tables whose entries are replaced whole by higher layers.

Type:

tuple of str

Functions

add_server(path, name, url)

Add [servers.NAME] to a config file, keeping its existing formatting.

add_template(path, name, table, *[, replace])

Add [templates.NAME] to a config file, keeping its existing formatting.

discover_layers(env, *[, explicit, isolated])

Find every config layer.

edit_hint(path, kind)

Get a hint telling the user how to edit a config file.

find_project_config(env)

Find the nearest zabgrab.toml in the working directory or its parents.

format_validation_errors(exc)

Describe a validation error for users.

load_config(layers)

Read, validate and merge config layers.

project_config_target(env)

Get where the project config is, or would be created.

read_config_file(path, *[, kind])

Read and validate a single config file.

set_server_url(path, name, url)

Change the URL of [servers.NAME] in a config file, keeping its formatting.

system_config_path(env)

Get the path of the system-wide config file.

user_config_path(env)

Get the path of the user's config file.

write_atomically(path, text)

Write a config file via a temporary file, so it's never left half-written.

Classes

ConfigLayer(kind, path, exists[, skipped])

One config layer and its file, if any.

Environment(variables, cwd, home, windows)

The parts of the process environment that affect config discovery.

LayerKind(*values)

Config layers, in increasing order of priority.

LoadedConfig(config, layers[, sources])

The merged config, plus where each part of it came from.

class zabgrab.adapters.configfiles.LayerKind(*values)[source]

Bases: StrEnum

Config layers, in increasing order of priority.

class zabgrab.adapters.configfiles.Environment(variables, cwd, home, windows)[source]

Bases: object

The parts of the process environment that affect config discovery.

Parameters:
variables

Environment variables.

Type:

mapping of str to str

cwd, home

The working and home directories.

Type:

Path

windows

Whether to use Windows locations.

Type:

bool

classmethod current()[source]

Get the running process’s environment.

Return type:

Environment

class zabgrab.adapters.configfiles.ConfigLayer(kind, path, exists, skipped=False)[source]

Bases: object

One config layer and its file, if any.

Parameters:
kind

Which layer.

Type:

LayerKind

path

Its file (None for built-in values, or no project file).

Type:

Path or None

exists

Whether the file exists.

Type:

bool

skipped

Whether --isolated skips it.

Type:

bool

property active: bool

Whether this layer contributes to the config.

property source: str

Label recorded as the source of values from this layer.

class zabgrab.adapters.configfiles.LoadedConfig(config, layers, sources=<factory>)[source]

Bases: object

The merged config, plus where each part of it came from.

Parameters:
config

The merged config.

Type:

Config

layers

Every layer, lowest priority first.

Type:

tuple of ConfigLayer

sources

Maps ("defaults", key), ("servers", name) and ("templates", name) to the source label of the layer that provided the value.

Type:

dict of tuple of str to str

source_of(*path)[source]

Get the source label of a [defaults] key or a named entry.

Parameters:

*path (str) – "defaults", key, "servers", name or "templates", name.

Returns:

str or None – The file path, "built-in", or None if nothing sets it.

Return type:

str | None

zabgrab.adapters.configfiles.system_config_path(env)[source]

Get the path of the system-wide config file.

Parameters:

env (Environment)

Return type:

Path

zabgrab.adapters.configfiles.user_config_path(env)[source]

Get the path of the user’s config file.

Parameters:

env (Environment)

Return type:

Path

zabgrab.adapters.configfiles.find_project_config(env)[source]

Find the nearest zabgrab.toml in the working directory or its parents.

The search stops before the home directory, so a file there is never treated as a project config.

Parameters:

env (Environment) – Where to start, and the home directory.

Returns:

Path or None – The project config file, if there is one.

Return type:

Path | None

zabgrab.adapters.configfiles.project_config_target(env)[source]

Get where the project config is, or would be created.

Parameters:

env (Environment)

Return type:

Path

zabgrab.adapters.configfiles.discover_layers(env, *, explicit=None, isolated=False)[source]

Find every config layer.

Parameters:
  • env (Environment) – Where to look.

  • explicit (Path, optional) – A config file given with --config or $ZABGRAB_CONFIG.

  • isolated (bool, optional) – Skip the system, user and project layers (--isolated).

Returns:

list of ConfigLayer – The layers, lowest priority first, including ones without a file.

Return type:

list[ConfigLayer]

zabgrab.adapters.configfiles.load_config(layers)[source]

Read, validate and merge config layers.

Each file is validated on its own first, so errors point at the file that caused them.

Parameters:

layers (iterable of ConfigLayer) – The layers, lowest priority first.

Returns:

LoadedConfig – The merged config and where each value came from.

Raises:

ConfigError – If a file can’t be read or is invalid, or an explicitly given file doesn’t exist.

Return type:

LoadedConfig

zabgrab.adapters.configfiles.read_config_file(path, *, kind=None)[source]

Read and validate a single config file.

Parameters:
  • path (Path) – The file.

  • kind (LayerKind, optional) – Its layer, for the hint on how to fix it.

Returns:

dict – The file’s contents, as parsed TOML.

Raises:

ConfigError – If the file can’t be read, isn’t valid TOML, or isn’t a valid config.

Return type:

dict[str, Any]

zabgrab.adapters.configfiles.edit_hint(path, kind)[source]

Get a hint telling the user how to edit a config file.

Parameters:
Return type:

str

zabgrab.adapters.configfiles.format_validation_errors(exc)[source]

Describe a validation error for users.

Parameters:

exc (pydantic.ValidationError) – The error.

Returns:

list of str – One line per problem, like templates.x.items[1]: unknown key 'nmae' (did you mean 'name'?).

Return type:

list[str]

zabgrab.adapters.configfiles.add_server(path, name, url)[source]

Add [servers.NAME] to a config file, keeping its existing formatting.

The file (and its directory) is created if needed.

Parameters:
  • path (Path) – The config file.

  • name (str) – The server’s name.

  • url (str) – The server’s URL.

Raises:

ConfigError – If the file can’t be parsed, already defines the server, or can’t be written.

Return type:

None

zabgrab.adapters.configfiles.add_template(path, name, table, *, replace=False)[source]

Add [templates.NAME] to a config file, keeping its existing formatting.

The file (and its directory) is created if needed.

Parameters:
  • path (Path) – The config file.

  • name (str) – The template’s name.

  • table (mapping) – The template’s settings, as config values (see zabgrab.services.templates.template_table()).

  • replace (bool, optional) – Replace a template with the same name (--force).

Returns:

str – The TOML of the template as written, for showing to the user.

Raises:

ConfigError – If the file can’t be parsed or written, or already defines the template and replace isn’t set.

Return type:

str

zabgrab.adapters.configfiles.set_server_url(path, name, url)[source]

Change the URL of [servers.NAME] in a config file, keeping its formatting.

Parameters:
  • path (Path) – The config file that defines the server.

  • name (str) – The server’s name.

  • url (str) – The new URL.

Raises:

ConfigError – If the file can’t be parsed or written, or doesn’t define the server.

Return type:

None

zabgrab.adapters.configfiles.write_atomically(path, text)[source]

Write a config file via a temporary file, so it’s never left half-written.

Parameters:
  • path (Path) – The file (created, with its directory, if needed).

  • text (str) – The new contents.

Raises:

ConfigError – If the file can’t be written.

Return type:

None