From b766e8c9d6fb5f86abd32a8355687103b43ac4b3 Mon Sep 17 00:00:00 2001 From: Giulio Ungaretti Date: Fri, 10 Mar 2017 17:57:47 +0100 Subject: [PATCH] fix: Recursively update the configuration object Closes #519 --- qcodes/config/config.py | 45 +++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/qcodes/config/config.py b/qcodes/config/config.py index a69eb703ac8..767832efe35 100644 --- a/qcodes/config/config.py +++ b/qcodes/config/config.py @@ -1,3 +1,4 @@ +import collections import copy import json import logging @@ -122,19 +123,19 @@ def update_config(self): if os.path.isfile(self.home_file_name): home_config = self.load_config(self.home_file_name) - config.update(home_config) + config = update(config, home_config) self.validate(config, self.current_schema, self.schema_home_file_name) if os.path.isfile(self.env_file_name): env_config = self.load_config(self.env_file_name) - config.update(env_config) + config = update(config, env_config) self.validate(config, self.current_schema, self.schema_env_file_name) if os.path.isfile(self.cwd_file_name): cwd_config = self.load_config(self.cwd_file_name) - config.update(cwd_config) + config = update(config, cwd_config) self.validate(config, self.current_schema, self.schema_cwd_file_name) @@ -161,9 +162,7 @@ def validate(self, json_config=None, schema=None, extra_schema_path=None): # be overwritten new_user = json.load(f)["properties"]["user"] user = schema["properties"]['user'] - user["properties"].update( - new_user["properties"] - ) + user["properties"].update(new_user["properties"]) jsonschema.validate(json_config, schema) else: logger.warning(EMPTY_USER_SCHEMA.format(extra_schema_path)) @@ -232,11 +231,13 @@ def add(self, key, value, value_type=None, description=None, default=None): # update schema! schema_entry = {key: {"type": value_type}} if description is not None: - schema_entry = {key: { - "type": value_type, - "default": default, - "description": description} - } + schema_entry = { + key: { + "type": value_type, + "default": default, + "description": description + } + } # the schema is nested we only update properties of the user object user = self.current_schema['properties']["user"] user["properties"].update(schema_entry) @@ -336,12 +337,7 @@ def describe(self, name): # add cool description to docstring base_docstring = """{}.\nCurrent value: {}. Type: {}. Default: {}.""" - doc = base_docstring.format( - description, - val, - _type, - default - ) + doc = base_docstring.format(description, val, _type, default) return doc @@ -357,15 +353,14 @@ def __getattr__(self, name): def __repr__(self): old = super().__repr__() base = """Current values: \n {} \n Current path: \n {} \n {}""" - return base.format(self.current_config, - self.current_config_path, - old) + return base.format(self.current_config, self.current_config_path, old) class DotDict(dict): """ Wrapper dict that allows to get dotted attributes """ + def __init__(self, value=None): if value is None: pass @@ -403,3 +398,13 @@ def __deepcopy__(self, memo): # dot acces baby __setattr__ = __setitem__ __getattr__ = __getitem__ + + +def update(d, u): + for k, v in u.items(): + if isinstance(v, collections.Mapping): + r = update(d.get(k, {}), v) + d[k] = r + else: + d[k] = u[k] + return d