Mercurial > hgrepos > Python > libs > ConfigMix
comparison configmix/config.py @ 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 | a9eef98e5038 |
comparison
equal
deleted
inserted
replaced
| 678:f39b96e2bb2a | 679:aa39c1856de4 |
|---|---|
| 936 if not pu.fragment: | 936 if not pu.fragment: |
| 937 return self | 937 return self |
| 938 if pu.fragment.startswith(_DOT): | 938 if pu.fragment.startswith(_DOT): |
| 939 raise ValueError("relative refs not supported") | 939 raise ValueError("relative refs not supported") |
| 940 return self.getvar(pu.fragment) | 940 return self.getvar(pu.fragment) |
| 941 | |
| 942 def try_get_reference_uri(self, v): | |
| 943 """Check whether `v` is a configuration reference and -- if true -- | |
| 944 return the configuration path where the reference points to. | |
| 945 | |
| 946 If `v` is not a text type or not a reference return `None`. | |
| 947 | |
| 948 Does not check whether the referenced configuration object exists. | |
| 949 | |
| 950 :rtype: None or str | |
| 951 | |
| 952 """ | |
| 953 if not isinstance(v, _TEXTTYPE): | |
| 954 return None | |
| 955 if v.startswith(_STARTTOK_REF) and v.endswith(_ENDTOK_REF): | |
| 956 uri = v[len(_STARTTOK_REF):-len(_ENDTOK_REF)] | |
| 957 pu = urlsplit(uri) | |
| 958 if pu.scheme or pu.netloc or pu.path or pu.query: | |
| 959 raise ValueError("only fragment-only URIs are supported") | |
| 960 if not pu.fragment: | |
| 961 return _EMPTY_STR | |
| 962 if pu.fragment.startswith(_DOT): | |
| 963 raise ValueError("relative refs not supported") | |
| 964 return pu.fragment | |
| 965 return None | |
| 941 | 966 |
| 942 def substitute_variables_in_obj(self, obj): | 967 def substitute_variables_in_obj(self, obj): |
| 943 """Recursively expand variables in the object tree `obj`.""" | 968 """Recursively expand variables in the object tree `obj`.""" |
| 944 ty = type(obj) | 969 ty = type(obj) |
| 945 if issubclass(ty, _TEXTTYPE): | 970 if issubclass(ty, _TEXTTYPE): |
| 1060 raise NameError("Filter %r not found" % (name, )) | 1085 raise NameError("Filter %r not found" % (name, )) |
| 1061 else: | 1086 else: |
| 1062 value = filterfn(self, value) | 1087 value = filterfn(self, value) |
| 1063 return value | 1088 return value |
| 1064 | 1089 |
| 1065 def jailed(self, rootpath=None, root=None, bind_root=True): | 1090 def jailed(self, rootpath=None, root=None, |
| 1091 bind_root=True, resolve_ref=True): | |
| 1066 """Return a "jailed" configuration of the current configuration. | 1092 """Return a "jailed" configuration of the current configuration. |
| 1067 | 1093 |
| 1068 :param rootpath: a sequence of strings (or objects) that shall | 1094 :param rootpath: a sequence of strings (or objects) that shall |
| 1069 emcompass the chroot-like jail of the returned | 1095 emcompass the chroot-like jail of the returned |
| 1070 configuration | 1096 configuration |
| 1073 the chroot-like jail of the returned configuration | 1099 the chroot-like jail of the returned configuration |
| 1074 :param bool bind_root: if you do a :meth:`~.rebind` just after | 1100 :param bool bind_root: if you do a :meth:`~.rebind` just after |
| 1075 creation of a jailed config you can set | 1101 creation of a jailed config you can set |
| 1076 `bind_root` to `False`; otherwise use | 1102 `bind_root` to `False`; otherwise use |
| 1077 the default | 1103 the default |
| 1104 :param bool resolve_ref: If `True` then the jail's root is checked | |
| 1105 whether it is a reference. If it is a | |
| 1106 reference then the jail is effectively rooted | |
| 1107 where the reference points to. | |
| 1078 :return: a jailed (aka restricted) configuration | 1108 :return: a jailed (aka restricted) configuration |
| 1079 :rtype: _JailedConfiguration | 1109 :rtype: _JailedConfiguration |
| 1080 | 1110 |
| 1081 Exactly one of `rootpath` or `root` must be given. | 1111 Exactly one of `rootpath` or `root` must be given. |
| 1082 | 1112 |
| 1092 varns, varname = _split_ns(root) | 1122 varns, varname = _split_ns(root) |
| 1093 if varns: | 1123 if varns: |
| 1094 raise ValueError( | 1124 raise ValueError( |
| 1095 "jailed configurations do not support namespaces") | 1125 "jailed configurations do not support namespaces") |
| 1096 rootpath = pathstr2path(root) | 1126 rootpath = pathstr2path(root) |
| 1127 if resolve_ref: | |
| 1128 while True: | |
| 1129 target = self.getvarl(*rootpath) | |
| 1130 target_uri = self.try_get_reference_uri(target) | |
| 1131 if target_uri is None: | |
| 1132 break | |
| 1133 rootpath = pathstr2path(target_uri) | |
| 1097 jc = _JailedConfiguration(*rootpath) | 1134 jc = _JailedConfiguration(*rootpath) |
| 1098 if bind_root: | 1135 if bind_root: |
| 1099 jc.rebind(self) | 1136 jc.rebind(self) |
| 1100 return jc | 1137 return jc |
| 1101 | 1138 |
| 1321 | 1358 |
| 1322 def __bool__(self): | 1359 def __bool__(self): |
| 1323 """Map- and list-style evaluation in boolean context""" | 1360 """Map- and list-style evaluation in boolean context""" |
| 1324 return bool(self._base.getvarl_s(*self._path)) | 1361 return bool(self._base.getvarl_s(*self._path)) |
| 1325 | 1362 |
| 1326 def jailed(self, rootpath=None, root=None, bind_root=True): | 1363 def jailed(self, rootpath=None, root=None, |
| 1364 bind_root=True, resolve_ref=True): | |
| 1327 """Return a "jailed" configuration that effectively is a | 1365 """Return a "jailed" configuration that effectively is a |
| 1328 subjail of the current jail | 1366 subjail of the current jail |
| 1329 | 1367 |
| 1330 For a more complete description see :meth:`.Configuration.jailed`. | 1368 For a more complete description see :meth:`.Configuration.jailed`. |
| 1331 | 1369 |
| 1345 rootpath = pathstr2path(varname) | 1383 rootpath = pathstr2path(varname) |
| 1346 if self._path: | 1384 if self._path: |
| 1347 new_rootpath = self._path + tuple(rootpath) | 1385 new_rootpath = self._path + tuple(rootpath) |
| 1348 else: | 1386 else: |
| 1349 new_rootpath = tuple(rootpath) | 1387 new_rootpath = tuple(rootpath) |
| 1388 if resolve_ref: | |
| 1389 while True: | |
| 1390 target = self._base.getvarl(*new_rootpath) | |
| 1391 target_uri = self._base.try_get_reference_uri(target) | |
| 1392 if target_uri is None: | |
| 1393 break | |
| 1394 new_rootpath = pathstr2path(target_uri) | |
| 1350 sjc = _JailedConfiguration(*new_rootpath) | 1395 sjc = _JailedConfiguration(*new_rootpath) |
| 1351 if bind_root: | 1396 if bind_root: |
| 1352 sjc.rebind(self._base) | 1397 sjc.rebind(self._base) |
| 1353 return sjc | 1398 return sjc |
| 1354 | 1399 |
