##// END OF EJS Templates
Apply JSON config updates recursively
Thomas Kluyver -
Show More
@@ -9,6 +9,25 b' from tornado import web'
9 9
10 10 from ...base.handlers import IPythonHandler, json_errors
11 11
12 def recursive_update(target, new):
13 """Recursively update one dictionary using another.
14
15 None values will delete their keys.
16 """
17 for k, v in new.items():
18 if isinstance(v, dict):
19 if k not in target:
20 target[k] = {}
21 recursive_update(target[k], v)
22 if not target[k]:
23 # Prune empty subdicts
24 del target[k]
25
26 elif v is None:
27 target.pop(k, None)
28
29 else:
30 target[k] = v
12 31
13 32 class ConfigHandler(IPythonHandler):
14 33 SUPPORTED_METHODS = ('GET', 'PUT', 'PATCH')
@@ -46,11 +65,8 b' class ConfigHandler(IPythonHandler):'
46 65 else:
47 66 section = {}
48 67
49 for k, v in self.get_json_body().items():
50 if v is None:
51 section.pop(k, None)
52 else:
53 section[k] = v
68 update = self.get_json_body()
69 recursive_update(section, update)
54 70
55 71 with io.open(filename, 'w', encoding='utf-8') as f:
56 72 json.dump(section, f)
@@ -1,5 +1,5 b''
1 1 # coding: utf-8
2 """Test the kernel specs webservice API."""
2 """Test the config webservice API."""
3 3
4 4 import json
5 5
@@ -32,7 +32,7 b' class ConfigAPI(object):'
32 32 return self._req('PATCH', section, json.dumps(values))
33 33
34 34 class APITest(NotebookTestBase):
35 """Test the kernelspec web service API"""
35 """Test the config web service API"""
36 36 def setUp(self):
37 37 self.config_api = ConfigAPI(self.base_url())
38 38
@@ -46,18 +46,22 b' class APITest(NotebookTestBase):'
46 46 self.assertEqual(r.json(), sample)
47 47
48 48 def test_modify(self):
49 sample = {'foo': 'bar', 'baz': 73}
49 sample = {'foo': 'bar', 'baz': 73,
50 'sub': {'a': 6, 'b': 7}, 'sub2': {'c': 8}}
50 51 self.config_api.set('example', sample)
51 52
52 53 r = self.config_api.modify('example', {'foo': None, # should delete foo
53 54 'baz': 75,
54 55 'wib': [1,2,3],
56 'sub': {'a': 8, 'b': None, 'd': 9},
57 'sub2': {'c': None} # should delete sub2
55 58 })
56 59 self.assertEqual(r.status_code, 204)
57 60
58 61 r = self.config_api.get('example')
59 62 self.assertEqual(r.status_code, 200)
60 self.assertEqual(r.json(), {'baz': 75, 'wib': [1,2,3]})
63 self.assertEqual(r.json(), {'baz': 75, 'wib': [1,2,3],
64 'sub': {'a': 8, 'd': 9}})
61 65
62 66 def test_get_unknown(self):
63 67 # We should get an empty config dictionary instead of a 404
General Comments 0
You need to be logged in to leave comments. Login now