Apply JSON config updates recursively

This commit is contained in:
Thomas Kluyver 2014-10-20 14:14:53 -07:00
parent 6786f86c63
commit 425d5a1c02
2 changed files with 29 additions and 9 deletions

View File

@ -9,6 +9,25 @@ from tornado import web
from ...base.handlers import IPythonHandler, json_errors
def recursive_update(target, new):
"""Recursively update one dictionary using another.
None values will delete their keys.
"""
for k, v in new.items():
if isinstance(v, dict):
if k not in target:
target[k] = {}
recursive_update(target[k], v)
if not target[k]:
# Prune empty subdicts
del target[k]
elif v is None:
target.pop(k, None)
else:
target[k] = v
class ConfigHandler(IPythonHandler):
SUPPORTED_METHODS = ('GET', 'PUT', 'PATCH')
@ -46,11 +65,8 @@ class ConfigHandler(IPythonHandler):
else:
section = {}
for k, v in self.get_json_body().items():
if v is None:
section.pop(k, None)
else:
section[k] = v
update = self.get_json_body()
recursive_update(section, update)
with io.open(filename, 'w', encoding='utf-8') as f:
json.dump(section, f)

View File

@ -1,5 +1,5 @@
# coding: utf-8
"""Test the kernel specs webservice API."""
"""Test the config webservice API."""
import json
@ -32,7 +32,7 @@ class ConfigAPI(object):
return self._req('PATCH', section, json.dumps(values))
class APITest(NotebookTestBase):
"""Test the kernelspec web service API"""
"""Test the config web service API"""
def setUp(self):
self.config_api = ConfigAPI(self.base_url())
@ -46,18 +46,22 @@ class APITest(NotebookTestBase):
self.assertEqual(r.json(), sample)
def test_modify(self):
sample = {'foo': 'bar', 'baz': 73}
sample = {'foo': 'bar', 'baz': 73,
'sub': {'a': 6, 'b': 7}, 'sub2': {'c': 8}}
self.config_api.set('example', sample)
r = self.config_api.modify('example', {'foo': None, # should delete foo
'baz': 75,
'wib': [1,2,3],
'sub': {'a': 8, 'b': None, 'd': 9},
'sub2': {'c': None} # should delete sub2
})
self.assertEqual(r.status_code, 204)
r = self.config_api.get('example')
self.assertEqual(r.status_code, 200)
self.assertEqual(r.json(), {'baz': 75, 'wib': [1,2,3]})
self.assertEqual(r.json(), {'baz': 75, 'wib': [1,2,3],
'sub': {'a': 8, 'd': 9}})
def test_get_unknown(self):
# We should get an empty config dictionary instead of a 404