From 3e6d85c404939482cfee140b272e6dfc6b333540 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Thu, 26 Apr 2018 14:00:46 -0700 Subject: init: remove spack.concretizer global variable --- lib/spack/spack/__init__.py | 5 -- lib/spack/spack/cmd/mirror.py | 103 +++++++++++++++++++------------------ lib/spack/spack/concretize.py | 54 ++++++++++++++----- lib/spack/spack/spec.py | 19 ++++--- lib/spack/spack/test/concretize.py | 5 +- 5 files changed, 104 insertions(+), 82 deletions(-) diff --git a/lib/spack/spack/__init__.py b/lib/spack/spack/__init__.py index b6492dc1a0..2467596a34 100644 --- a/lib/spack/spack/__init__.py +++ b/lib/spack/spack/__init__.py @@ -62,11 +62,6 @@ except spack.error.SpackError as e: tty.die('while initializing Spack RepoPath:', e.message) -#: Concretizer class implements policy decisions for concretization -from spack.concretize import Concretizer -concretizer = Concretizer() - - #: Needed for test dependencies from spack.package_prefs import PackageTesting package_testing = PackageTesting() diff --git a/lib/spack/spack/cmd/mirror.py b/lib/spack/spack/cmd/mirror.py index 6777c76030..34f342fb9e 100644 --- a/lib/spack/spack/cmd/mirror.py +++ b/lib/spack/spack/cmd/mirror.py @@ -31,6 +31,7 @@ from llnl.util.tty.colify import colify import spack import spack.cmd +import spack.concretize import spack.config import spack.mirror import spack.cmd.common.arguments as arguments @@ -168,57 +169,57 @@ def mirror_create(args): """Create a directory to be used as a spack mirror, and fill it with package archives.""" # try to parse specs from the command line first. - spack.concretizer.disable_compiler_existence_check() - specs = spack.cmd.parse_specs(args.specs, concretize=True) - - # If there is a file, parse each line as a spec and add it to the list. - if args.file: - if specs: - tty.die("Cannot pass specs on the command line with --file.") - specs = _read_specs_from_file(args.file) - - # If nothing is passed, use all packages. - if not specs: - specs = [Spec(n) for n in spack.repo.all_package_names()] - specs.sort(key=lambda s: s.format("$_$@").lower()) - - # If the user asked for dependencies, traverse spec DAG get them. - if args.dependencies: - new_specs = set() - for spec in specs: - spec.concretize() - for s in spec.traverse(): - new_specs.add(s) - specs = list(new_specs) - - # Default name for directory is spack-mirror- - directory = args.directory - if not directory: - timestamp = datetime.now().strftime("%Y-%m-%d") - directory = 'spack-mirror-' + timestamp - - # Make sure nothing is in the way. - existed = False - if os.path.isfile(directory): - tty.error("%s already exists and is a file." % directory) - elif os.path.isdir(directory): - existed = True - - # Actually do the work to create the mirror - present, mirrored, error = spack.mirror.create( - directory, specs, num_versions=args.one_version_per_spec) - p, m, e = len(present), len(mirrored), len(error) - - verb = "updated" if existed else "created" - tty.msg( - "Successfully %s mirror in %s" % (verb, directory), - "Archive stats:", - " %-4d already present" % p, - " %-4d added" % m, - " %-4d failed to fetch." % e) - if error: - tty.error("Failed downloads:") - colify(s.cformat("$_$@") for s in error) + with spack.concretize.disable_compiler_existence_check(): + specs = spack.cmd.parse_specs(args.specs, concretize=True) + + # If there is a file, parse each line as a spec and add it to the list. + if args.file: + if specs: + tty.die("Cannot pass specs on the command line with --file.") + specs = _read_specs_from_file(args.file) + + # If nothing is passed, use all packages. + if not specs: + specs = [Spec(n) for n in spack.repo.all_package_names()] + specs.sort(key=lambda s: s.format("$_$@").lower()) + + # If the user asked for dependencies, traverse spec DAG get them. + if args.dependencies: + new_specs = set() + for spec in specs: + spec.concretize() + for s in spec.traverse(): + new_specs.add(s) + specs = list(new_specs) + + # Default name for directory is spack-mirror- + directory = args.directory + if not directory: + timestamp = datetime.now().strftime("%Y-%m-%d") + directory = 'spack-mirror-' + timestamp + + # Make sure nothing is in the way. + existed = False + if os.path.isfile(directory): + tty.error("%s already exists and is a file." % directory) + elif os.path.isdir(directory): + existed = True + + # Actually do the work to create the mirror + present, mirrored, error = spack.mirror.create( + directory, specs, num_versions=args.one_version_per_spec) + p, m, e = len(present), len(mirrored), len(error) + + verb = "updated" if existed else "created" + tty.msg( + "Successfully %s mirror in %s" % (verb, directory), + "Archive stats:", + " %-4d already present" % p, + " %-4d added" % m, + " %-4d failed to fetch." % e) + if error: + tty.error("Failed downloads:") + colify(s.cformat("$_$@") for s in error) def mirror(parser, args): diff --git a/lib/spack/spack/concretize.py b/lib/spack/spack/concretize.py index 6efc365b5d..c38dfd024a 100644 --- a/lib/spack/spack/concretize.py +++ b/lib/spack/spack/concretize.py @@ -36,6 +36,7 @@ TODO: make this customizable and allow users to configure from __future__ import print_function from itertools import chain from functools_backport import reverse_order +from contextlib import contextmanager from six import iteritems import spack @@ -47,23 +48,48 @@ import spack.error from spack.version import ver, Version, VersionList, VersionRange from spack.package_prefs import PackagePrefs, spec_externals, is_spec_buildable +#: controls whether we check that compiler versions actually exist during +#: concretization. Used for testing. +check_for_compiler_existence = True + + +#: Concretizer singleton +_concretizer = None + #: impements rudimentary logic for ABI compatibility -abi = spack.abi.ABI() +_abi_checker = None + + +def _abi(): + """Get an ABI checker object.""" + global _abi_checker + if _abi_checker is None: + _abi_checker = spack.abi.ABI() + return _abi_checker + + +def concretizer(): + """Get concretizer singleton.""" + global _concretizer + if _concretizer is None: + _concretizer = Concretizer() + return _concretizer + + +@contextmanager +def disable_compiler_existence_check(): + global check_for_compiler_existence + saved = check_for_compiler_existence + check_for_compiler_existence = False + yield + check_for_compiler_existence = saved class Concretizer(object): """You can subclass this class to override some of the default concretization strategies, or you can override all of them. """ - def __init__(self): - self.check_for_compiler_existence = True - - def disable_compiler_existence_check(self): - self.check_for_compiler_existence = False - - def enable_compiler_existence_check(self): - self.check_for_compiler_existence = True def _valid_virtuals_and_externals(self, spec): """Returns a list of candidate virtual dep providers and external @@ -137,8 +163,8 @@ class Concretizer(object): return sorted(candidates, reverse=True, key=lambda spec: ( - abi.compatible(spec, abi_exemplar, loose=True), - abi.compatible(spec, abi_exemplar))) + _abi().compatible(spec, abi_exemplar, loose=True), + _abi().compatible(spec, abi_exemplar))) def concretize_version(self, spec): """If the spec is already concrete, return. Otherwise take @@ -299,7 +325,7 @@ class Concretizer(object): return spack.compilers.compilers_for_spec(cspec, arch_spec=aspec) if spec.compiler and spec.compiler.concrete: - if (self.check_for_compiler_existence and not + if (check_for_compiler_existence and not _proper_compiler_style(spec.compiler, spec.architecture)): _compiler_concretization_failure( spec.compiler, spec.architecture) @@ -313,7 +339,7 @@ class Concretizer(object): # Check if the compiler is already fully specified if (other_compiler and other_compiler.concrete and - not self.check_for_compiler_existence): + not check_for_compiler_existence): spec.compiler = other_compiler.copy() return True @@ -407,7 +433,7 @@ class Concretizer(object): compiler = spack.compilers.compiler_for_spec( spec.compiler, spec.architecture) except spack.compilers.NoCompilerForSpecError: - if self.check_for_compiler_existence: + if check_for_compiler_existence: raise return ret for flag in compiler.flags: diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index 72b83440df..cb21e551f0 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -1675,13 +1675,15 @@ class Spec(object): # to presets below, their constraints will all be merged, but we'll # still need to select a concrete package later. if not self.virtual: + import spack.concretize + concretizer = spack.concretize.concretizer() changed |= any( - (spack.concretizer.concretize_architecture(self), - spack.concretizer.concretize_compiler(self), - spack.concretizer.concretize_compiler_flags( - self), # has to be concretized after compiler - spack.concretizer.concretize_version(self), - spack.concretizer.concretize_variants(self))) + (concretizer.concretize_architecture(self), + concretizer.concretize_compiler(self), + # flags must be concretized after compiler + concretizer.concretize_compiler_flags(self), + concretizer.concretize_version(self), + concretizer.concretize_variants(self))) presets[self.name] = self visited.add(self.name) @@ -1742,8 +1744,9 @@ class Spec(object): if not replacement: # Get a list of possible replacements in order of # preference. - candidates = spack.concretizer.choose_virtual_or_external( - spec) + import spack.concretize + concretizer = spack.concretize.concretizer() + candidates = concretizer.choose_virtual_or_external(spec) # Try the replacements in order, skipping any that cause # satisfiability problems. diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index f23c20fd6e..989699bbf3 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -152,13 +152,10 @@ class TestConcretize(object): with pytest.raises(spack.concretize.UnavailableCompilerVersionError): check_concretize('dttop %gcc@100.100') - try: - spack.concretizer.disable_compiler_existence_check() + with spack.concretize.disable_compiler_existence_check(): spec = check_concretize('dttop %gcc@100.100') assert spec.satisfies('%gcc@100.100') assert spec['dtlink3'].satisfies('%gcc@100.100') - finally: - spack.concretizer.enable_compiler_existence_check() def test_concretize_with_provides_when(self): """Make sure insufficient versions of MPI are not in providers list when -- cgit v1.2.3-70-g09d2