Add type hints to the config reading functions

Return a TypedDict from _read_config() and stop reusing variables for different types, so that mypy can check the config values. No change in behaviour.
This commit is contained in:
Fuxino
2026-10-14 08:33:45 +02:00
parent d803790c1a
commit 1fb0513467
+33 -29
View File
@@ -18,7 +18,7 @@ from __future__ import annotations
import sys
import os
import pwd
from typing import Callable, List, Optional, ParamSpec, TypeVar, Union
from typing import Callable, List, Optional, ParamSpec, TypedDict, TypeVar, Union
import warnings
from functools import wraps
from shutil import rmtree, which
@@ -766,8 +766,8 @@ def _expand_home(path: str, user: str) -> str:
return os.path.expanduser(path)
def _expand_inputs(inputs, user: Optional[str] = None):
expanded_inputs = []
def _expand_inputs(inputs: List[str], user: Optional[str] = None) -> List[str]:
expanded_inputs: List[str] = []
for i in inputs:
if i == '':
@@ -790,8 +790,30 @@ def _expand_inputs(inputs, user: Optional[str] = None):
return expanded_inputs
def _read_config(config_file, user: Optional[str] = None):
config_args = {'inputs': None,
class ConfigArgs(TypedDict):
"""Values read from the configuration file"""
inputs: Optional[List[str]]
output: Optional[str]
exclude: Optional[List[str]]
keep: int
ssh_host: Optional[str]
ssh_user: Optional[str]
ssh_keyfile: Optional[str]
remote_sudo: bool
numeric_ids: bool
def _get_bool(config: configparser.ConfigParser, key: str) -> bool:
# Empty values (as in the example config) count as false
if config.get('server', key, fallback='').strip() == '':
return False
return config.getboolean('server', key)
def _read_config(config_file: str, user: Optional[str] = None) -> ConfigArgs:
config_args: ConfigArgs = {'inputs': None,
'output': None,
'exclude': None,
'keep': -1,
@@ -823,29 +845,15 @@ def _read_config(config_file, user: Optional[str] = None):
section = 'default'
inputs = config.get(section, 'inputs')
inputs = [i.strip() for i in inputs.split(',')]
inputs = _expand_inputs(inputs, user)
inputs = list(set(inputs))
config_args['inputs'] = inputs
config_args['inputs'] = list(set(_expand_inputs([i.strip() for i in inputs.split(',')], user)))
# '~' is expanded later, since for remote backups it refers to the home on the server
config_args['output'] = config.get(section, 'backup_dir')
try:
exclude = config.get(section, 'exclude')
exclude = [e.strip() for e in exclude.split(',') if e.strip() != '']
except configparser.NoOptionError:
exclude = []
exclude = config.get(section, 'exclude', fallback='')
config_args['exclude'] = [e.strip() for e in exclude.split(',') if e.strip() != '']
config_args['exclude'] = exclude
try:
keep = config.getint(section, 'keep')
except configparser.NoOptionError:
keep = -1
config_args['keep'] = keep
config_args['keep'] = config.getint(section, 'keep', fallback=-1)
# Read host and user separately, so that a missing one is reported instead of silently
# disabling remote backup. Empty values count as not set
@@ -854,12 +862,8 @@ def _read_config(config_file, user: Optional[str] = None):
config_args['ssh_keyfile'] = config.get('server', 'ssh_keyfile', fallback='').strip() or None
# Empty values (as in the example config) count as false
for key in ['remote_sudo', 'numeric_ids']:
if config.get('server', key, fallback='').strip() == '':
config_args[key] = False
else:
config_args[key] = config.getboolean('server', key)
config_args['remote_sudo'] = _get_bool(config, 'remote_sudo')
config_args['numeric_ids'] = _get_bool(config, 'numeric_ids')
return config_args