diff options
author | Todd Gamblin <tgamblin@llnl.gov> | 2023-06-20 17:16:42 -0700 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2024-01-09 00:26:22 -0800 |
commit | 1bda594f70d611d52ef9bc372fef6418266c9a5e (patch) | |
tree | 4e10fd985003177bce72cf10425e10dd4a1b10cb /lib | |
parent | 6542c94cc1e0cdb5f8c61936c78b74c46d7b6c01 (diff) | |
download | spack-1bda594f70d611d52ef9bc372fef6418266c9a5e.tar.gz spack-1bda594f70d611d52ef9bc372fef6418266c9a5e.tar.bz2 spack-1bda594f70d611d52ef9bc372fef6418266c9a5e.tar.xz spack-1bda594f70d611d52ef9bc372fef6418266c9a5e.zip |
refactor: Index conflicts by `when` spec
Part 2 of reworking all package metadata to key by `when` conditions.
Changes conflict dictionary structure from this:
{ conflict_spec: [(when_spec, msg), ...] }
to this:
{ when_spec: [(conflict_spec, msg), ...] }
Also attempts to consistently name the variables used to iterate over conflict
dictionaries.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/audit.py | 4 | ||||
-rw-r--r-- | lib/spack/spack/directives.py | 8 | ||||
-rw-r--r-- | lib/spack/spack/package_base.py | 5 | ||||
-rw-r--r-- | lib/spack/spack/solver/asp.py | 37 | ||||
-rw-r--r-- | lib/spack/spack/spec.py | 9 | ||||
-rw-r--r-- | lib/spack/spack/test/concretize.py | 2 | ||||
-rw-r--r-- | lib/spack/spack/test/directives.py | 2 |
7 files changed, 33 insertions, 34 deletions
diff --git a/lib/spack/spack/audit.py b/lib/spack/spack/audit.py index d9b2610267..40bd04e9bc 100644 --- a/lib/spack/spack/audit.py +++ b/lib/spack/spack/audit.py @@ -667,8 +667,8 @@ def _unknown_variants_in_directives(pkgs, error_cls): pkg_cls = spack.repo.PATH.get_pkg_class(pkg_name) # Check "conflicts" directive - for conflict, triggers in pkg_cls.conflicts.items(): - for trigger, _ in triggers: + for trigger, conflicts in pkg_cls.conflicts.items(): + for conflict, _ in conflicts: vrn = spack.spec.Spec(conflict) try: vrn.constrain(trigger) diff --git a/lib/spack/spack/directives.py b/lib/spack/spack/directives.py index e837f497af..75cda9f90b 100644 --- a/lib/spack/spack/directives.py +++ b/lib/spack/spack/directives.py @@ -525,7 +525,7 @@ def _depends_on( @directive("conflicts") -def conflicts(conflict_spec, when=None, msg=None): +def conflicts(conflict_spec: SpecType, when: WhenType = None, msg: Optional[str] = None): """Allows a package to define a conflict. Currently, a "conflict" is a concretized configuration that is known @@ -545,16 +545,16 @@ def conflicts(conflict_spec, when=None, msg=None): msg (str): optional user defined message """ - def _execute_conflicts(pkg): + def _execute_conflicts(pkg: "spack.package_base.PackageBase"): # If when is not specified the conflict always holds when_spec = make_when_spec(when) if not when_spec: return # Save in a list the conflicts and the associated custom messages - when_spec_list = pkg.conflicts.setdefault(conflict_spec, []) + conflict_spec_list = pkg.conflicts.setdefault(when_spec, []) msg_with_name = f"{pkg.name}: {msg}" if msg is not None else msg - when_spec_list.append((when_spec, msg_with_name)) + conflict_spec_list.append((spack.spec.Spec(conflict_spec), msg_with_name)) return _execute_conflicts diff --git a/lib/spack/spack/package_base.py b/lib/spack/spack/package_base.py index 926df89181..9b1b1c17c8 100644 --- a/lib/spack/spack/package_base.py +++ b/lib/spack/spack/package_base.py @@ -560,11 +560,8 @@ class PackageBase(WindowsRPath, PackageViewMixin, metaclass=PackageMeta): # Declare versions dictionary as placeholder for values. # This allows analysis tools to correctly interpret the class attributes. versions: dict - - # Same for dependencies dependencies: Dict["spack.spec.Spec", Dict[str, "spack.dependency.Dependency"]] - - # and patches + conflicts: Dict["spack.spec.Spec", List[Tuple["spack.spec.Spec", Optional[str]]]] patches: Dict["spack.spec.Spec", List["spack.patch.Patch"]] #: By default, packages are not virtual diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index aa00600d0b..3a0267a50c 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -1234,29 +1234,30 @@ class SpackSolverSetup: return [fn.attr("node_target_satisfies", spec.name, target)] def conflict_rules(self, pkg): - default_msg = "{0}: '{1}' conflicts with '{2}'" - no_constraint_msg = "{0}: conflicts with '{1}'" - for trigger, constraints in pkg.conflicts.items(): - trigger_msg = f"conflict is triggered when {str(trigger)}" - trigger_spec = spack.spec.Spec(trigger) - trigger_id = self.condition( - trigger_spec, name=trigger_spec.name or pkg.name, msg=trigger_msg - ) + for when_spec, conflict_specs in pkg.conflicts.items(): + when_spec_msg = "conflict constraint %s" % str(when_spec) + when_spec_id = self.condition(when_spec, name=pkg.name, msg=when_spec_msg) - for constraint, conflict_msg in constraints: + for conflict_spec, conflict_msg in conflict_specs: + conflict_spec = spack.spec.Spec(conflict_spec) if conflict_msg is None: - if constraint == spack.spec.Spec(): - conflict_msg = no_constraint_msg.format(pkg.name, trigger) + conflict_msg = f"{pkg.name}: " + if when_spec == spack.spec.Spec(): + conflict_msg += f"conflicts with '{conflict_spec}'" else: - conflict_msg = default_msg.format(pkg.name, trigger, constraint) - - spec_for_msg = ( - spack.spec.Spec(pkg.name) if constraint == spack.spec.Spec() else constraint + conflict_msg += f"'{conflict_spec}' conflicts with '{when_spec}'" + + spec_for_msg = conflict_spec + if conflict_spec == spack.spec.Spec(): + spec_for_msg = spack.spec.Spec(pkg.name) + conflict_spec_msg = f"conflict is triggered when {str(spec_for_msg)}" + conflict_spec_id = self.condition( + conflict_spec, name=conflict_spec.name or pkg.name, msg=conflict_spec_msg ) - constraint_msg = f"conflict applies to spec {str(spec_for_msg)}" - constraint_id = self.condition(constraint, name=pkg.name, msg=constraint_msg) self.gen.fact( - fn.pkg_fact(pkg.name, fn.conflict(trigger_id, constraint_id, conflict_msg)) + fn.pkg_fact( + pkg.name, fn.conflict(conflict_spec_id, when_spec_id, conflict_msg) + ) ) self.gen.newline() diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index a11e8ab915..b27272e8e1 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -2823,10 +2823,11 @@ class Spec: # external specs are already built, don't worry about whether # it's possible to build that configuration with Spack continue - for conflict_spec, when_list in x.package_class.conflicts.items(): - if x.satisfies(conflict_spec): - for when_spec, msg in when_list: - if x.satisfies(when_spec): + + for when_spec, conflict_list in x.package_class.conflicts.items(): + if x.satisfies(when_spec): + for conflict_spec, msg in conflict_list: + if x.satisfies(conflict_spec): when = when_spec.copy() when.name = x.name matches.append((x, conflict_spec, when, msg)) diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index c53dc0dd36..b6ddf6c4dd 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -1905,7 +1905,7 @@ class TestConcretize: """ # Add a conflict to "mpich" that match an already installed "mpich~debug" pkg_cls = spack.repo.PATH.get_pkg_class("mpich") - monkeypatch.setitem(pkg_cls.conflicts, "~debug", [(Spec(), None)]) + monkeypatch.setitem(pkg_cls.conflicts, Spec(), [("~debug", None)]) # If we concretize with --fresh the conflict is taken into account with spack.config.override("concretizer:reuse", False): diff --git a/lib/spack/spack/test/directives.py b/lib/spack/spack/test/directives.py index 73d40365b9..5b34e40793 100644 --- a/lib/spack/spack/test/directives.py +++ b/lib/spack/spack/test/directives.py @@ -46,7 +46,7 @@ def test_constraints_from_context(mock_packages): assert "b" in pkg_cls.dependencies[spack.spec.Spec("@1.0")] assert pkg_cls.conflicts - assert (spack.spec.Spec("+foo@1.0"), None) in pkg_cls.conflicts["%gcc"] + assert (spack.spec.Spec("%gcc"), None) in pkg_cls.conflicts[spack.spec.Spec("+foo@1.0")] @pytest.mark.regression("26656") |