Mercurial > hgrepos > Python > libs > ConfigMix
comparison configmix/config.py @ 539:9546d38cd3f8
Refactor: the parsing of the quoted and dot-separated path string is put into a function that handles also empty inputs properly
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Tue, 28 Dec 2021 17:28:19 +0100 |
| parents | be740ed67d16 |
| children | 33856ae1cc0b |
comparison
equal
deleted
inserted
replaced
| 538:e85d1eddf539 | 539:9546d38cd3f8 |
|---|---|
| 315 else: | 315 else: |
| 316 raise ValueError("unknown quote syntax string: {}".format(s)) | 316 raise ValueError("unknown quote syntax string: {}".format(s)) |
| 317 return _EMPTY_STR.join(res) | 317 return _EMPTY_STR.join(res) |
| 318 | 318 |
| 319 | 319 |
| 320 def pathstr2path(varname): | |
| 321 """Parse a dot-separated path string `varname` into a tuple of | |
| 322 unquoted path items | |
| 323 | |
| 324 :param str varname: The quoted and dot-separated path string | |
| 325 :return: The unquoted and parsed path items | |
| 326 :rtype: tuple | |
| 327 | |
| 328 Used e.g. by :meth:`~.Configuration.getvar`, | |
| 329 :meth:`~.Configuration.getvar_s` and :meth:`~.Configuration.jailed`. | |
| 330 | |
| 331 The returned value is suitable as input for | |
| 332 :meth:`~.Configuration.getvarl`, :meth:`~.Configuration.getvarl_s` and | |
| 333 friends. | |
| 334 | |
| 335 An empty `varname` returns an empty tuple. | |
| 336 | |
| 337 """ | |
| 338 # | |
| 339 # Because str.split yields a non-empty list for an empty string handle | |
| 340 # the empty string separately. | |
| 341 # | |
| 342 if varname: | |
| 343 return tuple([unquote(p) for p in varname.split(_HIER_SEPARATOR)]) | |
| 344 else: | |
| 345 return tuple() | |
| 346 | |
| 347 | |
| 320 class Configuration(CoercingMethodsMixin, _AttributeDict): | 348 class Configuration(CoercingMethodsMixin, _AttributeDict): |
| 321 | 349 |
| 322 """The configuration dictionary with attribute support or | 350 """The configuration dictionary with attribute support or |
| 323 variable substitution. | 351 variable substitution. |
| 324 | 352 |
| 495 See also :func:`.quote`. | 523 See also :func:`.quote`. |
| 496 | 524 |
| 497 """ | 525 """ |
| 498 varns, varname = self._split_ns(varname) | 526 varns, varname = self._split_ns(varname) |
| 499 if not varns: | 527 if not varns: |
| 500 if varname: | 528 return self.getvarl(*pathstr2path(varname), default=default) |
| 501 varnameparts = tuple([unquote(vp) | 529 else: |
| 502 for vp in varname.split(_HIER_SEPARATOR)]) | 530 return self.getvarl(varname, namespace=varns, default=default) |
| 503 else: | |
| 504 varnameparts = tuple() | |
| 505 else: | |
| 506 varnameparts = (varname,) | |
| 507 return self.getvarl(*varnameparts, namespace=varns, default=default) | |
| 508 | 531 |
| 509 def getkeys(self, varname): | 532 def getkeys(self, varname): |
| 510 """Yield all the keys of a variable value. | 533 """Yield all the keys of a variable value. |
| 511 | 534 |
| 512 :rtype: A generator | 535 :rtype: A generator |
| 612 | 635 |
| 613 For more details see chapter :ref:`variable-interpolation`. | 636 For more details see chapter :ref:`variable-interpolation`. |
| 614 | 637 |
| 615 """ | 638 """ |
| 616 varns, varname = self._split_ns(varname) | 639 varns, varname = self._split_ns(varname) |
| 617 if not varns: | |
| 618 if varname: | |
| 619 varnameparts = tuple([unquote(vp) | |
| 620 for vp in varname.split(_HIER_SEPARATOR)]) | |
| 621 else: | |
| 622 varnameparts = tuple() | |
| 623 else: | |
| 624 varnameparts = (varname,) | |
| 625 try: | 640 try: |
| 626 obj = self.getvarl(*varnameparts, namespace=varns) | 641 if not varns: |
| 627 return self.substitute_variables_in_obj(obj) | 642 return self.substitute_variables_in_obj( |
| 643 self.getvarl(*pathstr2path(varname))) | |
| 644 else: | |
| 645 return self.substitute_variables_in_obj( | |
| 646 self.getvarl(varname, namespace=varns)) | |
| 628 except KeyError: | 647 except KeyError: |
| 629 if default is _MARKER: | 648 if default is _MARKER: |
| 630 raise | 649 raise |
| 631 else: | 650 else: |
| 632 return default | 651 return default |
| 640 Currently used by :meth:`~.interpolate_variables`. | 659 Currently used by :meth:`~.interpolate_variables`. |
| 641 | 660 |
| 642 """ | 661 """ |
| 643 varns, varname = self._split_ns(varname) | 662 varns, varname = self._split_ns(varname) |
| 644 if not varns: | 663 if not varns: |
| 645 cacheable = True | 664 # no namespace -> cacheable |
| 646 if varname: | 665 return ( |
| 647 varnameparts = tuple([unquote(vp) | 666 self.substitute_variables_in_obj( |
| 648 for vp in varname.split(_HIER_SEPARATOR)]) | 667 self.getvarl(*pathstr2path(varname))), |
| 649 else: | 668 True |
| 650 varnameparts = tuple() | 669 ) |
| 651 else: | 670 else: |
| 652 cacheable = False | 671 # results from namespaced lookups are currently not cacheable |
| 653 varnameparts = (varname,) | 672 return ( |
| 654 obj = self.getvarl(*varnameparts, namespace=varns) | 673 self.substitute_variables_in_obj( |
| 655 return (self.substitute_variables_in_obj(obj), cacheable) | 674 self.getvarl(varname, namespace=varns)), |
| 675 False | |
| 676 ) | |
| 656 | 677 |
| 657 def getfirstvar_s(self, *varnames, **kwds): | 678 def getfirstvar_s(self, *varnames, **kwds): |
| 658 """A variant of :meth:`~.getvar_s` that returns the first found | 679 """A variant of :meth:`~.getvar_s` that returns the first found |
| 659 variable in the list of given variables in `varnames`. | 680 variable in the list of given variables in `varnames`. |
| 660 | 681 |
| 818 end = s.find(_ENDTOK, start) | 839 end = s.find(_ENDTOK, start) |
| 819 if end < 0: | 840 if end < 0: |
| 820 rest = start | 841 rest = start |
| 821 break | 842 break |
| 822 varname, filters = self._split_filters( | 843 varname, filters = self._split_filters( |
| 823 s[start+2:end]) | 844 s[start+2:end]) # noqa: E226 |
| 824 try: | 845 try: |
| 825 varvalue, cacheable = self._getvar_s_with_cache_info(varname) | 846 varvalue, cacheable = self._getvar_s_with_cache_info(varname) |
| 826 except KeyError: | 847 except KeyError: |
| 827 cacheable = True | 848 cacheable = True |
| 828 if NONE_FILTER in filters: | 849 if NONE_FILTER in filters: |
| 903 # convert to path | 924 # convert to path |
| 904 varns, varname = self._split_ns(root) | 925 varns, varname = self._split_ns(root) |
| 905 if varns: | 926 if varns: |
| 906 raise ValueError( | 927 raise ValueError( |
| 907 "jailed configurations do not support namespaces") | 928 "jailed configurations do not support namespaces") |
| 908 if varname: | 929 rootpath = pathstr2path(root) |
| 909 rootpath = tuple([unquote(p) | |
| 910 for p in root.split(_HIER_SEPARATOR)]) | |
| 911 else: | |
| 912 rootpath = tuple() | |
| 913 jc = _JailedConfiguration(*rootpath) | 930 jc = _JailedConfiguration(*rootpath) |
| 914 if bind_root: | 931 if bind_root: |
| 915 jc.rebind(self) | 932 jc.rebind(self) |
| 916 return jc | 933 return jc |
| 917 | 934 |
| 1069 else: | 1086 else: |
| 1070 raise TypeError("a paths item must be a list or tuple") | 1087 raise TypeError("a paths item must be a list or tuple") |
| 1071 return self._base.getfirstvarl_s(*real_paths, **kwds) | 1088 return self._base.getfirstvarl_s(*real_paths, **kwds) |
| 1072 | 1089 |
| 1073 def getvar(self, varname, **kwds): | 1090 def getvar(self, varname, **kwds): |
| 1074 if varname: | 1091 return self._base.getvarl(*(self._path + pathstr2path(varname)), |
| 1075 varnameparts = self._path \ | 1092 **kwds) |
| 1076 + tuple([unquote(vp) | |
| 1077 for vp in varname.split(_HIER_SEPARATOR)]) | |
| 1078 else: | |
| 1079 varnameparts = self._path | |
| 1080 return self._base.getvarl(*varnameparts, **kwds) | |
| 1081 | 1093 |
| 1082 def getkeys(self, varname): | 1094 def getkeys(self, varname): |
| 1083 if varname: | 1095 for k in self._base.getkeysl(*(self._path + pathstr2path(varname))): |
| 1084 varnameparts = self._path \ | |
| 1085 + tuple([unquote(vp) | |
| 1086 for vp in varname.split(_HIER_SEPARATOR)]) | |
| 1087 else: | |
| 1088 varnameparts = self._path | |
| 1089 for k in self._base.getkeysl(*varnameparts): | |
| 1090 yield k | 1096 yield k |
| 1091 | 1097 |
| 1092 def getfirstvar(self, *varnames, **kwds): | 1098 def getfirstvar(self, *varnames, **kwds): |
| 1093 real_varnames = [self._pathstr + vn for vn in varnames] | 1099 real_varnames = [self._pathstr + vn for vn in varnames] |
| 1094 return self._base.getfirstvar(*real_varnames, **kwds) | 1100 return self._base.getfirstvar(*real_varnames, **kwds) |
| 1095 | 1101 |
| 1096 def getvar_s(self, varname, **kwds): | 1102 def getvar_s(self, varname, **kwds): |
| 1097 if varname: | 1103 return self._base.getvarl_s(*(self._path + pathstr2path(varname)), |
| 1098 varnameparts = self._path \ | 1104 **kwds) |
| 1099 + tuple([unquote(vp) | |
| 1100 for vp in varname.split(_HIER_SEPARATOR)]) | |
| 1101 else: | |
| 1102 varnameparts = self._path | |
| 1103 return self._base.getvarl_s(*varnameparts, **kwds) | |
| 1104 | 1105 |
| 1105 def getfirstvar_s(self, *varnames, **kwds): | 1106 def getfirstvar_s(self, *varnames, **kwds): |
| 1106 real_varnames = [self._pathstr + vn for vn in varnames] | 1107 real_varnames = [self._pathstr + vn for vn in varnames] |
| 1107 return self._base.getfirstvar_s(*real_varnames, **kwds) | 1108 return self._base.getfirstvar_s(*real_varnames, **kwds) |
| 1108 | 1109 |
| 1143 # convert to path | 1144 # convert to path |
| 1144 varns, varname = self._base._split_ns(root) | 1145 varns, varname = self._base._split_ns(root) |
| 1145 if varns: | 1146 if varns: |
| 1146 raise ValueError( | 1147 raise ValueError( |
| 1147 "sub-jails do not support namespaces") | 1148 "sub-jails do not support namespaces") |
| 1148 if varname: | 1149 rootpath = pathstr2path(varname) |
| 1149 rootpath = tuple([unquote(p) | |
| 1150 for p in varname.split(_HIER_SEPARATOR)]) | |
| 1151 else: | |
| 1152 rootpath = tuple() | |
| 1153 if self._path: | 1150 if self._path: |
| 1154 new_rootpath = self._path + tuple(rootpath) | 1151 new_rootpath = self._path + tuple(rootpath) |
| 1155 else: | 1152 else: |
| 1156 new_rootpath = tuple(rootpath) | 1153 new_rootpath = tuple(rootpath) |
| 1157 sjc = _JailedConfiguration(*new_rootpath) | 1154 sjc = _JailedConfiguration(*new_rootpath) |
