Fix a few circular deps (#46373)

This commit is contained in:
Harmen Stoppels 2024-09-16 09:15:51 +02:00 committed by GitHub
parent 02320b18f3
commit 8225b18985
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 196 additions and 226 deletions

View File

@ -3,6 +3,13 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import re
from typing import Optional
import spack.paths
import spack.util.git
#: PEP440 canonical <major>.<minor>.<micro>.<devN> string #: PEP440 canonical <major>.<minor>.<micro>.<devN> string
__version__ = "0.23.0.dev0" __version__ = "0.23.0.dev0"
spack_version = __version__ spack_version = __version__
@ -19,4 +26,47 @@ def __try_int(v):
spack_version_info = tuple([__try_int(v) for v in __version__.split(".")]) spack_version_info = tuple([__try_int(v) for v in __version__.split(".")])
__all__ = ["spack_version_info", "spack_version"] def get_spack_commit() -> Optional[str]:
"""Get the Spack git commit sha.
Returns:
(str or None) the commit sha if available, otherwise None
"""
git_path = os.path.join(spack.paths.prefix, ".git")
if not os.path.exists(git_path):
return None
git = spack.util.git.git()
if not git:
return None
rev = git(
"-C",
spack.paths.prefix,
"rev-parse",
"HEAD",
output=str,
error=os.devnull,
fail_on_error=False,
)
if git.returncode != 0:
return None
match = re.match(r"[a-f\d]{7,}$", rev)
return match.group(0) if match else None
def get_version() -> str:
"""Get a descriptive version of this instance of Spack.
Outputs '<PEP440 version> (<git commit sha>)'.
The commit sha is only added when available.
"""
commit = get_spack_commit()
if commit:
return f"{spack_version} ({commit})"
return spack_version
__all__ = ["spack_version_info", "spack_version", "get_version", "get_spack_commit"]

View File

@ -44,6 +44,7 @@
import spack.oci.image import spack.oci.image
import spack.oci.oci import spack.oci.oci
import spack.oci.opener import spack.oci.opener
import spack.paths
import spack.platforms import spack.platforms
import spack.relocate as relocate import spack.relocate as relocate
import spack.repo import spack.repo
@ -1447,7 +1448,9 @@ def _oci_push_pkg_blob(
filename = os.path.join(tmpdir, f"{spec.dag_hash()}.tar.gz") filename = os.path.join(tmpdir, f"{spec.dag_hash()}.tar.gz")
# Create an oci.image.layer aka tarball of the package # Create an oci.image.layer aka tarball of the package
compressed_tarfile_checksum, tarfile_checksum = spack.oci.oci.create_tarball(spec, filename) compressed_tarfile_checksum, tarfile_checksum = _do_create_tarball(
filename, spec.prefix, get_buildinfo_dict(spec)
)
blob = spack.oci.oci.Blob( blob = spack.oci.oci.Blob(
Digest.from_sha256(compressed_tarfile_checksum), Digest.from_sha256(compressed_tarfile_checksum),

View File

@ -13,7 +13,6 @@
import spack.config import spack.config
import spack.error import spack.error
import spack.fetch_strategy import spack.fetch_strategy
import spack.mirror
import spack.paths import spack.paths
import spack.util.file_cache import spack.util.file_cache
import spack.util.path import spack.util.path

View File

@ -1219,8 +1219,8 @@ def main_script_replacements(cmd):
# Capture the version of Spack used to generate the pipeline, that can be # Capture the version of Spack used to generate the pipeline, that can be
# passed to `git checkout` for version consistency. If we aren't in a Git # passed to `git checkout` for version consistency. If we aren't in a Git
# repository, presume we are a Spack release and use the Git tag instead. # repository, presume we are a Spack release and use the Git tag instead.
spack_version = spack.main.get_version() spack_version = spack.get_version()
version_to_clone = spack.main.get_spack_commit() or f"v{spack.spack_version}" version_to_clone = spack.get_spack_commit() or f"v{spack.spack_version}"
output_object["variables"] = { output_object["variables"] = {
"SPACK_ARTIFACTS_ROOT": rel_artifacts_root, "SPACK_ARTIFACTS_ROOT": rel_artifacts_root,

View File

@ -13,11 +13,11 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import working_dir from llnl.util.filesystem import working_dir
import spack
import spack.config import spack.config
import spack.paths import spack.paths
import spack.platforms import spack.platforms
import spack.util.git import spack.util.git
from spack.main import get_version
from spack.util.executable import which from spack.util.executable import which
description = "debugging commands for troubleshooting Spack" description = "debugging commands for troubleshooting Spack"
@ -89,7 +89,7 @@ def report(args):
host_os = host_platform.operating_system("frontend") host_os = host_platform.operating_system("frontend")
host_target = host_platform.target("frontend") host_target = host_platform.target("frontend")
architecture = spack.spec.ArchSpec((str(host_platform), str(host_os), str(host_target))) architecture = spack.spec.ArchSpec((str(host_platform), str(host_os), str(host_target)))
print("* **Spack:**", get_version()) print("* **Spack:**", spack.get_version())
print("* **Python:**", platform.python_version()) print("* **Python:**", platform.python_version())
print("* **Platform:**", architecture) print("* **Platform:**", architecture)

View File

@ -6,6 +6,7 @@
convenience functions. convenience functions.
""" """
import copy import copy
import shlex
from collections import namedtuple from collections import namedtuple
from typing import Optional from typing import Optional
@ -15,7 +16,7 @@
import spack.tengine as tengine import spack.tengine as tengine
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
from ..images import ( from .images import (
bootstrap_template_for, bootstrap_template_for,
build_info, build_info,
checkout_command, checkout_command,
@ -308,7 +309,54 @@ def __call__(self):
return t.render(**self.to_dict()) return t.render(**self.to_dict())
# Import after function definition all the modules in this package, @writer("docker")
# so that registration of writers will happen automatically class DockerContext(PathContext):
from . import docker # noqa: F401 E402 """Context used to instantiate a Dockerfile"""
from . import singularity # noqa: F401 E402
#: Name of the template used for Dockerfiles
template_name = "container/Dockerfile"
@tengine.context_property
def manifest(self):
manifest_str = super().manifest
# Docker doesn't support HEREDOC, so we need to resort to
# a horrible echo trick to have the manifest in the Dockerfile
echoed_lines = []
for idx, line in enumerate(manifest_str.split("\n")):
quoted_line = shlex.quote(line)
if idx == 0:
echoed_lines.append("&& (echo " + quoted_line + " \\")
continue
echoed_lines.append("&& echo " + quoted_line + " \\")
echoed_lines[-1] = echoed_lines[-1].replace(" \\", ")")
return "\n".join(echoed_lines)
@writer("singularity")
class SingularityContext(PathContext):
"""Context used to instantiate a Singularity definition file"""
#: Name of the template used for Singularity definition files
template_name = "container/singularity.def"
@property
def singularity_config(self):
return self.container_config.get("singularity", {})
@tengine.context_property
def runscript(self):
return self.singularity_config.get("runscript", "")
@tengine.context_property
def startscript(self):
return self.singularity_config.get("startscript", "")
@tengine.context_property
def test(self):
return self.singularity_config.get("test", "")
@tengine.context_property
def help(self):
return self.singularity_config.get("help", "")

View File

@ -1,34 +0,0 @@
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import shlex
import spack.tengine as tengine
from . import PathContext, writer
@writer("docker")
class DockerContext(PathContext):
"""Context used to instantiate a Dockerfile"""
#: Name of the template used for Dockerfiles
template_name = "container/Dockerfile"
@tengine.context_property
def manifest(self):
manifest_str = super().manifest
# Docker doesn't support HEREDOC, so we need to resort to
# a horrible echo trick to have the manifest in the Dockerfile
echoed_lines = []
for idx, line in enumerate(manifest_str.split("\n")):
quoted_line = shlex.quote(line)
if idx == 0:
echoed_lines.append("&& (echo " + quoted_line + " \\")
continue
echoed_lines.append("&& echo " + quoted_line + " \\")
echoed_lines[-1] = echoed_lines[-1].replace(" \\", ")")
return "\n".join(echoed_lines)

View File

@ -1,35 +0,0 @@
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import spack.tengine as tengine
from . import PathContext, writer
@writer("singularity")
class SingularityContext(PathContext):
"""Context used to instantiate a Singularity definition file"""
#: Name of the template used for Singularity definition files
template_name = "container/singularity.def"
@property
def singularity_config(self):
return self.container_config.get("singularity", {})
@tengine.context_property
def runscript(self):
return self.singularity_config.get("runscript", "")
@tengine.context_property
def startscript(self):
return self.singularity_config.get("startscript", "")
@tengine.context_property
def test(self):
return self.singularity_config.get("test", "")
@tengine.context_property
def help(self):
return self.singularity_config.get("help", "")

View File

@ -24,25 +24,20 @@
from llnl.util.link_tree import ConflictingSpecsError from llnl.util.link_tree import ConflictingSpecsError
from llnl.util.symlink import readlink, symlink from llnl.util.symlink import readlink, symlink
import spack
import spack.caches import spack.caches
import spack.cmd
import spack.compilers import spack.compilers
import spack.concretize import spack.concretize
import spack.config import spack.config
import spack.deptypes as dt import spack.deptypes as dt
import spack.error import spack.error
import spack.fetch_strategy
import spack.filesystem_view as fsv import spack.filesystem_view as fsv
import spack.hash_types as ht import spack.hash_types as ht
import spack.hooks
import spack.main
import spack.paths import spack.paths
import spack.repo import spack.repo
import spack.schema.env import spack.schema.env
import spack.spec import spack.spec
import spack.stage
import spack.store import spack.store
import spack.subprocess_context
import spack.user_environment as uenv import spack.user_environment as uenv
import spack.util.cpus import spack.util.cpus
import spack.util.environment import spack.util.environment
@ -53,7 +48,6 @@
import spack.util.spack_json as sjson import spack.util.spack_json as sjson
import spack.util.spack_yaml as syaml import spack.util.spack_yaml as syaml
import spack.util.url import spack.util.url
import spack.version
from spack import traverse from spack import traverse
from spack.installer import PackageInstaller from spack.installer import PackageInstaller
from spack.schema.env import TOP_LEVEL_KEY from spack.schema.env import TOP_LEVEL_KEY
@ -2179,7 +2173,7 @@ def _to_lockfile_dict(self):
root_specs = self._concrete_roots_dict() root_specs = self._concrete_roots_dict()
spack_dict = {"version": spack.spack_version} spack_dict = {"version": spack.spack_version}
spack_commit = spack.main.get_spack_commit() spack_commit = spack.get_spack_commit()
if spack_commit: if spack_commit:
spack_dict["type"] = "git" spack_dict["type"] = "git"
spack_dict["commit"] = spack_commit spack_dict["commit"] = spack_commit

View File

@ -132,3 +132,15 @@ def __init__(self, provided, required, constraint_type):
class FetchError(SpackError): class FetchError(SpackError):
"""Superclass for fetch-related errors.""" """Superclass for fetch-related errors."""
class NoSuchPatchError(SpackError):
"""Raised when a patch file doesn't exist."""
class PatchDirectiveError(SpackError):
"""Raised when the wrong arguments are suppled to the patch directive."""
class PatchLookupError(NoSuchPatchError):
"""Raised when a patch file cannot be located from sha256."""

View File

@ -32,6 +32,7 @@
import llnl.util.tty.color as color import llnl.util.tty.color as color
from llnl.util.tty.log import log_output from llnl.util.tty.log import log_output
import spack
import spack.cmd import spack.cmd
import spack.config import spack.config
import spack.environment as ev import spack.environment as ev
@ -44,8 +45,6 @@
import spack.store import spack.store
import spack.util.debug import spack.util.debug
import spack.util.environment import spack.util.environment
import spack.util.git
import spack.util.path
from spack.error import SpackError from spack.error import SpackError
#: names of profile statistics #: names of profile statistics
@ -122,51 +121,6 @@ def add_all_commands(parser):
parser.add_command(cmd) parser.add_command(cmd)
def get_spack_commit():
"""Get the Spack git commit sha.
Returns:
(str or None) the commit sha if available, otherwise None
"""
git_path = os.path.join(spack.paths.prefix, ".git")
if not os.path.exists(git_path):
return None
git = spack.util.git.git()
if not git:
return None
rev = git(
"-C",
spack.paths.prefix,
"rev-parse",
"HEAD",
output=str,
error=os.devnull,
fail_on_error=False,
)
if git.returncode != 0:
return None
match = re.match(r"[a-f\d]{7,}$", rev)
return match.group(0) if match else None
def get_version():
"""Get a descriptive version of this instance of Spack.
Outputs '<PEP440 version> (<git commit sha>)'.
The commit sha is only added when available.
"""
version = spack.spack_version
commit = get_spack_commit()
if commit:
version += " ({0})".format(commit)
return version
def index_commands(): def index_commands():
"""create an index of commands by section for this help level""" """create an index of commands by section for this help level"""
index = {} index = {}
@ -954,7 +908,7 @@ def _main(argv=None):
# version is special as it does not require a command or loading and additional infrastructure # version is special as it does not require a command or loading and additional infrastructure
if args.version: if args.version:
print(get_version()) print(spack.get_version())
return 0 return 0
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------

View File

@ -15,7 +15,6 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.binary_distribution
import spack.config import spack.config
import spack.error import spack.error
import spack.fetch_strategy import spack.fetch_strategy
@ -37,11 +36,6 @@ class Blob(NamedTuple):
size: int size: int
def create_tarball(spec: spack.spec.Spec, tarfile_path):
buildinfo = spack.binary_distribution.get_buildinfo_dict(spec)
return spack.binary_distribution._do_create_tarball(tarfile_path, spec.prefix, buildinfo)
def with_query_param(url: str, param: str, value: str) -> str: def with_query_param(url: str, param: str, value: str) -> str:
"""Add a query parameter to a URL """Add a query parameter to a URL

View File

@ -65,6 +65,7 @@
install_test_root, install_test_root,
) )
from spack.installer import InstallError, PackageInstaller from spack.installer import InstallError, PackageInstaller
from spack.solver.version_order import concretization_version_order
from spack.stage import DevelopStage, ResourceStage, Stage, StageComposite, compute_stage_name from spack.stage import DevelopStage, ResourceStage, Stage, StageComposite, compute_stage_name
from spack.util.executable import ProcessError, which from spack.util.executable import ProcessError, which
from spack.util.package_hash import package_hash from spack.util.package_hash import package_hash
@ -116,7 +117,6 @@ def preferred_version(pkg: "PackageBase"):
Arguments: Arguments:
pkg: The package whose versions are to be assessed. pkg: The package whose versions are to be assessed.
""" """
from spack.solver.asp import concretization_version_order
version, _ = max(pkg.versions.items(), key=concretization_version_order) version, _ = max(pkg.versions.items(), key=concretization_version_order)
return version return version

View File

@ -113,7 +113,7 @@ def apply(self, stage: "spack.stage.Stage") -> None:
stage: stage where source code lives stage: stage where source code lives
""" """
if not self.path or not os.path.isfile(self.path): if not self.path or not os.path.isfile(self.path):
raise NoSuchPatchError(f"No such patch: {self.path}") raise spack.error.NoSuchPatchError(f"No such patch: {self.path}")
apply_patch(stage, self.path, self.level, self.working_dir, self.reverse) apply_patch(stage, self.path, self.level, self.working_dir, self.reverse)
@ -275,14 +275,14 @@ def __init__(
self.ordering_key = ordering_key self.ordering_key = ordering_key
if allowed_archive(self.url) and not archive_sha256: if allowed_archive(self.url) and not archive_sha256:
raise PatchDirectiveError( raise spack.error.PatchDirectiveError(
"Compressed patches require 'archive_sha256' " "Compressed patches require 'archive_sha256' "
"and patch 'sha256' attributes: %s" % self.url "and patch 'sha256' attributes: %s" % self.url
) )
self.archive_sha256 = archive_sha256 self.archive_sha256 = archive_sha256
if not sha256: if not sha256:
raise PatchDirectiveError("URL patches require a sha256 checksum") raise spack.error.PatchDirectiveError("URL patches require a sha256 checksum")
self.sha256 = sha256 self.sha256 = sha256
def apply(self, stage: "spack.stage.Stage") -> None: def apply(self, stage: "spack.stage.Stage") -> None:
@ -480,7 +480,7 @@ def patch_for_package(self, sha256: str, pkg: "spack.package_base.PackageBase")
""" """
sha_index = self.index.get(sha256) sha_index = self.index.get(sha256)
if not sha_index: if not sha_index:
raise PatchLookupError( raise spack.error.PatchLookupError(
f"Couldn't find patch for package {pkg.fullname} with sha256: {sha256}" f"Couldn't find patch for package {pkg.fullname} with sha256: {sha256}"
) )
@ -490,7 +490,7 @@ def patch_for_package(self, sha256: str, pkg: "spack.package_base.PackageBase")
if patch_dict: if patch_dict:
break break
else: else:
raise PatchLookupError( raise spack.error.PatchLookupError(
f"Couldn't find patch for package {pkg.fullname} with sha256: {sha256}" f"Couldn't find patch for package {pkg.fullname} with sha256: {sha256}"
) )
@ -573,15 +573,3 @@ def _index_patches(
index[patch.sha256] = {dspec_cls.fullname: patch_dict} index[patch.sha256] = {dspec_cls.fullname: patch_dict}
return index return index
class NoSuchPatchError(spack.error.SpackError):
"""Raised when a patch file doesn't exist."""
class PatchLookupError(NoSuchPatchError):
"""Raised when a patch file cannot be located from sha256."""
class PatchDirectiveError(spack.error.SpackError):
"""Raised when the wrong arguments are suppled to the patch directive."""

View File

@ -51,7 +51,6 @@ def __call__(self):
def use_platform(new_platform): def use_platform(new_platform):
global host global host
import spack.compilers
import spack.config import spack.config
msg = '"{0}" must be an instance of Platform' msg = '"{0}" must be an instance of Platform'
@ -61,16 +60,9 @@ def use_platform(new_platform):
try: try:
host = _PickleableCallable(new_platform) host = _PickleableCallable(new_platform)
# Clear configuration and compiler caches
spack.config.CONFIG.clear_caches() spack.config.CONFIG.clear_caches()
spack.compilers._cache_config_files = []
yield new_platform yield new_platform
finally: finally:
host = original_host_fn host = original_host_fn
# Clear configuration and compiler caches
spack.config.CONFIG.clear_caches() spack.config.CONFIG.clear_caches()
spack.compilers._cache_config_files = []

View File

@ -19,9 +19,11 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.filesystem import working_dir from llnl.util.filesystem import working_dir
import spack
import spack.build_environment import spack.build_environment
import spack.fetch_strategy import spack.fetch_strategy
import spack.package_base import spack.package_base
import spack.paths
import spack.platforms import spack.platforms
import spack.util.git import spack.util.git
from spack.error import SpackError from spack.error import SpackError
@ -119,7 +121,7 @@ def __init__(self, configuration: CDashConfiguration):
git = spack.util.git.git() git = spack.util.git.git()
with working_dir(spack.paths.spack_root): with working_dir(spack.paths.spack_root):
self.revision = git("rev-parse", "HEAD", output=str).strip() self.revision = git("rev-parse", "HEAD", output=str).strip()
self.generator = "spack-{0}".format(spack.main.get_version()) self.generator = "spack-{0}".format(spack.get_version())
self.multiple_packages = False self.multiple_packages = False
def report_build_name(self, pkg_name): def report_build_name(self, pkg_name):

View File

@ -64,6 +64,7 @@
parse_term, parse_term,
) )
from .counter import FullDuplicatesCounter, MinimalDuplicatesCounter, NoDuplicatesCounter from .counter import FullDuplicatesCounter, MinimalDuplicatesCounter, NoDuplicatesCounter
from .version_order import concretization_version_order
GitOrStandardVersion = Union[spack.version.GitVersion, spack.version.StandardVersion] GitOrStandardVersion = Union[spack.version.GitVersion, spack.version.StandardVersion]
@ -579,20 +580,6 @@ def _is_checksummed_version(version_info: Tuple[GitOrStandardVersion, dict]):
return _is_checksummed_git_version(version) return _is_checksummed_git_version(version)
def concretization_version_order(version_info: Tuple[GitOrStandardVersion, dict]):
"""Version order key for concretization, where preferred > not preferred,
not deprecated > deprecated, finite > any infinite component; only if all are
the same, do we use default version ordering."""
version, info = version_info
return (
info.get("preferred", False),
not info.get("deprecated", False),
not version.isdevelop(),
not version.is_prerelease(),
version,
)
def _spec_with_default_name(spec_str, name): def _spec_with_default_name(spec_str, name):
"""Return a spec with a default name if none is provided, used for requirement specs""" """Return a spec with a default name if none is provided, used for requirement specs"""
spec = spack.spec.Spec(spec_str) spec = spack.spec.Spec(spec_str)

View File

@ -0,0 +1,21 @@
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from typing import Tuple, Union
from spack.version import GitVersion, StandardVersion
def concretization_version_order(version_info: Tuple[Union[GitVersion, StandardVersion], dict]):
"""Version order key for concretization, where preferred > not preferred,
not deprecated > deprecated, finite > any infinite component; only if all are
the same, do we use default version ordering."""
version, info = version_info
return (
info.get("preferred", False),
not info.get("deprecated", False),
not version.isdevelop(),
not version.is_prerelease(),
version,
)

View File

@ -68,6 +68,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import llnl.util.tty.color as clr import llnl.util.tty.color as clr
import spack
import spack.compiler import spack.compiler
import spack.compilers import spack.compilers
import spack.config import spack.config
@ -75,7 +76,6 @@
import spack.error import spack.error
import spack.hash_types as ht import spack.hash_types as ht
import spack.parser import spack.parser
import spack.patch
import spack.paths import spack.paths
import spack.platforms import spack.platforms
import spack.provider_index import spack.provider_index
@ -1307,7 +1307,7 @@ def copy(self, *args, **kwargs):
def tree( def tree(
specs: List["spack.spec.Spec"], specs: List["Spec"],
*, *,
color: Optional[bool] = None, color: Optional[bool] = None,
depth: bool = False, depth: bool = False,
@ -2032,7 +2032,7 @@ def _lookup_hash(self):
raise InvalidHashError(self, self.abstract_hash) raise InvalidHashError(self, self.abstract_hash)
if len(matches) != 1: if len(matches) != 1:
raise spack.spec.AmbiguousHashError( raise AmbiguousHashError(
f"Multiple packages specify hash beginning '{self.abstract_hash}'.", *matches f"Multiple packages specify hash beginning '{self.abstract_hash}'.", *matches
) )
@ -3464,7 +3464,7 @@ def patches(self):
pkg_cls = spack.repo.PATH.get_pkg_class(self.name) pkg_cls = spack.repo.PATH.get_pkg_class(self.name)
try: try:
patch = index.patch_for_package(sha256, pkg_cls) patch = index.patch_for_package(sha256, pkg_cls)
except spack.patch.PatchLookupError as e: except spack.error.PatchLookupError as e:
raise spack.error.SpecError( raise spack.error.SpecError(
f"{e}. This usually means the patch was modified or removed. " f"{e}. This usually means the patch was modified or removed. "
"To fix this, either reconcretize or use the original package " "To fix this, either reconcretize or use the original package "
@ -4535,7 +4535,7 @@ def merge_abstract_anonymous_specs(*abstract_specs: Spec):
Args: Args:
*abstract_specs: abstract specs to be merged *abstract_specs: abstract specs to be merged
""" """
merged_spec = spack.spec.Spec() merged_spec = Spec()
for current_spec_constraint in abstract_specs: for current_spec_constraint in abstract_specs:
merged_spec.constrain(current_spec_constraint, deps=False) merged_spec.constrain(current_spec_constraint, deps=False)
@ -4890,7 +4890,6 @@ def get_host_environment_metadata() -> Dict[str, str]:
"""Get the host environment, reduce to a subset that we can store in """Get the host environment, reduce to a subset that we can store in
the install directory, and add the spack version. the install directory, and add the spack version.
""" """
import spack.main
environ = get_host_environment() environ = get_host_environment()
return { return {
@ -4898,7 +4897,7 @@ def get_host_environment_metadata() -> Dict[str, str]:
"platform": environ["platform"], "platform": environ["platform"],
"host_target": environ["target"], "host_target": environ["target"],
"hostname": environ["hostname"], "hostname": environ["hostname"],
"spack_version": spack.main.get_version(), "spack_version": spack.get_version(),
"kernel_version": platform.version(), "kernel_version": platform.version(),
} }

View File

@ -305,8 +305,8 @@ def test_ci_generate_with_custom_settings(
ci_generate_test, tmp_path, mock_binary_index, monkeypatch ci_generate_test, tmp_path, mock_binary_index, monkeypatch
): ):
"""Test use of user-provided scripts and attributes""" """Test use of user-provided scripts and attributes"""
monkeypatch.setattr(spack.main, "get_version", lambda: "0.15.3") monkeypatch.setattr(spack, "get_version", lambda: "0.15.3")
monkeypatch.setattr(spack.main, "get_spack_commit", lambda: "big ol commit sha") monkeypatch.setattr(spack, "get_spack_commit", lambda: "big ol commit sha")
spack_yaml, outputfile, _ = ci_generate_test( spack_yaml, outputfile, _ = ci_generate_test(
f"""\ f"""\
spack: spack:
@ -1040,8 +1040,8 @@ def test_ci_generate_override_runner_attrs(
inherit them from the top level, as well as when we override one or inherit them from the top level, as well as when we override one or
more at the runner level""" more at the runner level"""
monkeypatch.setattr(spack, "spack_version", "0.20.0.test0") monkeypatch.setattr(spack, "spack_version", "0.20.0.test0")
monkeypatch.setattr(spack.main, "get_version", lambda: "0.20.0.test0 (blah)") monkeypatch.setattr(spack, "get_version", lambda: "0.20.0.test0 (blah)")
monkeypatch.setattr(spack.main, "get_spack_commit", lambda: git_version) monkeypatch.setattr(spack, "get_spack_commit", lambda: git_version)
spack_yaml, outputfile, _ = ci_generate_test( spack_yaml, outputfile, _ = ci_generate_test(
f"""\ f"""\
spack: spack:

View File

@ -9,9 +9,10 @@
import pytest import pytest
import spack
import spack.config import spack.config
import spack.platforms import spack.platforms
from spack.main import SpackCommand, get_version from spack.main import SpackCommand
from spack.util.executable import which from spack.util.executable import which
debug = SpackCommand("debug") debug = SpackCommand("debug")
@ -55,6 +56,6 @@ def test_report():
host_target = host_platform.target("frontend") host_target = host_platform.target("frontend")
architecture = spack.spec.ArchSpec((str(host_platform), str(host_os), str(host_target))) architecture = spack.spec.ArchSpec((str(host_platform), str(host_os), str(host_target)))
assert get_version() in out assert spack.get_version() in out
assert platform.python_version() in out assert platform.python_version() in out
assert str(architecture) in out assert str(architecture) in out

View File

@ -25,6 +25,7 @@
import spack.platforms import spack.platforms
import spack.repo import spack.repo
import spack.solver.asp import spack.solver.asp
import spack.solver.version_order
import spack.store import spack.store
import spack.util.file_cache import spack.util.file_cache
import spack.util.libc import spack.util.libc
@ -2928,7 +2929,7 @@ def test_concretization_version_order():
result = [ result = [
v v
for v, _ in sorted( for v, _ in sorted(
versions, key=spack.solver.asp.concretization_version_order, reverse=True versions, key=spack.solver.version_order.concretization_version_order, reverse=True
) )
] ]
assert result == [ assert result == [

View File

@ -8,10 +8,11 @@
import llnl.util.filesystem as fs import llnl.util.filesystem as fs
import spack
import spack.paths import spack.paths
import spack.util.executable as exe import spack.util.executable as exe
import spack.util.git import spack.util.git
from spack.main import get_version, main from spack.main import main
pytestmark = pytest.mark.not_on_windows( pytestmark = pytest.mark.not_on_windows(
"Test functionality supported but tests are failing on Win" "Test functionality supported but tests are failing on Win"
@ -29,7 +30,7 @@ def test_version_git_nonsense_output(tmpdir, working_env, monkeypatch):
fs.set_executable(git) fs.set_executable(git)
monkeypatch.setattr(spack.util.git, "git", lambda: exe.which(git)) monkeypatch.setattr(spack.util.git, "git", lambda: exe.which(git))
assert spack.spack_version == get_version() assert spack.spack_version == spack.get_version()
def test_version_git_fails(tmpdir, working_env, monkeypatch): def test_version_git_fails(tmpdir, working_env, monkeypatch):
@ -44,7 +45,7 @@ def test_version_git_fails(tmpdir, working_env, monkeypatch):
fs.set_executable(git) fs.set_executable(git)
monkeypatch.setattr(spack.util.git, "git", lambda: exe.which(git)) monkeypatch.setattr(spack.util.git, "git", lambda: exe.which(git))
assert spack.spack_version == get_version() assert spack.spack_version == spack.get_version()
def test_git_sha_output(tmpdir, working_env, monkeypatch): def test_git_sha_output(tmpdir, working_env, monkeypatch):
@ -62,17 +63,17 @@ def test_git_sha_output(tmpdir, working_env, monkeypatch):
monkeypatch.setattr(spack.util.git, "git", lambda: exe.which(git)) monkeypatch.setattr(spack.util.git, "git", lambda: exe.which(git))
expected = "{0} ({1})".format(spack.spack_version, sha) expected = "{0} ({1})".format(spack.spack_version, sha)
assert expected == get_version() assert expected == spack.get_version()
def test_get_version_no_repo(tmpdir, monkeypatch): def test_get_version_no_repo(tmpdir, monkeypatch):
monkeypatch.setattr(spack.paths, "prefix", str(tmpdir)) monkeypatch.setattr(spack.paths, "prefix", str(tmpdir))
assert spack.spack_version == get_version() assert spack.spack_version == spack.get_version()
def test_get_version_no_git(tmpdir, working_env, monkeypatch): def test_get_version_no_git(tmpdir, working_env, monkeypatch):
monkeypatch.setattr(spack.util.git, "git", lambda: None) monkeypatch.setattr(spack.util.git, "git", lambda: None)
assert spack.spack_version == get_version() assert spack.spack_version == spack.get_version()
def test_main_calls_get_version(tmpdir, capsys, working_env, monkeypatch): def test_main_calls_get_version(tmpdir, capsys, working_env, monkeypatch):
@ -96,4 +97,4 @@ def test_get_version_bad_git(tmpdir, working_env, monkeypatch):
fs.set_executable(bad_git) fs.set_executable(bad_git)
monkeypatch.setattr(spack.util.git, "git", lambda: exe.which(bad_git)) monkeypatch.setattr(spack.util.git, "git", lambda: exe.which(bad_git))
assert spack.spack_version == get_version() assert spack.spack_version == spack.get_version()

View File

@ -13,6 +13,7 @@
from llnl.util.filesystem import mkdirp, touch, working_dir from llnl.util.filesystem import mkdirp, touch, working_dir
import spack.error
import spack.patch import spack.patch
import spack.paths import spack.paths
import spack.repo import spack.repo
@ -434,7 +435,7 @@ def test_patch_no_file():
patch = spack.patch.Patch(fp, "nonexistent_file", 0, "") patch = spack.patch.Patch(fp, "nonexistent_file", 0, "")
patch.path = "test" patch.path = "test"
with pytest.raises(spack.patch.NoSuchPatchError, match="No such patch:"): with pytest.raises(spack.error.NoSuchPatchError, match="No such patch:"):
patch.apply("") patch.apply("")
@ -444,10 +445,10 @@ def test_patch_no_sha256():
fp = FakePackage("fake-package", "test", "fake-package") fp = FakePackage("fake-package", "test", "fake-package")
url = url_util.path_to_file_url("foo.tgz") url = url_util.path_to_file_url("foo.tgz")
match = "Compressed patches require 'archive_sha256' and patch 'sha256' attributes: file://" match = "Compressed patches require 'archive_sha256' and patch 'sha256' attributes: file://"
with pytest.raises(spack.patch.PatchDirectiveError, match=match): with pytest.raises(spack.error.PatchDirectiveError, match=match):
spack.patch.UrlPatch(fp, url, sha256="", archive_sha256="") spack.patch.UrlPatch(fp, url, sha256="", archive_sha256="")
match = "URL patches require a sha256 checksum" match = "URL patches require a sha256 checksum"
with pytest.raises(spack.patch.PatchDirectiveError, match=match): with pytest.raises(spack.error.PatchDirectiveError, match=match):
spack.patch.UrlPatch(fp, url, sha256="", archive_sha256="abc") spack.patch.UrlPatch(fp, url, sha256="", archive_sha256="abc")

View File

@ -12,6 +12,7 @@
import pickle import pickle
import re import re
import shlex import shlex
import subprocess
import sys import sys
from functools import wraps from functools import wraps
from typing import Any, Callable, Dict, List, MutableMapping, Optional, Tuple, Union from typing import Any, Callable, Dict, List, MutableMapping, Optional, Tuple, Union
@ -20,8 +21,6 @@
from llnl.util import tty from llnl.util import tty
from llnl.util.lang import dedupe from llnl.util.lang import dedupe
from .executable import Executable, which
if sys.platform == "win32": if sys.platform == "win32":
SYSTEM_PATHS = [ SYSTEM_PATHS = [
"C:\\", "C:\\",
@ -1034,8 +1033,6 @@ def environment_after_sourcing_files(
source_command = kwargs.get("source_command", "source") source_command = kwargs.get("source_command", "source")
concatenate_on_success = kwargs.get("concatenate_on_success", "&&") concatenate_on_success = kwargs.get("concatenate_on_success", "&&")
shell = Executable(shell_cmd)
def _source_single_file(file_and_args, environment): def _source_single_file(file_and_args, environment):
shell_options_list = shell_options.split() shell_options_list = shell_options.split()
@ -1043,26 +1040,21 @@ def _source_single_file(file_and_args, environment):
source_file.extend(x for x in file_and_args) source_file.extend(x for x in file_and_args)
source_file = " ".join(source_file) source_file = " ".join(source_file)
# If the environment contains 'python' use it, if not
# go with sys.executable. Below we just need a working
# Python interpreter, not necessarily sys.executable.
python_cmd = which("python3", "python", "python2")
python_cmd = python_cmd.path if python_cmd else sys.executable
dump_cmd = "import os, json; print(json.dumps(dict(os.environ)))" dump_cmd = "import os, json; print(json.dumps(dict(os.environ)))"
dump_environment_cmd = python_cmd + f' -E -c "{dump_cmd}"' dump_environment_cmd = sys.executable + f' -E -c "{dump_cmd}"'
# Try to source the file # Try to source the file
source_file_arguments = " ".join( source_file_arguments = " ".join(
[source_file, suppress_output, concatenate_on_success, dump_environment_cmd] [source_file, suppress_output, concatenate_on_success, dump_environment_cmd]
) )
output = shell(
*shell_options_list, with subprocess.Popen(
source_file_arguments, [shell_cmd, *shell_options_list, source_file_arguments],
output=str,
env=environment, env=environment,
ignore_quotes=True, stdout=subprocess.PIPE,
) stderr=subprocess.PIPE,
) as shell:
output, _ = shell.communicate()
return json.loads(output) return json.loads(output)

View File

@ -12,6 +12,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.error import spack.error
from spack.util.environment import EnvironmentModifications
__all__ = ["Executable", "which", "ProcessError"] __all__ = ["Executable", "which", "ProcessError"]
@ -27,7 +28,6 @@ def __init__(self, name):
self.exe = [file_path] self.exe = [file_path]
self.default_env = {} self.default_env = {}
from spack.util.environment import EnvironmentModifications # no cycle
self.default_envmod = EnvironmentModifications() self.default_envmod = EnvironmentModifications()
self.returncode = None self.returncode = None