refactor: Index requirements by when spec

Part 3 of reworking all package metadata to key by `when` conditions.

Changes conflict dictionary structure from this:

    { (requirement_spec, ...): [(when_spec, policy, msg)] }

to this:

    { when_spec: [((requirement_spec, ...), policy, msg), ...] }
This commit is contained in:
Todd Gamblin 2023-06-20 18:34:21 -07:00
parent 1bda594f70
commit d2a9e3f871
4 changed files with 14 additions and 10 deletions

View file

@ -967,10 +967,10 @@ def _extracts_errors(triggers, summary):
summary = f"{pkg_name}: wrong 'when=' condition for the '{provided}' virtual"
errors.extend(_extracts_errors(triggers, summary))
for _, triggers in pkg_cls.requirements.items():
triggers = [when_spec for when_spec, _, _ in triggers]
summary = f"{pkg_name}: wrong 'when=' condition in 'requires' directive"
errors.extend(_extracts_errors(triggers, summary))
for when, requirements, details in _error_items(pkg_cls.requirements):
errors.append(
error_cls(f"{pkg_name}: wrong 'when=' condition in 'requires' directive", details)
)
for when, _, details in _error_items(pkg_cls.patches):
errors.append(

View file

@ -965,7 +965,7 @@ def license(
@directive("requirements")
def requires(*requirement_specs, policy="one_of", when=None, msg=None):
def requires(*requirement_specs: str, policy="one_of", when=None, msg=None):
"""Allows a package to request a configuration to be present in all valid solutions.
For instance, a package that is known to compile only with GCC can declare:
@ -984,7 +984,7 @@ def requires(*requirement_specs, policy="one_of", when=None, msg=None):
msg: optional user defined message
"""
def _execute_requires(pkg):
def _execute_requires(pkg: "spack.package_base.PackageBase"):
if policy not in ("one_of", "any_of"):
err_msg = (
f"the 'policy' argument of the 'requires' directive in {pkg.name} is set "
@ -997,9 +997,10 @@ def _execute_requires(pkg):
return
# Save in a list the requirements and the associated custom messages
when_spec_list = pkg.requirements.setdefault(tuple(requirement_specs), [])
requirement_list = pkg.requirements.setdefault(when_spec, [])
msg_with_name = f"{pkg.name}: {msg}" if msg is not None else msg
when_spec_list.append((when_spec, policy, msg_with_name))
requirements = tuple(spack.spec.Spec(s) for s in requirement_specs)
requirement_list.append((requirements, policy, msg_with_name))
return _execute_requires

View file

@ -562,6 +562,9 @@ class PackageBase(WindowsRPath, PackageViewMixin, metaclass=PackageMeta):
versions: dict
dependencies: Dict["spack.spec.Spec", Dict[str, "spack.dependency.Dependency"]]
conflicts: Dict["spack.spec.Spec", List[Tuple["spack.spec.Spec", Optional[str]]]]
requirements: Dict[
"spack.spec.Spec", List[Tuple[Tuple["spack.spec.Spec", ...], str, Optional[str]]]
]
patches: Dict["spack.spec.Spec", List["spack.patch.Patch"]]
#: By default, packages are not virtual

View file

@ -1303,8 +1303,8 @@ def package_requirement_rules(self, pkg):
def requirement_rules_from_package_py(self, pkg):
rules = []
for requirements, conditions in pkg.requirements.items():
for when_spec, policy, message in conditions:
for when_spec, requirement_list in pkg.requirements.items():
for requirements, policy, message in requirement_list:
rules.append(
RequirementRule(
pkg_name=pkg.name,