diff configmix/config.py @ 314:043a6412be3c

Implemented new access methods .getvarl() and .getvarl_s
author Franz Glasner <fzglas.hg@dom66.de>
date Wed, 05 May 2021 01:32:07 +0200
parents 035b42a224ed
children 98490375d90c
line wrap: on
line diff
--- a/configmix/config.py	Thu Apr 29 08:43:15 2021 +0200
+++ b/configmix/config.py	Wed May 05 01:32:07 2021 +0200
@@ -64,12 +64,37 @@
     _TEXTTYPE = type(u(""))
     _STARTTOK = u(b"{{")
     _ENDTOK = u(b"}}")
+    _HIER_SEPARATOR = u(b'.')
     _NS_SEPARATOR = u(b':')
     _FILTER_SEPARATOR = u(b'|')
     _STARTTOK_REF = _STARTTOK + REF_NAMESPACE + _NS_SEPARATOR
     _ENDTOK_REF = _ENDTOK
     _DOT = u(b'.')
 
+    def getvarl(self, *names, default=_MARKER, namespace=None):
+        """Get a variable where the hierarchy is given in `names` as sequence
+        and the namespace is given in `namespace`.
+
+        No variable interpolation is done and no filters are applied.
+
+        """
+        try:
+            if not namespace:
+                lookupfn = self._lookupvar
+            else:
+                if namespace == REF_NAMESPACE:
+                    lookupfn = self._lookupref
+                else:
+                    lookupfn = lookup_varns(namespace)
+            varvalue = lookupfn(*names)
+        except KeyError:
+            if default is _MARKER:
+                raise KeyError("Variable %r not found" % (names,))
+            else:
+                return default
+        else:
+            return varvalue
+
     def getvar(self, varname, default=_MARKER):
         """Get a variable of the form ``[ns:][[key1.]key2.]name`` - including
         variables from other namespaces.
@@ -78,22 +103,31 @@
 
         """
         varns, varname = self._split_ns(varname)
+        if not varns:
+            varnameparts = varname.split(self._HIER_SEPARATOR)
+        else:
+            varnameparts = (varname,)
+        return self.getvarl(*varnameparts, namespace=varns)
+
+    def getvarl_s(self, *names, default=_MARKER, namespace=None):
+        """Get a variable - including variables from other namespaces.
+
+        `names` and `namespace` are interpreted as in
+        :meth:`.getvarl`. But variables will be interpolated
+        recursively within the variable values and filters are
+        applied.
+
+        For more details see chapter :ref:`variable-interpolation`.
+
+        """
         try:
-            if not varns:
-                lookupfn = self._lookupvar
-            else:
-                if varns == REF_NAMESPACE:
-                    lookupfn = self._lookupref
-                else:
-                    lookupfn = lookup_varns(varns)
-            varvalue = lookupfn(varname)
+            obj = self.getvarl(*names, namespace=namespace)
+            return self.substitute_variables_in_obj(obj)
         except KeyError:
             if default is _MARKER:
-                raise KeyError("Variable %r not found" % varname)
+                raise
             else:
                 return default
-        else:
-            return varvalue
 
     def getvar_s(self, varname, default=_MARKER):
         """Get a variable - including variables from other namespaces.
@@ -114,23 +148,48 @@
             else:
                 return default
 
+    def getintvarl_s(self, *names, default=_MARKER, namespace=None):
+        """Get a (possibly substituted) variable and coerce text to a
+        number.
+
+        """
+        s = self.getvarl_s(*names, default=default, namespace=namespace)
+        if isinstance(s, self._TEXTTYPE):
+            return int(s, 0)
+        else:
+            return s
+
     def getintvar_s(self, varname, default=_MARKER):
         """Get a (possibly substituted) variable and coerce text to a
         number.
 
         """
-        s = self.getvar_s(varname, default)
+        s = self.getvar_s(varname, default=default)
         if isinstance(s, self._TEXTTYPE):
             return int(s, 0)
         else:
             return s
 
+    def getboolvarl_s(self, *names, default=_MARKER, namespace=None):
+        """Get a (possibly substituted) variable and convert text to a
+        boolean
+
+        """
+        s = self.getvarl_s(*names, default=default, namespace=namespace)
+        if isinstance(s, self._TEXTTYPE):
+            sl = s.strip().lower()
+            if sl not in self._BOOL_CVT:
+                raise ValueError("Not a boolean: %r" % s)
+            return self._BOOL_CVT[sl]
+        else:
+            return s
+
     def getboolvar_s(self, varname, default=_MARKER):
         """Get a (possibly substituted) variable and convert text to a
         boolean
 
         """
-        s = self.getvar_s(varname, default)
+        s = self.getvar_s(varname, default=default)
         if isinstance(s, self._TEXTTYPE):
             sl = s.strip().lower()
             if sl not in self._BOOL_CVT:
@@ -145,6 +204,17 @@
         u('0'): False, u('no'): False, u('false'): False, u('off'): False
     }
 
+    def getfloatvarl_s(self, *names, default=_MARKER, namespace=None):
+        """Get a (possibly substituted) variable and convert text to a
+        float
+
+        """
+        s = self.getvarl_s(*names, default=default, namespace=namespace)
+        if isinstance(s, self._TEXTTYPE):
+            return float(s)
+        else:
+            return s
+
     def getfloatvar_s(self, varname, default=_MARKER):
         """Get a (possibly substituted) variable and convert text to a
         float
@@ -170,24 +240,24 @@
         else:
             return (nameparts[0].rstrip(), nameparts[1:], )
 
-    def _lookupvar(self, key, default=_MARKER):
-        """Lookup a variable.
+    def _lookupvar(self, *names, default=_MARKER):
+        """Lookup a variable within a hierarchy.
 
-        If no default is given an unexisting `key` raises a `KeyError`
+        If no default is given an unexisting `name` raises a `KeyError`
         else `default` is returned.
         """
-        parts = key.split('.')
         try:
-            v = self.expand_if_reference(self[parts[0]])
-            for p in parts[1:]:
+            v = self.expand_if_reference(self[names[0]])
+            for p in names[1:]:
                 v = self.expand_if_reference(v[p])
         except TypeError:
             raise KeyError(
                 "Configuration variable %r not found"
-                "(missing intermediate keys?)" % key)
+                "(missing intermediate keys?)" % (names,))
         except KeyError:
             if default is _MARKER:
-                raise KeyError("Configuration variable %r not found" % key)
+                raise KeyError(
+                    "Configuration variable %r not found" % (names,))
             else:
                 return default
         return v