Repository: janehmueller/python-json-config

Issue:
When upserting a new value in a new subfield, the subfield is not added
E.g., we add value `x` to path `[foo, bar]` but `foo` does not exist yet. The subpath `foo` is not added and an error is thrown.

Discussion:

Patch:
diff --git a/python_json_config/config_node.py b/python_json_config/config_node.py
index 9879339..9fb07b3 100644
--- a/python_json_config/config_node.py
+++ b/python_json_config/config_node.py
@@ -126,6 +126,11 @@ class ConfigNode(object):
             else:
                 self.__node_dict[key] = value
         else:
+            if key not in self.__node_dict and upsert:
+                self.__node_dict[key] = ConfigNode({}, path=self.__path + [key])
+            elif key not in self.__node_dict:
+                raise RuntimeError(f"Updating not existing key {self.__path_for_key(key)}. To insert non existing keys"
+                                   f"set upsert=True.")
             self.get(key).update(path=path[1:], value=value, upsert=upsert)
 
     def merge_with_env_variables(self, prefix: Union[str, List[str]]):


Test patch:
diff --git a/tests/config_node/test_crud.py b/tests/config_node/test_crud.py
index 57d313f..503e4c1 100644
--- a/tests/config_node/test_crud.py
+++ b/tests/config_node/test_crud.py
@@ -81,7 +81,7 @@ def test_update(config_dict):
     assert node.key2.key4 == 1337
 
 
-def test_update_upsert():
+def test_upsert():
     node = ConfigNode({"key1": 1})
 
     with pytest.raises(AttributeError):
@@ -94,6 +94,26 @@ def test_update_upsert():
     assert node.key2 == "asd"
 
 
+def test_nested_update():
+    node = ConfigNode({"key1": 1})
+
+    with pytest.raises(AttributeError):
+        node.key2
+
+    with pytest.raises(RuntimeError):
+        node.update("key2.key3", "asd", upsert=False)
+
+
+def test_nested_upsert():
+    node = ConfigNode({"key1": 1})
+
+    with pytest.raises(AttributeError):
+        node.key2
+
+    node.update("key2.key3", "asd", upsert=True)
+    assert node.key2.key3 == "asd"
+
+
 def test_strict_access(config_dict):
     config = ConfigNode(config_dict,
                         strict_access=True,