diff --git a/lib/spack/spack/directory_layout.py b/lib/spack/spack/directory_layout.py index f97f9eb9747..b9c29a2b0cb 100644 --- a/lib/spack/spack/directory_layout.py +++ b/lib/spack/spack/directory_layout.py @@ -8,7 +8,7 @@ import shutil import sys from pathlib import Path -from typing import List, Optional, Tuple +from typing import Dict, List, Optional, Tuple import llnl.util.filesystem as fs from llnl.util.symlink import readlink @@ -69,10 +69,9 @@ def specs_from_metadata_dirs(root: str) -> List["spack.spec.Spec"]: class DirectoryLayout: - """A directory layout is used to associate unique paths with specs. - Different installations are going to want different layouts for their - install, and they can use this to customize the nesting structure of - spack installs. The default layout is: + """A directory layout is used to associate unique paths with specs. Different installations are + going to want different layouts for their install, and they can use this to customize the + nesting structure of spack installs. The default layout is: * / @@ -82,35 +81,31 @@ class DirectoryLayout: * -- - The hash here is a SHA-1 hash for the full DAG plus the build - spec. + The installation directory projections can be modified with the projections argument.""" - The installation directory projections can be modified with the - projections argument. - """ - - def __init__(self, root, **kwargs): + def __init__( + self, + root, + *, + projections: Optional[Dict[str, str]] = None, + hash_length: Optional[int] = None, + ) -> None: self.root = root self.check_upstream = True - projections = kwargs.get("projections") or default_projections - self.projections = dict( - (key, projection.lower()) for key, projection in projections.items() - ) + projections = projections or default_projections + self.projections = {key: projection.lower() for key, projection in projections.items()} # apply hash length as appropriate - self.hash_length = kwargs.get("hash_length", None) + self.hash_length = hash_length if self.hash_length is not None: for when_spec, projection in self.projections.items(): if "{hash}" not in projection: - if "{hash" in projection: - raise InvalidDirectoryLayoutParametersError( - "Conflicting options for installation layout hash" " length" - ) - else: - raise InvalidDirectoryLayoutParametersError( - "Cannot specify hash length when the hash is not" - " part of all install_tree projections" - ) + raise InvalidDirectoryLayoutParametersError( + "Conflicting options for installation layout hash length" + if "{hash" in projection + else "Cannot specify hash length when the hash is not part of all " + "install_tree projections" + ) self.projections[when_spec] = projection.replace( "{hash}", "{hash:%d}" % self.hash_length ) diff --git a/lib/spack/spack/test/bindist.py b/lib/spack/spack/test/bindist.py index c04e652654a..0845be0e4b5 100644 --- a/lib/spack/spack/test/bindist.py +++ b/lib/spack/spack/test/bindist.py @@ -43,7 +43,6 @@ import spack.util.url as url_util import spack.util.web as web_util from spack.binary_distribution import CannotListKeys, GenerateIndexError -from spack.directory_layout import DirectoryLayout from spack.paths import test_path from spack.spec import Spec @@ -136,35 +135,28 @@ def default_config(tmp_path, config_directory, monkeypatch, install_mockery): @pytest.fixture(scope="function") def install_dir_default_layout(tmpdir): """Hooks a fake install directory with a default layout""" - scheme = os.path.join( - "${architecture}", "${compiler.name}-${compiler.version}", "${name}-${version}-${hash}" - ) - real_store, real_layout = spack.store.STORE, spack.store.STORE.layout opt_dir = tmpdir.join("opt") - spack.store.STORE = spack.store.Store(str(opt_dir)) - spack.store.STORE.layout = DirectoryLayout(str(opt_dir), path_scheme=scheme) + original_store, spack.store.STORE = spack.store.STORE, spack.store.Store(str(opt_dir)) try: yield spack.store finally: - spack.store.STORE = real_store - spack.store.STORE.layout = real_layout + spack.store.STORE = original_store @pytest.fixture(scope="function") def install_dir_non_default_layout(tmpdir): """Hooks a fake install directory with a non-default layout""" - scheme = os.path.join( - "${name}", "${version}", "${architecture}-${compiler.name}-${compiler.version}-${hash}" - ) - real_store, real_layout = spack.store.STORE, spack.store.STORE.layout opt_dir = tmpdir.join("opt") - spack.store.STORE = spack.store.Store(str(opt_dir)) - spack.store.STORE.layout = DirectoryLayout(str(opt_dir), path_scheme=scheme) + original_store, spack.store.STORE = spack.store.STORE, spack.store.Store( + str(opt_dir), + projections={ + "all": "{name}/{version}/{architecture}-{compiler.name}-{compiler.version}-{hash}" + }, + ) try: yield spack.store finally: - spack.store.STORE = real_store - spack.store.STORE.layout = real_layout + spack.store.STORE = original_store @pytest.fixture(scope="function")