Mercurial > hgrepos > Python > libs > ConfigMix
changeset 679:aa39c1856de4
Begin "ref:" support for jails.
Currently jailed configurations do not work if the jail's root is
located at a substitution.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Fri, 09 Jun 2023 09:24:41 +0200 |
| parents | f39b96e2bb2a |
| children | e71f8bd50342 |
| files | configmix/config.py |
| diffstat | 1 files changed, 47 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/configmix/config.py Thu Jun 08 22:14:30 2023 +0200 +++ b/configmix/config.py Fri Jun 09 09:24:41 2023 +0200 @@ -939,6 +939,31 @@ raise ValueError("relative refs not supported") return self.getvar(pu.fragment) + def try_get_reference_uri(self, v): + """Check whether `v` is a configuration reference and -- if true -- + return the configuration path where the reference points to. + + If `v` is not a text type or not a reference return `None`. + + Does not check whether the referenced configuration object exists. + + :rtype: None or str + + """ + if not isinstance(v, _TEXTTYPE): + return None + if v.startswith(_STARTTOK_REF) and v.endswith(_ENDTOK_REF): + uri = v[len(_STARTTOK_REF):-len(_ENDTOK_REF)] + pu = urlsplit(uri) + if pu.scheme or pu.netloc or pu.path or pu.query: + raise ValueError("only fragment-only URIs are supported") + if not pu.fragment: + return _EMPTY_STR + if pu.fragment.startswith(_DOT): + raise ValueError("relative refs not supported") + return pu.fragment + return None + def substitute_variables_in_obj(self, obj): """Recursively expand variables in the object tree `obj`.""" ty = type(obj) @@ -1062,7 +1087,8 @@ value = filterfn(self, value) return value - def jailed(self, rootpath=None, root=None, bind_root=True): + def jailed(self, rootpath=None, root=None, + bind_root=True, resolve_ref=True): """Return a "jailed" configuration of the current configuration. :param rootpath: a sequence of strings (or objects) that shall @@ -1075,6 +1101,10 @@ creation of a jailed config you can set `bind_root` to `False`; otherwise use the default + :param bool resolve_ref: If `True` then the jail's root is checked + whether it is a reference. If it is a + reference then the jail is effectively rooted + where the reference points to. :return: a jailed (aka restricted) configuration :rtype: _JailedConfiguration @@ -1094,6 +1124,13 @@ raise ValueError( "jailed configurations do not support namespaces") rootpath = pathstr2path(root) + if resolve_ref: + while True: + target = self.getvarl(*rootpath) + target_uri = self.try_get_reference_uri(target) + if target_uri is None: + break + rootpath = pathstr2path(target_uri) jc = _JailedConfiguration(*rootpath) if bind_root: jc.rebind(self) @@ -1323,7 +1360,8 @@ """Map- and list-style evaluation in boolean context""" return bool(self._base.getvarl_s(*self._path)) - def jailed(self, rootpath=None, root=None, bind_root=True): + def jailed(self, rootpath=None, root=None, + bind_root=True, resolve_ref=True): """Return a "jailed" configuration that effectively is a subjail of the current jail @@ -1347,6 +1385,13 @@ new_rootpath = self._path + tuple(rootpath) else: new_rootpath = tuple(rootpath) + if resolve_ref: + while True: + target = self._base.getvarl(*new_rootpath) + target_uri = self._base.try_get_reference_uri(target) + if target_uri is None: + break + new_rootpath = pathstr2path(target_uri) sjc = _JailedConfiguration(*new_rootpath) if bind_root: sjc.rebind(self._base)
