From 2970a50ef6bd8349e8d6f6b722431f38fb9902c3 Mon Sep 17 00:00:00 2001 From: Mario Melara Date: Fri, 23 Mar 2018 12:05:07 -0700 Subject: Add the ability to separate architecture in path scheme (#4329) * Add format to separate target and os for path spec format can now handle separations of target and os for setting up the path. * Added ${PLATFORM} et al to spec.format() ${PLATFORM}, ${OS}, ${TARGET} * Update tests Updated tests and got rid of unnecessary code. * Also update documentation to reflect this new ability. * Add default path scheme to config.yaml Added default path scheme to config.yaml. Users can overwrite this section if they want. --- lib/spack/spack/spec.py | 23 +++++++++++++---- lib/spack/spack/test/directory_layout.py | 8 +++++- lib/spack/spack/test/spec_semantics.py | 42 ++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index 35ab59f76a..a88cb3f62a 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -2905,6 +2905,9 @@ class Spec(object): ${COMPILERFLAGS} Compiler flags ${OPTIONS} Options ${ARCHITECTURE} Architecture + ${PLATFORM} Platform + ${OS} Operating System + ${TARGET} Target ${SHA1} Dependencies 8-char sha1 prefix ${HASH:len} DAG hash with optional length specifier @@ -3062,12 +3065,22 @@ class Spec(object): elif named_str == 'OPTIONS': if self.variants: write(fmt % token_transform(str(self.variants)), '+') - elif named_str == 'ARCHITECTURE': + elif named_str in ["ARCHITECTURE", "PLATFORM", "TARGET", "OS"]: if self.architecture and str(self.architecture): - write( - fmt % token_transform(str(self.architecture)), - '=' - ) + if named_str == "ARCHITECTURE": + write( + fmt % token_transform(str(self.architecture)), + '=' + ) + elif named_str == "PLATFORM": + platform = str(self.architecture.platform) + write(fmt % token_transform(platform), '=') + elif named_str == "OS": + operating_sys = str(self.architecture.platform_os) + write(fmt % token_transform(operating_sys), '=') + elif named_str == "TARGET": + target = str(self.architecture.target) + write(fmt % token_transform(target), '=') elif named_str == 'SHA1': if self.dependencies: out.write(fmt % token_transform(str(self.dag_hash(7)))) diff --git a/lib/spack/spack/test/directory_layout.py b/lib/spack/spack/test/directory_layout.py index b166ea4eac..e5fb8c7a29 100644 --- a/lib/spack/spack/test/directory_layout.py +++ b/lib/spack/spack/test/directory_layout.py @@ -74,13 +74,19 @@ def test_yaml_directory_layout_parameters( # Test path_scheme arch, compiler, package7 = path_7.split('/') scheme_package7 = "${PACKAGE}-${VERSION}-${HASH:7}" - layout_package7 = YamlDirectoryLayout(str(tmpdir), path_scheme=scheme_package7) path_package7 = layout_package7.relative_path_for_spec(spec) assert(package7 == path_package7) + # Test separation of architecture + arch_scheme_package = "${PLATFORM}/${TARGET}/${OS}/${PACKAGE}/${VERSION}/${HASH:7}" # NOQA: ignore=E501 + layout_arch_package = YamlDirectoryLayout(str(tmpdir), + path_scheme=arch_scheme_package) + arch_path_package = layout_arch_package.relative_path_for_spec(spec) + assert(arch_path_package == spec.format(arch_scheme_package)) + # Ensure conflicting parameters caught with pytest.raises(InvalidDirectoryLayoutParametersError): YamlDirectoryLayout(str(tmpdir), diff --git a/lib/spack/spack/test/spec_semantics.py b/lib/spack/spack/test/spec_semantics.py index 03f77992c5..4ffb458765 100644 --- a/lib/spack/spack/test/spec_semantics.py +++ b/lib/spack/spack/test/spec_semantics.py @@ -720,3 +720,45 @@ class TestSpecSematics(object): with pytest.raises(ValueError): Spec('libelf foo') + + def test_spec_formatting(self): + spec = Spec("libelf cflags=-O2") + spec.concretize() + + # Since the default is the full spec see if the string rep of + # spec is the same as the output of spec.format() + # ignoring whitespace (though should we?) + assert str(spec) == spec.format().strip() + + # Testing named strings ie ${STRING} and whether we get + # the correct component + package_segments = [("${PACKAGE}", "name"), + ("${VERSION}", "versions"), + ("${COMPILER}", "compiler"), + ("${COMPILERFLAGS}", "compiler_flags"), + ("${OPTIONS}", "variants"), + ("${ARCHITECTURE}", "architecture")] + + compiler_segments = [("${COMPILERNAME}", "name"), + ("${COMPILERVER}", "versions")] + + architecture_segments = [("${PLATFORM}", "platform"), + ("${OS}", "platform_os"), + ("${TARGET}", "target")] + + for named_str, prop in package_segments: + expected = getattr(spec, prop, "") + actual = spec.format(named_str) + assert str(expected) == actual + + compiler = spec.compiler + for named_str, prop in compiler_segments: + expected = getattr(compiler, prop, "") + actual = spec.format(named_str) + assert str(expected) == actual + + arch = spec.architecture + for named_str, prop in architecture_segments: + expected = getattr(arch, prop, "") + actual = spec.format(named_str) + assert str(expected) == actual -- cgit v1.2.3-70-g09d2