Mercurial > hgrepos > Python > libs > ConfigMix
changeset 395:0b3ffc34fa5c
Begin a jailed configuration with access to a sub-tree of the original configuration
| author | Franz Glasner <f.glasner@feldmann-mg.com> |
|---|---|
| date | Thu, 18 Nov 2021 18:30:59 +0100 |
| parents | e05195ee869d |
| children | a50f8fb16b05 |
| files | CHANGES.txt configmix/config.py tests/test.py |
| diffstat | 3 files changed, 181 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES.txt Wed Nov 10 09:43:15 2021 +0100 +++ b/CHANGES.txt Thu Nov 18 18:30:59 2021 +0100 @@ -12,6 +12,13 @@ Pre-1.0 Series -------------- +not yet (not yet) +~~~~~~~~~~~~~~~~~ + +- **[feature]** Jailed Configuration with + :py:meth:`~configmix.config.Configuration.jailed` + + 0.16.1 (2021-11-10) ~~~~~~~~~~~~~~~~~~~
--- a/configmix/config.py Wed Nov 10 09:43:15 2021 +0100 +++ b/configmix/config.py Thu Nov 18 18:30:59 2021 +0100 @@ -118,7 +118,7 @@ Quoting of anything in `paths` is *not* needed and wrong. - """ + """ default = kwds.pop("default", _MARKER) for path in paths: if isinstance(path, (list, tuple)): @@ -648,3 +648,61 @@ else: raise ValueError("unknown quote syntax string: {}".format(s)) return ''.join(res) + + def jailed(self, rootpath=None, root=None): + """Return a "jailed" configuration. + + """ + if rootpath is not None and root is not None: + raise ValueError("only one of `rootpath' or `root' can be given") + if rootpath is None and root is None: + raise ValueError("one of `rootpath' or `root' must be given") + if root is not None: + # convert to path + varns, varname = self._split_ns(root) + if varns: + raise ValueError( + "jailed configurations do not support namespaces") + rootpath = [ + self.unquote(p) for p in root.split( + self._HIER_SEPARATOR) + ] + + return _JailedConfiguration(self, *rootpath) + + +class _JailedConfiguration(object): + + """Chrooted into a subtree of the configuration -- no namespace support""" + + __slots__ = ("_base", "_path", "_pathstr" ) + + def __init__(self, config, *path): + super(_JailedConfiguration, self).__init__() + self._base = config + self._path = path + if path: + self._pathstr = \ + Configuration._HIER_SEPARATOR.join( + [Configuration.quote(p) for p in path]) \ + + Configuration._HIER_SEPARATOR + else: + self._pathstr = '' + # + # Early error out if the chroot does not exist but allow + # degenerated case if `self._path` is empty. + # + if self._path: + self._base.getvarl(*self._path) + + def getvarl(self, *path, **kwds): + return self._base.getvarl(*(self._path + path), **kwds) + + def getvarl_s(self, *path, **kwds): + return self._base.getvarl_s(*(self._path + path), **kwds) + + def getvar(self, varname, default=_MARKER): + return self._base.getvar(self._pathstr + varname, default=default) + + def getvar_s(self, varname, default=_MARKER): + return self._base.getvar_s(self._pathstr + varname, default=default)
--- a/tests/test.py Wed Nov 10 09:43:15 2021 +0100 +++ b/tests/test.py Thu Nov 18 18:30:59 2021 +0100 @@ -1157,5 +1157,120 @@ self.assertEqual("value", v) +class T08Jailed(unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + self._reset() + + def _reset(self): + configmix.clear_assoc() + for pat, fmode in configmix.DEFAULT_ASSOC: + configmix.set_assoc(pat, fmode) + + def test_root(self): + cfg = configmix.load(os.path.join(TESTDATADIR, "conf10.py")) + jcfg = cfg.jailed(root=u"tree1") + + self.assertTrue(jcfg.getvarl(u"tree2", u"key5")) + self.assertTrue(jcfg.getvarl_s(u"tree2", u"key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvarl(u"tree2", u"key4")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvarl_s(u"tree2", u"key4")) + + self.assertTrue(jcfg.getvar(u"tree2.key5")) + self.assertTrue(jcfg.getvar_s(u"tree2.key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvar(u"tree2.key4")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvar_s(u"tree2.key4")) + + def test_root2(self): + cfg = configmix.load(os.path.join(TESTDATADIR, "conf10.py")) + jcfg = cfg.jailed(root=u"tree1.tree2") + + self.assertTrue(jcfg.getvarl(u"key5")) + self.assertTrue(jcfg.getvarl_s(u"key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvarl(u"key4")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvarl_s(u"key4")) + + self.assertTrue(jcfg.getvar(u"key5")) + self.assertTrue(jcfg.getvar_s(u"key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvar(u"key4")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvar_s(u"key4")) + + def test_root_non_existing_raises(self): + cfg = configmix.load(os.path.join(TESTDATADIR, "conf10.py")) + self.assertRaises(KeyError, cfg.jailed, root=u"tree-non-existing") + + def test_rootpath(self): + cfg = configmix.load(os.path.join(TESTDATADIR, "conf10.py")) + jcfg = cfg.jailed(rootpath=[u"tree1"]) + + self.assertTrue(jcfg.getvarl(u"tree2", u"key5")) + self.assertTrue(jcfg.getvarl_s(u"tree2", u"key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvarl_s(u"tree2", u"key4")) + + self.assertTrue(jcfg.getvar(u"tree2.key5")) + self.assertTrue(jcfg.getvar_s(u"tree2.key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvar_s(u"tree2.key4")) + + def test_rootpath_non_existing_raises(self): + cfg = configmix.load(os.path.join(TESTDATADIR, "conf10.py")) + self.assertRaises( + KeyError, cfg.jailed, rootpath=[u"tree-non-existing"]) + + def test_root_empty(self): + cfg = configmix.load(os.path.join(TESTDATADIR, "conf10.py")) + jcfg = cfg.jailed(rootpath=u"") + + self.assertTrue(jcfg.getvarl(u"tree1", u"tree2", u"key5")) + self.assertTrue(jcfg.getvarl_s(u"tree1", u"tree2", u"key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvarl_s(u"tree1", u"tree2", u"key4")) + + self.assertTrue(jcfg.getvar(u"tree1.tree2.key5")) + self.assertTrue(jcfg.getvar_s(u"tree1.tree2.key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvar_s(u"tree1.tree2.key4")) + + def test_rootpath_empty(self): + cfg = configmix.load(os.path.join(TESTDATADIR, "conf10.py")) + jcfg = cfg.jailed(rootpath=tuple()) + + self.assertTrue(jcfg.getvarl(u"tree1", u"tree2", u"key5")) + self.assertTrue(jcfg.getvarl_s(u"tree1", u"tree2", u"key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvarl_s(u"tree1", u"tree2", u"key4")) + + self.assertTrue(jcfg.getvar(u"tree1.tree2.key5")) + self.assertTrue(jcfg.getvar_s(u"tree1.tree2.key5")) + self.assertEqual( + u"get this as `tree1.tree2.key4'", + jcfg.getvar_s(u"tree1.tree2.key4")) + + if __name__ == "__main__": unittest.main()
