Added custom messages for conflicts directive. fixes #4965 (#5083)

Users can now add an optional custom message to the conflicts directive.
Layout on screen has been changed to improve readability and the long
spec is shown in tree format. Two conflicts in `espresso` have been
modified to showcase the feature.
This commit is contained in:
Massimiliano Culpo 2017-08-21 18:20:07 +02:00 committed by becker33
parent bd8ac0a738
commit 581f70ff6f
3 changed files with 37 additions and 10 deletions

View file

@ -263,7 +263,7 @@ def _depends_on(pkg, spec, when=None, type=None):
@directive('conflicts') @directive('conflicts')
def conflicts(conflict_spec, when=None): def conflicts(conflict_spec, when=None, msg=None):
"""Allows a package to define a conflict. """Allows a package to define a conflict.
Currently, a "conflict" is a concretized configuration that is known Currently, a "conflict" is a concretized configuration that is known
@ -280,14 +280,16 @@ def conflicts(conflict_spec, when=None):
Args: Args:
conflict_spec (Spec): constraint defining the known conflict conflict_spec (Spec): constraint defining the known conflict
when (Spec): optional constraint that triggers the conflict when (Spec): optional constraint that triggers the conflict
msg (str): optional user defined message
""" """
def _execute(pkg): def _execute(pkg):
# If when is not specified the conflict always holds # If when is not specified the conflict always holds
condition = pkg.name if when is None else when condition = pkg.name if when is None else when
when_spec = parse_anonymous_spec(condition, pkg.name) when_spec = parse_anonymous_spec(condition, pkg.name)
# Save in a list the conflicts and the associated custom messages
when_spec_list = pkg.conflicts.setdefault(conflict_spec, []) when_spec_list = pkg.conflicts.setdefault(conflict_spec, [])
when_spec_list.append(when_spec) when_spec_list.append((when_spec, msg))
return _execute return _execute

View file

@ -1798,9 +1798,9 @@ def concretize(self):
for x in self.traverse(): for x in self.traverse():
for conflict_spec, when_list in x.package.conflicts.items(): for conflict_spec, when_list in x.package.conflicts.items():
if x.satisfies(conflict_spec): if x.satisfies(conflict_spec):
for when_spec in when_list: for when_spec, msg in when_list:
if x.satisfies(when_spec): if x.satisfies(when_spec):
matches.append((x, conflict_spec, when_spec)) matches.append((x, conflict_spec, when_spec, msg))
if matches: if matches:
raise ConflictsInSpecError(self, matches) raise ConflictsInSpecError(self, matches)
@ -3447,8 +3447,24 @@ def __init__(self, spec, matches):
message = 'Conflicts in concretized spec "{0}"\n'.format( message = 'Conflicts in concretized spec "{0}"\n'.format(
spec.short_spec spec.short_spec
) )
long_message = 'List of matching conflicts:\n\n'
match_fmt = '{0}. "{1}" conflicts with "{2}" in spec "{3}"\n' visited = set()
for idx, (s, c, w) in enumerate(matches):
long_message += match_fmt.format(idx + 1, c, w, s) long_message = ''
match_fmt_default = '{0}. "{1}" conflicts with "{2}"\n'
match_fmt_custom = '{0}. "{1}" conflicts with "{2}" [{3}]\n'
for idx, (s, c, w, msg) in enumerate(matches):
if s not in visited:
visited.add(s)
long_message += 'List of matching conflicts for spec:\n\n'
long_message += s.tree(indent=4) + '\n'
if msg is None:
long_message += match_fmt_default.format(idx + 1, c, w)
else:
long_message += match_fmt_custom.format(idx + 1, c, w, msg)
super(ConflictsInSpecError, self).__init__(message, long_message) super(ConflictsInSpecError, self).__init__(message, long_message)

View file

@ -75,8 +75,17 @@ class Espresso(Package):
patch('dspev_drv_elpa.patch', when='@6.1 ^elpa@2016.05.003') patch('dspev_drv_elpa.patch', when='@6.1 ^elpa@2016.05.003')
# We can't ask for scalapack or elpa if we don't want MPI # We can't ask for scalapack or elpa if we don't want MPI
conflicts('+scalapack', when='~mpi') conflicts(
conflicts('+elpa', when='~mpi') '+scalapack',
when='~mpi',
msg='scalapack is a parallel library and needs MPI support'
)
conflicts(
'+elpa',
when='~mpi',
msg='elpa is a parallel library and needs MPI support'
)
# Elpa is formally supported by @:5.4.0, but QE configure searches # Elpa is formally supported by @:5.4.0, but QE configure searches
# for it in the wrong folders (or tries to download it within # for it in the wrong folders (or tries to download it within