solver: first prototype of chained error messages for one message type
This commit is contained in:
parent
59acfe4f0b
commit
e9012c7781
@ -614,6 +614,23 @@ def multiple_values_error(self, attribute, pkg):
|
|||||||
def no_value_error(self, attribute, pkg):
|
def no_value_error(self, attribute, pkg):
|
||||||
return f'Cannot select a single "{attribute}" for package "{pkg}"'
|
return f'Cannot select a single "{attribute}" for package "{pkg}"'
|
||||||
|
|
||||||
|
def _get_cause_tree(self, cause, conditions, condition_causes, literals, indent=""):
|
||||||
|
parents = [c for e, c in condition_causes if e == cause]
|
||||||
|
local = "required because %s " % conditions[cause]
|
||||||
|
|
||||||
|
return [indent + local] + [
|
||||||
|
c
|
||||||
|
for parent in parents
|
||||||
|
for c in self._get_cause_tree(
|
||||||
|
parent, conditions, condition_causes, literals, indent=indent + " "
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_cause_tree(self, cause):
|
||||||
|
conditions = dict(extract_args(self.model, "condition"))
|
||||||
|
condition_causes = list(extract_args(self.model, "condition_cause"))
|
||||||
|
return self._get_cause_tree(cause, conditions, condition_causes, [])
|
||||||
|
|
||||||
def handle_error(self, msg, *args):
|
def handle_error(self, msg, *args):
|
||||||
"""Handle an error state derived by the solver."""
|
"""Handle an error state derived by the solver."""
|
||||||
if msg == "multiple_values_error":
|
if msg == "multiple_values_error":
|
||||||
@ -622,10 +639,24 @@ def handle_error(self, msg, *args):
|
|||||||
if msg == "no_value_error":
|
if msg == "no_value_error":
|
||||||
return self.no_value_error(*args)
|
return self.no_value_error(*args)
|
||||||
|
|
||||||
|
try:
|
||||||
|
idx = args.index("startcauses")
|
||||||
|
except ValueError:
|
||||||
|
msg_args = args
|
||||||
|
cause_args = []
|
||||||
|
else:
|
||||||
|
msg_args = args[:idx]
|
||||||
|
cause_args = args[idx + 1 :]
|
||||||
|
|
||||||
|
msg = msg.format(*msg_args)
|
||||||
|
|
||||||
|
for cause in set(cause_args):
|
||||||
|
for c in self.get_cause_tree(cause):
|
||||||
|
msg += f"\n{c}"
|
||||||
|
|
||||||
# For variant formatting, we sometimes have to construct specs
|
# For variant formatting, we sometimes have to construct specs
|
||||||
# to format values properly. Find/replace all occurances of
|
# to format values properly. Find/replace all occurances of
|
||||||
# Spec(...) with the string representation of the spec mentioned
|
# Spec(...) with the string representation of the spec mentioned
|
||||||
msg = msg.format(*args)
|
|
||||||
specs_to_construct = re.findall(r"Spec\(([^)]*)\)", msg)
|
specs_to_construct = re.findall(r"Spec\(([^)]*)\)", msg)
|
||||||
for spec_str in specs_to_construct:
|
for spec_str in specs_to_construct:
|
||||||
msg = msg.replace("Spec(%s)" % spec_str, str(spack.spec.Spec(spec_str)))
|
msg = msg.replace("Spec(%s)" % spec_str, str(spack.spec.Spec(spec_str)))
|
||||||
@ -1266,9 +1297,11 @@ def package_provider_rules(self, pkg):
|
|||||||
for when in whens:
|
for when in whens:
|
||||||
msg = "%s provides %s when %s" % (pkg.name, provided, when)
|
msg = "%s provides %s when %s" % (pkg.name, provided, when)
|
||||||
condition_id = self.condition(when, provided, pkg.name, msg)
|
condition_id = self.condition(when, provided, pkg.name, msg)
|
||||||
self.gen.fact(fn.imposed_constraint(
|
self.gen.fact(
|
||||||
condition_id, "virtual_condition_holds", pkg.name, provided.name
|
fn.imposed_constraint(
|
||||||
))
|
condition_id, "virtual_condition_holds", pkg.name, provided.name
|
||||||
|
)
|
||||||
|
)
|
||||||
self.gen.newline()
|
self.gen.newline()
|
||||||
|
|
||||||
def package_dependencies_rules(self, pkg):
|
def package_dependencies_rules(self, pkg):
|
||||||
@ -1298,9 +1331,11 @@ def package_dependencies_rules(self, pkg):
|
|||||||
|
|
||||||
for t in sorted(deptypes):
|
for t in sorted(deptypes):
|
||||||
# there is a declared dependency of type t
|
# there is a declared dependency of type t
|
||||||
self.gen.fact(fn.imposed_constraint(
|
self.gen.fact(
|
||||||
condition_id, "dependency_holds", pkg.name, dep.spec.name, t
|
fn.imposed_constraint(
|
||||||
))
|
condition_id, "dependency_holds", pkg.name, dep.spec.name, t
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.gen.newline()
|
self.gen.newline()
|
||||||
|
|
||||||
@ -1454,9 +1489,11 @@ def external_packages(self):
|
|||||||
for local_idx, spec in enumerate(external_specs):
|
for local_idx, spec in enumerate(external_specs):
|
||||||
msg = "%s available as external when satisfying %s" % (spec.name, spec)
|
msg = "%s available as external when satisfying %s" % (spec.name, spec)
|
||||||
condition_id = self.condition(spec, msg=msg)
|
condition_id = self.condition(spec, msg=msg)
|
||||||
self.gen.fact(fn.imposed_constraint(
|
self.gen.fact(
|
||||||
condition_id, "external_conditions_hold", pkg_name, local_idx
|
fn.imposed_constraint(
|
||||||
))
|
condition_id, "external_conditions_hold", pkg_name, local_idx
|
||||||
|
)
|
||||||
|
)
|
||||||
self.possible_versions[spec.name].add(spec.version)
|
self.possible_versions[spec.name].add(spec.version)
|
||||||
self.gen.newline()
|
self.gen.newline()
|
||||||
|
|
||||||
@ -2310,16 +2347,20 @@ def literal_specs(self, specs):
|
|||||||
|
|
||||||
self.gen.fact(fn.condition_requirement(condition_id, "literal_solved", condition_id))
|
self.gen.fact(fn.condition_requirement(condition_id, "literal_solved", condition_id))
|
||||||
|
|
||||||
self.gen.fact(fn.imposed_constraint(
|
self.gen.fact(
|
||||||
condition_id, "virtual_root" if spec.virtual else "root", spec.name
|
fn.imposed_constraint(
|
||||||
))
|
condition_id, "virtual_root" if spec.virtual else "root", spec.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
for clause in self.spec_clauses(spec):
|
for clause in self.spec_clauses(spec):
|
||||||
self.gen.fact(fn.imposed_constraint(condition_id, *clause.args))
|
self.gen.fact(fn.imposed_constraint(condition_id, *clause.args))
|
||||||
if clause.args[0] == "variant_set":
|
if clause.args[0] == "variant_set":
|
||||||
self.gen.fact(fn.imposed_constraint(
|
self.gen.fact(
|
||||||
condition_id, "variant_default_value_from_cli", *clause.args[1:]
|
fn.imposed_constraint(
|
||||||
))
|
condition_id, "variant_default_value_from_cli", *clause.args[1:]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if self.concretize_everything:
|
if self.concretize_everything:
|
||||||
self.gen.fact(fn.concretize_everything())
|
self.gen.fact(fn.concretize_everything())
|
||||||
|
@ -86,6 +86,27 @@ version_satisfies(Package, Constraint, HashVersion) :- version_satisfies(Package
|
|||||||
{ attr("version", Package, Version) : version_declared(Package, Version) }
|
{ attr("version", Package, Version) : version_declared(Package, Version) }
|
||||||
:- attr("node", Package).
|
:- attr("node", Package).
|
||||||
|
|
||||||
|
% error we expect users to see
|
||||||
|
error(0, "Version '{0}' of {1} does not satisfy '@{2}'", Version, Package, Constraint, startcauses, VersionCause, ConstraintCause)
|
||||||
|
:- attr("node", Package),
|
||||||
|
attr("version", Package, Version),
|
||||||
|
imposed_constraint(VersionCause, "node_version_satisfies", Package, Version),
|
||||||
|
condition_holds(VersionCause),
|
||||||
|
attr("node_version_satisfies", Package, Constraint),
|
||||||
|
imposed_constraint(ConstraintCause, "node_version_satisfies", Package, Constraint),
|
||||||
|
condition_holds(ConstraintCause),
|
||||||
|
not version_satisfies(Package, Constraint, Version).
|
||||||
|
|
||||||
|
% Error to ensure structure of the program is not violated
|
||||||
|
error(2, "No version from '{0}' satisfies '@{1}' and '@{2}'", Package, Version1, Version2)
|
||||||
|
:- attr("node", Package),
|
||||||
|
attr("version", Package, Version1),
|
||||||
|
attr("version", Package, Version2),
|
||||||
|
Version1 < Version2. % see[1]
|
||||||
|
|
||||||
|
error(2, "No versions available for package '{0}'", Package)
|
||||||
|
:- attr("node", Package), not attr("version", Package, _).
|
||||||
|
|
||||||
% A virtual package may or may not have a version, but never has more than one
|
% A virtual package may or may not have a version, but never has more than one
|
||||||
error(100, "Cannot select a single version for virtual '{0}'", Virtual)
|
error(100, "Cannot select a single version for virtual '{0}'", Virtual)
|
||||||
:- attr("virtual_node", Virtual),
|
:- attr("virtual_node", Virtual),
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
#show error/4.
|
#show error/4.
|
||||||
#show error/5.
|
#show error/5.
|
||||||
#show error/6.
|
#show error/6.
|
||||||
|
#show error/7.
|
||||||
|
#show error/8.
|
||||||
|
|
||||||
% show cause -> effect data for errors
|
% show cause -> effect data for errors
|
||||||
#show condition_cause/2.
|
#show condition_cause/2.
|
||||||
|
Loading…
Reference in New Issue
Block a user