changeset 666:0eff8441c4b9 v0.21

Implement iteration support that yields properly jailed configurations for each container item
author Franz Glasner <fzglas.hg@dom66.de>
date Fri, 03 Jun 2022 02:17:12 +0200
parents 9f0842a942b2
children f5d1679896d0
files CHANGES.txt configmix/config.py tests/test.py
diffstat 3 files changed, 58 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES.txt	Fri Jun 03 01:38:04 2022 +0200
+++ b/CHANGES.txt	Fri Jun 03 02:17:12 2022 +0200
@@ -20,6 +20,12 @@
   path string representation like ``~NNN~``
 
 - **[feature]**
+  Implement methods :py:meth:`configmix.config.Configuration.iter_jailed` and
+  :py:meth:`configmix.config._JailedConfiguration.iter_jailed` that yield
+  properly jailed configurations for container items (for lists and dicts,
+  no sets).
+  
+- **[feature]**
   Allow to enable and disable the internal caching
 
 - **[feature]**
--- a/configmix/config.py	Fri Jun 03 01:38:04 2022 +0200
+++ b/configmix/config.py	Fri Jun 03 02:17:12 2022 +0200
@@ -1099,6 +1099,14 @@
             jc.rebind(self)
         return jc
 
+    def iter_jailed(self, rootpath=None, root=None):
+        """Iterator that yields properly jailed configurations.
+
+        `rootpath` or `root` must refer to a `list` or `dict` container.
+
+        """
+        return self.jailed(rootpath=rootpath, root=root).iter_jailed()
+
 
 class _JailedConfiguration(CoercingMethodsMixin):
 
@@ -1282,6 +1290,27 @@
         """Length support for containers"""
         return len(self._base.getvarl_s(*self._path))
 
+    def iter_jailed(self):
+        """Iteration support for containers which yields properly jailed
+        sub-jails.
+
+        Only supported for type `list` or type `dict` jails.
+
+        """
+        container = self._base.getvarl(*self._path)
+        if isinstance(container, dict):
+            for k in container:
+                yield self.jailed(rootpath=(k, ))
+        elif isinstance(container, list):
+            len_container = len(container)
+            idx = 0
+            while idx < len_container:
+                yield self.jailed(rootpath=(idx, ))
+                idx += 1
+        else:
+            raise TypeError(
+                "jailed iterators only supported for lists and dicts")
+
     if PY2:
 
         def __nonzero__(self):
--- a/tests/test.py	Fri Jun 03 01:38:04 2022 +0200
+++ b/tests/test.py	Fri Jun 03 02:17:12 2022 +0200
@@ -1946,6 +1946,29 @@
             self.assertEqual((u"the-list", idx), jcfg2._path)
             self.assertEqual(u"the-list.~%d~." % (idx, ), jcfg2._pathstr)
 
+    def test_direct_iter_jailed(self):
+        cfg = configmix.load(os.path.join(
+            TESTDATADIR, "index-access-for-jails.yml"))
+        testidx = -1
+        for jcfg2 in cfg.iter_jailed(rootpath=(u"the-list", )):
+            testidx += 1
+            self.assertEqual(1, len(jcfg2))
+            self.assertEqual(testidx, jcfg2.getvarl_s(u"entry"))
+            self.assertEqual((u"the-list", testidx), jcfg2._path)
+            self.assertEqual(u"the-list.~%d~." % (testidx, ), jcfg2._pathstr)
+
+    def test_iter_jailed(self):
+        cfg = configmix.load(os.path.join(
+            TESTDATADIR, "index-access-for-jails.yml"))
+        jcfg = cfg.jailed(rootpath=(u"the-list",))
+        testidx = -1
+        for jcfg2 in jcfg.iter_jailed():
+            testidx += 1
+            self.assertEqual(1, len(jcfg2))
+            self.assertEqual(testidx, jcfg2.getvarl_s(u"entry"))
+            self.assertEqual((u"the-list", testidx), jcfg2._path)
+            self.assertEqual(u"the-list.~%d~." % (testidx, ), jcfg2._pathstr)
+
     def test_negative_index_jail_access(self):
         cfg = configmix.load(os.path.join(
             TESTDATADIR, "index-access-for-jails.yml"))