Skip to content

Commit 7226bd6

Browse files
authored
Improve error message for inconsistencies in package.py (#21811)
* Improve error message for inconsistencies in package.py Sometimes directives refer to variants that do not exist. Make it such that: 1. The name of the variant 2. The name of the package which is supposed to have such variant 3. The name of the package making this assumption are all printed in the error message for easier debugging. * Add unit tests
1 parent 56e5776 commit 7226bd6

4 files changed

Lines changed: 66 additions & 5 deletions

File tree

lib/spack/spack/solver/asp.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -647,11 +647,15 @@ def _condition_facts(
647647
self.gen.fact(cond_fn(condition_id, pkg_name, dep_spec.name))
648648

649649
# conditions that trigger the condition
650-
conditions = self.spec_clauses(named_cond, body=True)
650+
conditions = self.checked_spec_clauses(
651+
named_cond, body=True, required_from=pkg_name
652+
)
651653
for pred in conditions:
652654
self.gen.fact(require_fn(condition_id, pred.name, *pred.args))
653655

654-
imposed_constraints = self.spec_clauses(dep_spec)
656+
imposed_constraints = self.checked_spec_clauses(
657+
dep_spec, required_from=pkg_name
658+
)
655659
for pred in imposed_constraints:
656660
# imposed "node"-like conditions are no-ops
657661
if pred.name in ("node", "virtual_node"):
@@ -857,6 +861,20 @@ def flag_defaults(self):
857861
self.gen.fact(fn.compiler_version_flag(
858862
compiler.name, compiler.version, name, flag))
859863

864+
def checked_spec_clauses(self, *args, **kwargs):
865+
"""Wrap a call to spec clauses into a try/except block that raise
866+
a comprehensible error message in case of failure.
867+
"""
868+
requestor = kwargs.pop('required_from', None)
869+
try:
870+
clauses = self.spec_clauses(*args, **kwargs)
871+
except RuntimeError as exc:
872+
msg = str(exc)
873+
if requestor:
874+
msg += ' [required from package "{0}"]'.format(requestor)
875+
raise RuntimeError(msg)
876+
return clauses
877+
860878
def spec_clauses(self, spec, body=False, transitive=True):
861879
"""Return a list of clauses for a spec mandates are true.
862880
@@ -925,9 +943,14 @@ class Body(object):
925943

926944
# validate variant value
927945
reserved_names = spack.directives.reserved_names
928-
if (not spec.virtual and vname not in reserved_names):
929-
variant_def = spec.package.variants[vname]
930-
variant_def.validate_or_raise(variant, spec.package)
946+
if not spec.virtual and vname not in reserved_names:
947+
try:
948+
variant_def = spec.package.variants[vname]
949+
except KeyError:
950+
msg = 'variant "{0}" not found in package "{1}"'
951+
raise RuntimeError(msg.format(vname, spec.name))
952+
else:
953+
variant_def.validate_or_raise(variant, spec.package)
931954

932955
clauses.append(f.variant_value(spec.name, vname, value))
933956

lib/spack/spack/test/concretize.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,3 +1098,15 @@ def test_concretization_of_test_dependencies(self):
10981098
# dependency type declared to infer that the dependency holds.
10991099
s = Spec('test-dep-with-imposed-conditions').concretized()
11001100
assert 'c' not in s
1101+
1102+
@pytest.mark.parametrize('spec_str', [
1103+
'wrong-variant-in-conflicts',
1104+
'wrong-variant-in-depends-on'
1105+
])
1106+
def test_error_message_for_inconsistent_variants(self, spec_str):
1107+
if spack.config.get('config:concretizer') == 'original':
1108+
pytest.xfail('Known failure of the original concretizer')
1109+
1110+
s = Spec(spec_str)
1111+
with pytest.raises(RuntimeError, match='not found in package'):
1112+
s.concretize()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
2+
# Spack Project Developers. See the top-level COPYRIGHT file for details.
3+
#
4+
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
5+
class WrongVariantInConflicts(Package):
6+
"""This package has a wrong variant spelled in a conflict."""
7+
8+
homepage = "http://www.example.com"
9+
url = "http://www.example.com/b-1.0.tar.gz"
10+
11+
version('1.0', '0123456789abcdef0123456789abcdef')
12+
13+
conflicts('+foo', when='@1.0')
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
2+
# Spack Project Developers. See the top-level COPYRIGHT file for details.
3+
#
4+
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
5+
class WrongVariantInDependsOn(Package):
6+
"""This package has a wrong variant spelled in a depends_on."""
7+
8+
homepage = "http://www.example.com"
9+
url = "http://www.example.com/b-1.0.tar.gz"
10+
11+
version('1.0', '0123456789abcdef0123456789abcdef')
12+
13+
depends_on('b+doesnotexist')

0 commit comments

Comments
 (0)