explicit splice: do not fail for bad config replacement if target not matched (#46925)
Originally, concretization failed if the splice config points to an invalid replacement. This PR defers the check until we know the splice is needed, so that irrelevant splices with bad config cannot stop concretization. While I was at it, I improved an error message from an assert to a ValueError.
This commit is contained in:
parent
fea2171672
commit
47e70c5c3a
@ -3829,8 +3829,16 @@ def execute_explicit_splices(self):
|
||||
for splice_set in splice_config:
|
||||
target = splice_set["target"]
|
||||
replacement = spack.spec.Spec(splice_set["replacement"])
|
||||
assert replacement.abstract_hash
|
||||
replacement.replace_hash()
|
||||
|
||||
if not replacement.abstract_hash:
|
||||
location = getattr(
|
||||
splice_set["replacement"], "_start_mark", " at unknown line number"
|
||||
)
|
||||
msg = f"Explicit splice replacement '{replacement}' does not include a hash.\n"
|
||||
msg += f"{location}\n\n"
|
||||
msg += " Splice replacements must be specified by hash"
|
||||
raise InvalidSpliceError(msg)
|
||||
|
||||
transitive = splice_set.get("transitive", False)
|
||||
splice_triples.append((target, replacement, transitive))
|
||||
|
||||
@ -3841,6 +3849,10 @@ def execute_explicit_splices(self):
|
||||
if target in current_spec:
|
||||
# matches root or non-root
|
||||
# e.g. mvapich2%gcc
|
||||
|
||||
# The first iteration, we need to replace the abstract hash
|
||||
if not replacement.concrete:
|
||||
replacement.replace_hash()
|
||||
current_spec = current_spec.splice(replacement, transitive)
|
||||
new_key = NodeArgument(id=key.id, pkg=current_spec.name)
|
||||
specs[new_key] = current_spec
|
||||
@ -4226,3 +4238,7 @@ def __init__(self, provided, conflicts):
|
||||
# Add attribute expected of the superclass interface
|
||||
self.required = None
|
||||
self.constraint_type = None
|
||||
|
||||
|
||||
class InvalidSpliceError(spack.error.SpackError):
|
||||
"""For cases in which the splice configuration is invalid."""
|
||||
|
@ -2306,6 +2306,30 @@ def test_explicit_splices(
|
||||
assert "hdf5 ^zmpi" in captured.err
|
||||
assert str(spec) in captured.err
|
||||
|
||||
def test_explicit_splice_fails_nonexistent(mutable_config, mock_packages, mock_store):
|
||||
splice_info = {"target": "mpi", "replacement": "mpich/doesnotexist"}
|
||||
spack.config.CONFIG.set("concretizer", {"splice": {"explicit": [splice_info]}})
|
||||
|
||||
with pytest.raises(spack.spec.InvalidHashError):
|
||||
_ = spack.spec.Spec("hdf5^zmpi").concretized()
|
||||
|
||||
def test_explicit_splice_fails_no_hash(mutable_config, mock_packages, mock_store):
|
||||
splice_info = {"target": "mpi", "replacement": "mpich"}
|
||||
spack.config.CONFIG.set("concretizer", {"splice": {"explicit": [splice_info]}})
|
||||
|
||||
with pytest.raises(spack.solver.asp.InvalidSpliceError, match="must be specified by hash"):
|
||||
_ = spack.spec.Spec("hdf5^zmpi").concretized()
|
||||
|
||||
def test_explicit_splice_non_match_nonexistent_succeeds(
|
||||
mutable_config, mock_packages, mock_store
|
||||
):
|
||||
"""When we have a nonexistent splice configured but are not using it, don't fail."""
|
||||
splice_info = {"target": "will_not_match", "replacement": "nonexistent/doesnotexist"}
|
||||
spack.config.CONFIG.set("concretizer", {"splice": {"explicit": [splice_info]}})
|
||||
spec = spack.spec.Spec("zlib").concretized()
|
||||
# the main test is that it does not raise
|
||||
assert not spec.spliced
|
||||
|
||||
@pytest.mark.db
|
||||
@pytest.mark.parametrize(
|
||||
"spec_str,mpi_name",
|
||||
|
Loading…
Reference in New Issue
Block a user