"spack config add": allow values with a ":" (#39279)
If you wanted to set a configuration option like `config:install_tree:root` to "C:/path/to/config.yaml", Spack had trouble parsing this because of the ":" in the value. This adds logic to allow using quotes to enclose the value, so you can add `config:install_tree:root:"C:/path/to/config.yaml"`. Configuration keys should never contain a quote character, so the presence of any quote is taken to mean that the rest of the string is specifying the value.
This commit is contained in:
parent
818195a3bd
commit
b72a268bc5
2 changed files with 30 additions and 7 deletions
|
@ -863,6 +863,7 @@ def add(fullpath, scope=None):
|
||||||
has_existing_value = True
|
has_existing_value = True
|
||||||
path = ""
|
path = ""
|
||||||
override = False
|
override = False
|
||||||
|
value = syaml.load_config(components[-1])
|
||||||
for idx, name in enumerate(components[:-1]):
|
for idx, name in enumerate(components[:-1]):
|
||||||
# First handle double colons in constructing path
|
# First handle double colons in constructing path
|
||||||
colon = "::" if override else ":" if path else ""
|
colon = "::" if override else ":" if path else ""
|
||||||
|
@ -883,14 +884,14 @@ def add(fullpath, scope=None):
|
||||||
existing = get_valid_type(path)
|
existing = get_valid_type(path)
|
||||||
|
|
||||||
# construct value from this point down
|
# construct value from this point down
|
||||||
value = syaml.load_config(components[-1])
|
|
||||||
for component in reversed(components[idx + 1 : -1]):
|
for component in reversed(components[idx + 1 : -1]):
|
||||||
value = {component: value}
|
value = {component: value}
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if override:
|
||||||
|
path += "::"
|
||||||
|
|
||||||
if has_existing_value:
|
if has_existing_value:
|
||||||
path, _, value = fullpath.rpartition(":")
|
|
||||||
value = syaml.load_config(value)
|
|
||||||
existing = get(path, scope=scope)
|
existing = get(path, scope=scope)
|
||||||
|
|
||||||
# append values to lists
|
# append values to lists
|
||||||
|
@ -1231,11 +1232,17 @@ def they_are(t):
|
||||||
return copy.copy(source)
|
return copy.copy(source)
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Process a path argument to config.set() that may contain overrides ('::' or
|
|
||||||
# trailing ':')
|
|
||||||
#
|
|
||||||
def process_config_path(path):
|
def process_config_path(path):
|
||||||
|
"""Process a path argument to config.set() that may contain overrides ('::' or
|
||||||
|
trailing ':')
|
||||||
|
|
||||||
|
Note: quoted value path components will be processed as a single value (escaping colons)
|
||||||
|
quoted path components outside of the value will be considered ill formed and will
|
||||||
|
raise.
|
||||||
|
e.g. `this:is:a:path:'value:with:colon'` will yield:
|
||||||
|
|
||||||
|
[this, is, a, path, value:with:colon]
|
||||||
|
"""
|
||||||
result = []
|
result = []
|
||||||
if path.startswith(":"):
|
if path.startswith(":"):
|
||||||
raise syaml.SpackYAMLError("Illegal leading `:' in path `{0}'".format(path), "")
|
raise syaml.SpackYAMLError("Illegal leading `:' in path `{0}'".format(path), "")
|
||||||
|
@ -1262,6 +1269,16 @@ def process_config_path(path):
|
||||||
front = syaml.syaml_str(front)
|
front = syaml.syaml_str(front)
|
||||||
front.append = True
|
front.append = True
|
||||||
|
|
||||||
|
quote = "['\"]"
|
||||||
|
not_quote = "[^'\"]"
|
||||||
|
|
||||||
|
if re.match(f"^{quote}", path):
|
||||||
|
m = re.match(rf"^{quote}({not_quote}+){quote}$", path)
|
||||||
|
if not m:
|
||||||
|
raise ValueError("Quotes indicate value, but there are additional path entries")
|
||||||
|
result.append(m.group(1))
|
||||||
|
break
|
||||||
|
|
||||||
result.append(front)
|
result.append(front)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -277,6 +277,12 @@ def test_add_config_path(mutable_config):
|
||||||
compilers = spack.config.get("packages")["all"]["compiler"]
|
compilers = spack.config.get("packages")["all"]["compiler"]
|
||||||
assert "gcc" in compilers
|
assert "gcc" in compilers
|
||||||
|
|
||||||
|
# Try with an escaped colon
|
||||||
|
path = 'config:install_tree:root:"C:/path/to/config.yaml"'
|
||||||
|
spack.config.add(path)
|
||||||
|
set_value = spack.config.get("config")["install_tree"]["root"]
|
||||||
|
assert set_value == "C:/path/to/config.yaml"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.regression("17543,23259")
|
@pytest.mark.regression("17543,23259")
|
||||||
def test_add_config_path_with_enumerated_type(mutable_config):
|
def test_add_config_path_with_enumerated_type(mutable_config):
|
||||||
|
|
Loading…
Reference in a new issue