The utils.update_config() and io.merge_mappings() (introduced in #981) do very similar things, recursively update a dictionary.
utils.update.config()
Recursively updates a dictionary (config) with values from a second dictionary or Namespace.
Converts base_dir and output_dir to Path via convert_path()
def update_config(config: dict, args: dict | Namespace) -> dict:
"""
Update the configuration with any arguments.
Parameters
----------
config : dict
Dictionary of configuration (typically read from YAML file specified with '-c/--config <filename>').
args : Namespace
Command line arguments.
Returns
-------
dict
Dictionary updated with command arguments.
"""
args = vars(args) if isinstance(args, Namespace) else args
config_keys = config.keys()
for arg_key, arg_value in args.items():
if isinstance(arg_value, dict):
update_config(config, arg_value)
else:
if arg_key in config_keys and arg_value is not None:
original_value = config[arg_key]
config[arg_key] = arg_value
LOGGER.debug(f"Updated config config[{arg_key}] : {original_value} > {arg_value} ")
if "base_dir" in config.keys():
config["base_dir"] = convert_path(config["base_dir"])
if "output_dir" in config.keys():
config["output_dir"] = convert_path(config["output_dir"])
return config
io.merge_mappings()
Recursively adds mappings if the value is a MutableMapping (i.e. dictionary)
If value isn't a MutableMapping its value updates that of the config.
def merge_mappings(map1: MutableMappingType, map2: MutableMappingType) -> MutableMappingType:
"""
Merge two mappings (dictionaries), with priority given to the second mapping.
Note: Using a Mapping should make this robust to any mapping type, not just dictionaries. MutableMapping was needed
as Mapping is not a mutable type, and this function needs to be able to change the dictionaries.
Parameters
----------
map1 : MutableMapping
First mapping to merge, with secondary priority.
map2 : MutableMapping
Second mapping to merge, with primary priority.
Returns
-------
dict
Merged dictionary.
"""
# Iterate over the second mapping
for key, value in map2.items():
# If the value is another mapping, then recurse
if isinstance(value, MutableMapping):
# If the key is not in the first mapping, add it as an empty dictionary before recursing
map1[key] = merge_mappings(map1.get(key, {}), value)
else:
# Else simply add / override the key value pair
map1[key] = value
return map1
It should be possible to combine these into a single function, avoiding duplication and simplifying the code base so
that a single call can be made to combine/update configurations.
The
utils.update_config()
andio.merge_mappings()
(introduced in #981) do very similar things, recursively update a dictionary.utils.update.config()
config
) with values from a second dictionary orNamespace
.base_dir
andoutput_dir
toPath
viaconvert_path()
io.merge_mappings()
value
is aMutableMapping
(i.e. dictionary)value
isn't aMutableMapping
its value updates that of the config.It should be possible to combine these into a single function, avoiding duplication and simplifying the code base so that a single call can be made to combine/update configurations.