Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
75a5546
Add a regression test
alalazo Feb 21, 2023
5d3e306
Fix wrong behavior with conditional provider and satisfies
alalazo Feb 21, 2023
8190f93
__contains__ use strict=True
alalazo Feb 21, 2023
45c00b7
ArchSpec.satisfies: remove default value to "strict" argument
alalazo Feb 22, 2023
164ca8b
Spec.satisfies: split the function on the `strict=` value
alalazo Feb 22, 2023
d46b002
Version*.satisfies: split the function on the `strict=` value
alalazo Feb 23, 2023
832191b
CompilerSpec.satisfies: split the function on the `strict=` value
alalazo Feb 23, 2023
7f1b36b
FlagMap.satisfies: split the function on the `strict=` value
alalazo Feb 23, 2023
a0f83c4
ArchSpec.satisfies: split the function on the `strict=` value
alalazo Feb 23, 2023
5633feb
VariantMap.satisfies: split the function on the `strict=` value
alalazo Feb 23, 2023
29fa842
Change name everywhere from "placeholder_satisfies" -> "satisfies"
alalazo Feb 23, 2023
e6e5d20
Fix failing unit tests
alalazo Feb 23, 2023
6444bd4
Mark 2 unit tests for later todo
alalazo Feb 23, 2023
4361e8b
ArchSpec: add unit tests for intersects, satisfies and constrain
alalazo Feb 24, 2023
73c4bdd
CompilerSpec: add unit tests for intersects, satisfies and constrain
alalazo Feb 24, 2023
d6cf0fe
FlagMap: add unit tests
alalazo Feb 24, 2023
cf9f813
Fixed an issue with symmetry of VariantMap.intersects
alalazo Feb 24, 2023
acec6e6
Fixup old solver
alalazo Feb 24, 2023
3f04ec7
Take care of a few FIXMEs
alalazo Feb 24, 2023
3f1f8ca
Remove non-commutative behavior in Spec._intersects_dependencies
alalazo Feb 24, 2023
124fa6c
Fix package audits and spack info
alalazo Feb 24, 2023
8691f2b
Fix failing tests for git commits
alalazo Feb 27, 2023
0aeaa35
Make Spec.intersects commutative
alalazo Feb 27, 2023
76d4ef9
version.py: clarify a few implementations, add tests
alalazo Mar 1, 2023
bebaf82
variant.py: switch implementation from compatible -> intersects
alalazo Mar 1, 2023
a1c1ece
for_package_version: add comment and safety belt
alalazo Mar 1, 2023
964b06e
macsio: change default variant to avoid build issues
alalazo Mar 2, 2023
984f6b3
Rename constrain_or_raise -> check_can_constrain
alalazo Mar 3, 2023
01a515c
Refactor check_can_constrain(..., concrete=False) into a parametrized…
alalazo Mar 3, 2023
a2a9167
Constraining an abstract spec by a concrete one makes the first concr…
alalazo Mar 3, 2023
cdbf559
Add a unit test for abstract specs that do not intersect
alalazo Mar 3, 2023
3466bd2
Add a unit test for concrete specs that do not satisfy abstract specs
alalazo Mar 3, 2023
8404391
Remove check_constrain, add the tests back as parameters
alalazo Mar 3, 2023
41a860d
Remove check_invalid_constrain, add the tests back as parameters
alalazo Mar 3, 2023
9a90d9f
Add parametrized tests to check is a constraint changes a spec or not
alalazo Mar 3, 2023
3b89375
Fix semantic of variant intersection
alalazo Mar 3, 2023
3a5b534
Fix flags semantic
alalazo Mar 3, 2023
de9e674
Remove outdated comment
alalazo Mar 3, 2023
9e97a44
Simplify version satisfies
alalazo Mar 3, 2023
00f68d9
Add a comment clarifying invariant when entering a function
alalazo Mar 3, 2023
cf3a79a
Inline Spec._satisfies_dependency
alalazo Mar 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/spack/spack/abi.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def architecture_compatible(self, target, constraint):
return (
not target.architecture
or not constraint.architecture
or target.architecture.satisfies(constraint.architecture)
or target.architecture.intersects(constraint.architecture)
)

@memoized
Expand Down Expand Up @@ -104,7 +104,7 @@ def compiler_compatible(self, parent, child, **kwargs):
for cversion in child.compiler.versions:
# For a few compilers use specialized comparisons.
# Otherwise match on version match.
if pversion.satisfies(cversion):
if pversion.intersects(cversion):
return True
elif parent.compiler.name == "gcc" and self._gcc_compiler_compare(
pversion, cversion
Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ def _version_constraints_are_satisfiable_by_some_version_in_repo(pkgs, error_cls
dependency_pkg_cls = None
try:
dependency_pkg_cls = spack.repo.path.get_pkg_class(s.name)
assert any(v.satisfies(s.versions) for v in list(dependency_pkg_cls.versions))
assert any(v.intersects(s.versions) for v in list(dependency_pkg_cls.versions))
except Exception:
summary = (
"{0}: dependency on {1} cannot be satisfied " "by known versions of {1.name}"
Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/bootstrap/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def _install_and_test(self, abstract_spec, bincache_platform, bincache_data, tes
# This will be None for things that don't depend on python
python_spec = item.get("python", None)
# Skip specs which are not compatible
if not abstract_spec.satisfies(candidate_spec):
if not abstract_spec.intersects(candidate_spec):
continue

if python_spec is not None and python_spec not in abstract_spec:
Expand Down
4 changes: 2 additions & 2 deletions lib/spack/spack/ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ def append_dep(s, d):


def _spec_matches(spec, match_string):
return spec.satisfies(match_string)
return spec.intersects(match_string)


def _remove_attributes(src_dict, dest_dict):
Expand Down Expand Up @@ -938,7 +938,7 @@ def generate_gitlab_ci_yaml(
bs_arch = c_spec.architecture
bs_arch_family = bs_arch.target.microarchitecture.family
if (
c_spec.satisfies(compiler_pkg_spec)
c_spec.intersects(compiler_pkg_spec)
and bs_arch_family == spec_arch_family
):
# We found the bootstrap compiler this release spec
Expand Down
4 changes: 2 additions & 2 deletions lib/spack/spack/cmd/buildcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,11 +498,11 @@ def list_fn(args):

if not args.allarch:
arch = spack.spec.Spec.default_arch()
specs = [s for s in specs if s.satisfies(arch)]
specs = [s for s in specs if s.intersects(arch)]

if args.specs:
constraints = set(args.specs)
specs = [s for s in specs if any(s.satisfies(c) for c in constraints)]
specs = [s for s in specs if any(s.intersects(c) for c in constraints)]
if sys.stdout.isatty():
builds = len(specs)
tty.msg("%s." % plural(builds, "cached build"))
Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/cmd/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ def print_tests(pkg):
c_names = ("gcc", "intel", "intel-parallel-studio", "pgi")
if pkg.name in c_names:
v_names.extend(["c", "cxx", "fortran"])
if pkg.spec.satisfies("llvm+clang"):
if pkg.spec.intersects("llvm+clang"):
v_names.extend(["c", "cxx"])
# TODO Refactor END

Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/cmd/mirror.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def not_excluded_fn(args):
exclude_specs.extend(spack.cmd.parse_specs(str(args.exclude_specs).split()))

def not_excluded(x):
return not any(x.satisfies(y, strict=True) for y in exclude_specs)
return not any(x.satisfies(y) for y in exclude_specs)

return not_excluded

Expand Down
6 changes: 3 additions & 3 deletions lib/spack/spack/concretize.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def _valid_virtuals_and_externals(self, spec):

externals = spec_externals(cspec)
for ext in externals:
if ext.satisfies(spec):
if ext.intersects(spec):
usable.append(ext)

# If nothing is in the usable list now, it's because we aren't
Expand Down Expand Up @@ -200,7 +200,7 @@ def concretize_version(self, spec):

# List of versions we could consider, in sorted order
pkg_versions = spec.package_class.versions
usable = [v for v in pkg_versions if any(v.satisfies(sv) for sv in spec.versions)]
usable = [v for v in pkg_versions if any(v.intersects(sv) for sv in spec.versions)]

yaml_prefs = PackagePrefs(spec.name, "version")

Expand Down Expand Up @@ -344,7 +344,7 @@ def concretize_architecture(self, spec):
new_target_arch = spack.spec.ArchSpec((None, None, str(new_target)))
curr_target_arch = spack.spec.ArchSpec((None, None, str(curr_target)))

if not new_target_arch.satisfies(curr_target_arch):
if not new_target_arch.intersects(curr_target_arch):
# new_target is an incorrect guess based on preferences
# and/or default
valid_target_ranges = str(curr_target).split(",")
Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,7 @@ def _query(
if not (start_date < inst_date < end_date):
continue

if query_spec is any or rec.spec.satisfies(query_spec, strict=True):
if query_spec is any or rec.spec.satisfies(query_spec):
results.append(rec.spec)

return results
Expand Down
5 changes: 3 additions & 2 deletions lib/spack/spack/environment/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,8 @@ def _is_dev_spec_and_has_changed(spec):

def _spec_needs_overwrite(spec, changed_dev_specs):
"""Check whether the current spec needs to be overwritten because either it has
changed itself or one of its dependencies have changed"""
changed itself or one of its dependencies have changed
"""
# if it's not installed, we don't need to overwrite it
if not spec.installed:
return False
Expand Down Expand Up @@ -2313,7 +2314,7 @@ def _concretize_from_constraints(spec_constraints, tests=False):
invalid_deps = [
c
for c in spec_constraints
if any(c.satisfies(invd, strict=True) for invd in invalid_deps_string)
if any(c.satisfies(invd) for invd in invalid_deps_string)
]
if len(invalid_deps) != len(invalid_deps_string):
raise e
Expand Down
16 changes: 13 additions & 3 deletions lib/spack/spack/fetch_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,7 @@ def _from_merged_attrs(fetcher, pkg, version):
return fetcher(**attrs)


def for_package_version(pkg, version):
def for_package_version(pkg, version=None):
"""Determine a fetch strategy based on the arguments supplied to
version() in the package description."""

Expand All @@ -1514,8 +1514,18 @@ def for_package_version(pkg, version):

check_pkg_attributes(pkg)

if not isinstance(version, spack.version.VersionBase):
version = spack.version.Version(version)
if version is not None:
Copy link
Copy Markdown
Member

@haampie haampie Mar 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow this, can you at least add a comment as to why this is mutating pkg.spec? Looks a bit unexpected...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue here is the following. When we initialize a Spec just by name we do:

self.versions = vn.VersionList(":")

There are contexts in which we want to extrapolate a version url from an abstract spec with just the name. Sometimes this means calling url_for_version, which has an unfortunate API:

def url_for_version(self, version):
if self.spec.satisfies("@:0.94i"):
url = "https://github.com/cddlib/cddlib/archive/refs/tags/{0}.tar.gz"
elif self.spec.satisfies("@0.94j:"):
url = "https://github.com/cddlib/cddlib/releases/download/{0}/cddlib-{0}.tar.gz"
return url.format(version.dotted)

where we pass the version as a string. Thus for any comparison we relied on satisfies(..., strict=False) i.e. the current intersects.

I think we don't want to have changes in packages to fit an implementation of extrapolation that can be improved later, and satisfies gives the same result as intersects for concrete specs. Thus, in contexts where we call this function with an abstract spec I currently hack the version to make it satisfy the correct branch in url_for_version.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment and an assert (for safety) in a1c1ece

assert not pkg.spec.concrete, "concrete specs should not pass the 'version=' argument"
# Specs are initialized with the universe range, if no version information is given,
# so here we make sure we always match the version passed as argument
if not isinstance(version, spack.version.VersionBase):
version = spack.version.Version(version)

version_list = spack.version.VersionList()
version_list.add(version)
pkg.spec.versions = version_list
else:
version = pkg.version

# if it's a commit, we must use a GitFetchStrategy
if isinstance(version, spack.version.GitVersion):
Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/mirror.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ def get_matching_versions(specs, num_versions=1):
break

# Generate only versions that satisfy the spec.
if spec.concrete or v.satisfies(spec.versions):
if spec.concrete or v.intersects(spec.versions):
s = spack.spec.Spec(pkg.name)
s.versions = VersionList([v])
s.variants = spec.variants.copy()
Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/modules/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def merge_config_rules(configuration, spec):
# evaluated in order of appearance in the module file
spec_configuration = module_specific_configuration.pop("all", {})
for constraint, action in module_specific_configuration.items():
if spec.satisfies(constraint, strict=True):
if spec.satisfies(constraint):
if hasattr(constraint, "override") and constraint.override:
spec_configuration = {}
update_dictionary_extending_lists(spec_configuration, action)
Expand Down
8 changes: 4 additions & 4 deletions lib/spack/spack/package_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,7 @@ def _make_fetcher(self):
# one element (the root package). In case there are resources
# associated with the package, append their fetcher to the
# composite.
root_fetcher = fs.for_package_version(self, self.version)
root_fetcher = fs.for_package_version(self)
fetcher = fs.FetchStrategyComposite() # Composite fetcher
fetcher.append(root_fetcher) # Root fetcher is always present
resources = self._get_needed_resources()
Expand Down Expand Up @@ -1311,7 +1311,7 @@ def provides(self, vpkg_name):
True if this package provides a virtual package with the specified name
"""
return any(
any(self.spec.satisfies(c) for c in constraints)
any(self.spec.intersects(c) for c in constraints)
for s, constraints in self.provided.items()
if s.name == vpkg_name
)
Expand Down Expand Up @@ -1617,7 +1617,7 @@ def content_hash(self, content=None):
# TODO: resources
if self.spec.versions.concrete:
try:
source_id = fs.for_package_version(self, self.version).source_id()
source_id = fs.for_package_version(self).source_id()
except (fs.ExtrapolationError, fs.InvalidArgsError):
# ExtrapolationError happens if the package has no fetchers defined.
# InvalidArgsError happens when there are version directives with args,
Expand Down Expand Up @@ -1780,7 +1780,7 @@ def _get_needed_resources(self):
# conflict with the spec, so we need to invoke
# when_spec.satisfies(self.spec) vs.
# self.spec.satisfies(when_spec)
if when_spec.satisfies(self.spec, strict=False):
if when_spec.intersects(self.spec):
resources.extend(resource_list)
# Sorts the resources by the length of the string representing their
# destination. Since any nested resource must contain another
Expand Down
4 changes: 2 additions & 2 deletions lib/spack/spack/package_prefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def __call__(self, spec):
# integer is the index of the first spec in order that satisfies
# spec, or it's a number larger than any position in the order.
match_index = next(
(i for i, s in enumerate(spec_order) if spec.satisfies(s)), len(spec_order)
(i for i, s in enumerate(spec_order) if spec.intersects(s)), len(spec_order)
)
if match_index < len(spec_order) and spec_order[match_index] == spec:
# If this is called with multiple specs that all satisfy the same
Expand Down Expand Up @@ -185,7 +185,7 @@ def _package(maybe_abstract_spec):
),
extra_attributes=entry.get("extra_attributes", {}),
)
if external_spec.satisfies(spec):
if external_spec.intersects(spec):
external_specs.append(external_spec)

# Defensively copy returned specs
Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/projections.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def get_projection(projections, spec):
"""
all_projection = None
for spec_like, projection in projections.items():
if spec.satisfies(spec_like, strict=True):
if spec.satisfies(spec_like):
return projection
elif spec_like == "all":
all_projection = projection
Expand Down
4 changes: 2 additions & 2 deletions lib/spack/spack/provider_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def providers_for(self, virtual_spec):
# Add all the providers that satisfy the vpkg spec.
if virtual_spec.name in self.providers:
for p_spec, spec_set in self.providers[virtual_spec.name].items():
if p_spec.satisfies(virtual_spec, deps=False):
if p_spec.intersects(virtual_spec, deps=False):
result.update(spec_set)

# Return providers in order. Defensively copy.
Expand Down Expand Up @@ -186,7 +186,7 @@ def update(self, spec):
provider_spec = provider_spec_readonly.copy()
provider_spec.compiler_flags = spec.compiler_flags.copy()

if spec.satisfies(provider_spec, deps=False):
if spec.intersects(provider_spec, deps=False):
provided_name = provided_spec.name

provider_map = self.providers.setdefault(provided_name, {})
Expand Down
4 changes: 2 additions & 2 deletions lib/spack/spack/solver/asp.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ def _compute_specs_from_answer_set(self):
key = providers[0]
candidate = answer.get(key)

if candidate and candidate.satisfies(input_spec):
if candidate and candidate.intersects(input_spec):
self._concrete_specs.append(answer[key])
self._concrete_specs_by_input[input_spec] = answer[key]
else:
Expand Down Expand Up @@ -1873,7 +1873,7 @@ def define_version_constraints(self):
for pkg_name, versions in sorted(self.version_constraints):
# version must be *one* of the ones the spec allows.
allowed_versions = [
v for v in sorted(self.possible_versions[pkg_name]) if v.satisfies(versions)
v for v in sorted(self.possible_versions[pkg_name]) if v.intersects(versions)
]

# This is needed to account for a variable number of
Expand Down
Loading