Mercurial > hgrepos > Python > libs > ConfigMix
diff configmix/config.py @ 320:98490375d90c
Allow variable name quoting to be used in .getvar() and .getvar_s() and references
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Thu, 06 May 2021 09:45:51 +0200 |
| parents | 043a6412be3c |
| children | 7a0f3c256cf4 |
line wrap: on
line diff
--- a/configmix/config.py Wed May 05 23:12:01 2021 +0200 +++ b/configmix/config.py Thu May 06 09:45:51 2021 +0200 @@ -28,7 +28,7 @@ from urlparse import urlsplit from .variables import lookup_varns, lookup_filter -from .compat import u +from .compat import u, uchr from .constants import REF_NAMESPACE @@ -70,6 +70,7 @@ _STARTTOK_REF = _STARTTOK + REF_NAMESPACE + _NS_SEPARATOR _ENDTOK_REF = _ENDTOK _DOT = u(b'.') + _QUOTE = u(b'%') def getvarl(self, *names, default=_MARKER, namespace=None): """Get a variable where the hierarchy is given in `names` as sequence @@ -104,7 +105,7 @@ """ varns, varname = self._split_ns(varname) if not varns: - varnameparts = varname.split(self._HIER_SEPARATOR) + varnameparts = [self.unquote(vp) for vp in varname.split(self._HIER_SEPARATOR)] else: varnameparts = (varname,) return self.getvarl(*varnameparts, namespace=varns) @@ -365,3 +366,46 @@ else: value = filterfn(self, value) return value + + @classmethod + def quote(klass, s): + """Quote a key to protect all dangerous chars: ``%``, ``.``, ``:`` + and ``|`` + + """ + qc = klass._QUOTE + s = s.replace(qc, qc + "x25") + s = s.replace(klass._DOT, qc + "x2e") + s = s.replace(klass._NS_SEPARATOR, qc + "x3a") + return s.replace(klass._FILTER_SEPARATOR, qc + "x7c") + + @classmethod + def unquote(klass, s): + """Unquote the content of `s`: handle all patterns ``%xXX``, + ``%uXXXX`` or `%UXXXXXXXX`` + + """ + if klass._QUOTE not in s: + return s + res = [] + parts = s.split(klass._QUOTE) + res.append(parts[0]) + for p in parts[1:]: + if p.startswith(u(b'x')): + if len(p) < 3: + raise ValueError("quote syntax: length too small") + res.append(uchr(int(p[1:3], 16))) + res.append(p[3:]) + elif p.startswith(u(b'u')): + if len(p) < 5: + raise ValueError("quote syntax: length too small") + res.append(uchr(int(p[1:5], 16))) + res.append(p[5:]) + elif p.startswith(u(b'U')): + if len(p) < 9: + raise ValueError("quote syntax: length too small") + res.append(uchr(int(p[1:9], 16))) + res.append(p[9:]) + else: + raise ValueError("unknown quote syntax string: {}".format(s)) + return ''.join(res)
