From 66ac22ecf6a1925f2f57dc390b4251e2c89603a8 Mon Sep 17 00:00:00 2001 From: Meir Tseitlin Date: Fri, 14 May 2021 14:10:52 -0500 Subject: [PATCH] allow removing items or sources from config --- confuse/core.py | 31 +++++++++++++++++++++++++++++++ test/test_views.py | 24 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/confuse/core.py b/confuse/core.py index c63b1a9..fe37ffd 100644 --- a/confuse/core.py +++ b/confuse/core.py @@ -87,6 +87,11 @@ def add(self, value): """ raise NotImplementedError + def remove(self, obj): + """Remove source or key from config + """ + raise NotImplementedError + def set(self, value): """*Override* the value for this configuration view. The specified value is added as the highest-priority configuration @@ -136,6 +141,11 @@ def __setitem__(self, key, value): """ self.set({key: value}) + def __delitem__(self, key): + """Remove value from config by key. + """ + self.remove(key) + def __contains__(self, key): return self[key].exists() @@ -439,6 +449,22 @@ def __init__(self, sources): def add(self, obj): self.sources.append(ConfigSource.of(obj)) + def remove(self, obj): + """Remove source or key from configuration + """ + if isinstance(obj, ConfigSource): + if obj.default: + raise ConfigError(u'Cannot remove default source') + self.sources.remove(obj) + elif isinstance(obj, util.STRING): + for source in self.sources: + if isinstance(source, ConfigSource) and obj in source: + del source[obj] + else: + raise ConfigError(u'Unrecognized obj {0}'.format( + obj + )) + def set(self, value): self.sources.insert(0, ConfigSource.of(value)) @@ -514,6 +540,11 @@ def set(self, value): def add(self, value): self.parent.add({self.key: value}) + def remove(self, key): + value = self.parent[self.key].get() + del value[key] + self.set(value) + def root(self): return self.parent.root() diff --git a/test/test_views.py b/test/test_views.py index 860633c..0bb12d0 100644 --- a/test/test_views.py +++ b/test/test_views.py @@ -241,6 +241,30 @@ def test_override_list_index(self): self.assertEqual(config['foo'][1].get(), 'bar') +class DeleteTest(unittest.TestCase): + + def test_remove(self): + config = _root({'foo': 'bar', 'qux': 'baz'}) + config.remove('foo') + with self.assertRaises(confuse.NotFoundError): + config['foo'].get() + self.assertEqual(set(config.keys()), set(['qux'])) + + def test_del(self): + config = _root({'foo': 'bar', 'qux': 'baz'}) + del config['foo'] + with self.assertRaises(confuse.NotFoundError): + config['foo'].get() + self.assertEqual(set(config.keys()), set(['qux'])) + + def test_nested_remove(self): + config = _root({'foo': {'bar': {'x': 'y', 'a': 'b'}, 'qux': 'baz'}}) + del config['foo']['bar']['x'] + self.assertEqual(config['foo']['bar'].get(), {'a': 'b'}) + config['foo']['bar'].remove('a') + self.assertEqual(config['foo']['bar'].get(), {}) + + class BuildNamespaceDictTests(unittest.TestCase): def test_pure_dicts(self): config = {'foo': {'bar': 1}}