def test_spec_formatting_escapes(self): spec = Spec('multivalue_variant cflags=-O2') spec.concretize() sigil_mismatches = [ '{@name}', '{@version.concrete}', '{%compiler.version}', '{/hashd}', '{arch=architecture.os}' ] for fmt_str in sigil_mismatches: with pytest.raises(SpecFormatSigilError): spec.format(fmt_str) bad_formats = [ r'{}', r'name}', r'\{name}', r'{name', r'{name\}', r'{_concrete}', r'{dag_hash}', r'{foo}', r'{+variants.debug}' ] for fmt_str in bad_formats: with pytest.raises(SpecFormatStringError): spec.format(fmt_str)
def test_yaml_directory_layout_parameters(tmpdir, config): """This tests the various parameters that can be used to configure the install location """ spec = Spec('python') spec.concretize() # Ensure default layout matches expected spec format layout_default = YamlDirectoryLayout(str(tmpdir)) path_default = layout_default.relative_path_for_spec(spec) assert(path_default == spec.format( "{architecture}/" "{compiler.name}-{compiler.version}/" "{name}-{version}-{hash}")) # Test hash_length parameter works correctly layout_10 = YamlDirectoryLayout(str(tmpdir), hash_length=10) path_10 = layout_10.relative_path_for_spec(spec) layout_7 = YamlDirectoryLayout(str(tmpdir), hash_length=7) path_7 = layout_7.relative_path_for_spec(spec) assert(len(path_default) - len(path_10) == 22) assert(len(path_default) - len(path_7) == 25) # Test path_scheme arch, compiler, package7 = path_7.split('/') projections_package7 = {'all': "{name}-{version}-{hash:7}"} layout_package7 = YamlDirectoryLayout(str(tmpdir), projections=projections_package7) path_package7 = layout_package7.relative_path_for_spec(spec) assert(package7 == path_package7) # Test separation of architecture or namespace spec2 = Spec('libelf').concretized() arch_scheme = "{architecture.platform}/{architecture.target}/{architecture.os}/{name}/{version}/{hash:7}" # NOQA: ignore=E501 ns_scheme = "${ARCHITECTURE}/${NAMESPACE}/${PACKAGE}-${VERSION}-${HASH:7}" # NOQA: ignore=E501 arch_ns_scheme_projections = {'all': arch_scheme, 'python': ns_scheme} layout_arch_ns = YamlDirectoryLayout( str(tmpdir), projections=arch_ns_scheme_projections) arch_path_spec2 = layout_arch_ns.relative_path_for_spec(spec2) assert(arch_path_spec2 == spec2.format(arch_scheme)) ns_path_spec = layout_arch_ns.relative_path_for_spec(spec) assert(ns_path_spec == spec.format(ns_scheme)) # Ensure conflicting parameters caught with pytest.raises(InvalidDirectoryLayoutParametersError): YamlDirectoryLayout(str(tmpdir), hash_length=20, projections=projections_package7)
def test_yaml_directory_layout_parameters( tmpdir, config ): """This tests the various parameters that can be used to configure the install location """ spec = Spec('python') spec.concretize() # Ensure default layout matches expected spec format layout_default = YamlDirectoryLayout(str(tmpdir)) path_default = layout_default.relative_path_for_spec(spec) assert(path_default == spec.format( "${ARCHITECTURE}/" "${COMPILERNAME}-${COMPILERVER}/" "${PACKAGE}-${VERSION}-${HASH}")) # Test hash_length parameter works correctly layout_10 = YamlDirectoryLayout(str(tmpdir), hash_len=10) path_10 = layout_10.relative_path_for_spec(spec) layout_7 = YamlDirectoryLayout(str(tmpdir), hash_len=7) path_7 = layout_7.relative_path_for_spec(spec) assert(len(path_default) - len(path_10) == 22) assert(len(path_default) - len(path_7) == 25) # 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)) # Test separation of namespace ns_scheme_package = "${ARCHITECTURE}/${NAMESPACE}/${PACKAGE}-${VERSION}-${HASH:7}" # NOQA: ignore=E501 layout_ns_package = YamlDirectoryLayout(str(tmpdir), path_scheme=ns_scheme_package) ns_path_package = layout_ns_package.relative_path_for_spec(spec) assert(ns_path_package == spec.format(ns_scheme_package)) # Ensure conflicting parameters caught with pytest.raises(InvalidDirectoryLayoutParametersError): YamlDirectoryLayout(str(tmpdir), hash_len=20, path_scheme=scheme_package7)
def test_dynamic_dot_graph_mpileaks(mock_packages): """Test dynamically graphing the mpileaks package.""" s = Spec('mpileaks').normalized() stream = StringIO() graph_dot([s], static=False, out=stream) dot = stream.getvalue() mpileaks_hash, mpileaks_lbl = s.dag_hash(), s.format('$_$/') mpi_hash, mpi_lbl = s['mpi'].dag_hash(), s['mpi'].format('$_$/') callpath_hash, callpath_lbl = ( s['callpath'].dag_hash(), s['callpath'].format('$_$/')) dyninst_hash, dyninst_lbl = ( s['dyninst'].dag_hash(), s['dyninst'].format('$_$/')) libdwarf_hash, libdwarf_lbl = ( s['libdwarf'].dag_hash(), s['libdwarf'].format('$_$/')) libelf_hash, libelf_lbl = ( s['libelf'].dag_hash(), s['libelf'].format('$_$/')) assert ' "%s" [label="%s"]\n' % (mpileaks_hash, mpileaks_lbl) in dot assert ' "%s" [label="%s"]\n' % (callpath_hash, callpath_lbl) in dot assert ' "%s" [label="%s"]\n' % (mpi_hash, mpi_lbl) in dot assert ' "%s" [label="%s"]\n' % (dyninst_hash, dyninst_lbl) in dot assert ' "%s" [label="%s"]\n' % (libdwarf_hash, libdwarf_lbl) in dot assert ' "%s" [label="%s"]\n' % (libelf_hash, libelf_lbl) in dot assert ' "%s" -> "%s"\n' % (dyninst_hash, libdwarf_hash) in dot assert ' "%s" -> "%s"\n' % (callpath_hash, dyninst_hash) in dot assert ' "%s" -> "%s"\n' % (mpileaks_hash, mpi_hash) in dot assert ' "%s" -> "%s"\n' % (libdwarf_hash, libelf_hash) in dot assert ' "%s" -> "%s"\n' % (callpath_hash, mpi_hash) in dot assert ' "%s" -> "%s"\n' % (mpileaks_hash, callpath_hash) in dot assert ' "%s" -> "%s"\n' % (dyninst_hash, libelf_hash) in dot
def test_dynamic_dot_graph_mpileaks(mock_packages, config): """Test dynamically graphing the mpileaks package.""" s = Spec('mpileaks').concretized() stream = StringIO() graph_dot([s], static=False, out=stream) dot = stream.getvalue() print(dot) mpileaks_hash, mpileaks_lbl = s.dag_hash(), s.format('{name}') mpi_hash, mpi_lbl = s['mpi'].dag_hash(), s['mpi'].format('{name}') callpath_hash, callpath_lbl = (s['callpath'].dag_hash(), s['callpath'].format('{name}')) dyninst_hash, dyninst_lbl = (s['dyninst'].dag_hash(), s['dyninst'].format('{name}')) libdwarf_hash, libdwarf_lbl = (s['libdwarf'].dag_hash(), s['libdwarf'].format('{name}')) libelf_hash, libelf_lbl = (s['libelf'].dag_hash(), s['libelf'].format('{name}')) assert ' "%s" [label="%s"]\n' % (mpileaks_hash, mpileaks_lbl) in dot assert ' "%s" [label="%s"]\n' % (callpath_hash, callpath_lbl) in dot assert ' "%s" [label="%s"]\n' % (mpi_hash, mpi_lbl) in dot assert ' "%s" [label="%s"]\n' % (dyninst_hash, dyninst_lbl) in dot assert ' "%s" [label="%s"]\n' % (libdwarf_hash, libdwarf_lbl) in dot assert ' "%s" [label="%s"]\n' % (libelf_hash, libelf_lbl) in dot assert ' "%s" -> "%s"\n' % (dyninst_hash, libdwarf_hash) in dot assert ' "%s" -> "%s"\n' % (callpath_hash, dyninst_hash) in dot assert ' "%s" -> "%s"\n' % (mpileaks_hash, mpi_hash) in dot assert ' "%s" -> "%s"\n' % (libdwarf_hash, libelf_hash) in dot assert ' "%s" -> "%s"\n' % (callpath_hash, mpi_hash) in dot assert ' "%s" -> "%s"\n' % (mpileaks_hash, callpath_hash) in dot assert ' "%s" -> "%s"\n' % (dyninst_hash, libelf_hash) in dot
def test_yaml_directory_layout_parameters( tmpdir, config ): """This tests the various parameters that can be used to configure the install location """ spec = Spec('python') spec.concretize() # Ensure default layout matches expected spec format layout_default = YamlDirectoryLayout(str(tmpdir)) path_default = layout_default.relative_path_for_spec(spec) assert(path_default == spec.format( "${ARCHITECTURE}/" "${COMPILERNAME}-${COMPILERVER}/" "${PACKAGE}-${VERSION}-${HASH}")) # Test hash_length parameter works correctly layout_10 = YamlDirectoryLayout(str(tmpdir), hash_len=10) path_10 = layout_10.relative_path_for_spec(spec) layout_7 = YamlDirectoryLayout(str(tmpdir), hash_len=7) path_7 = layout_7.relative_path_for_spec(spec) assert(len(path_default) - len(path_10) == 22) assert(len(path_default) - len(path_7) == 25) # 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), hash_len=20, path_scheme=scheme_package7)
def test_spec_deprecated_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 # Mixed case intentional for testing both 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}", "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
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
def test_spec_formatting(self): spec = Spec("multivalue-variant 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?) and ignoring dependencies spec_string = str(spec) idx = spec_string.index(' ^') assert spec_string[:idx] == spec.format().strip() # Testing named strings ie {string} and whether we get # the correct component # Mixed case intentional to test both package_segments = [("{NAME}", "name"), ("{VERSION}", "versions"), ("{compiler}", "compiler"), ("{compiler_flags}", "compiler_flags"), ("{variants}", "variants"), ("{architecture}", "architecture")] sigil_package_segments = [("{@VERSIONS}", '@' + str(spec.version)), ("{%compiler}", '%' + str(spec.compiler)), ("{arch=architecture}", 'arch=' + str(spec.architecture))] compiler_segments = [("{compiler.name}", "name"), ("{compiler.version}", "versions")] sigil_compiler_segments = [ ("{%compiler.name}", '%' + spec.compiler.name), ("{@compiler.version}", '@' + str(spec.compiler.version)) ] architecture_segments = [("{architecture.platform}", "platform"), ("{architecture.os}", "os"), ("{architecture.target}", "target")] other_segments = [('{spack_root}', spack.paths.spack_root), ('{spack_install}', spack.store.layout.root), ('{hash:7}', spec.dag_hash(7)), ('{/hash}', '/' + spec.dag_hash())] for named_str, prop in package_segments: expected = getattr(spec, prop, "") actual = spec.format(named_str) assert str(expected).strip() == actual for named_str, expected in sigil_package_segments: actual = spec.format(named_str) assert 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 for named_str, expected in sigil_compiler_segments: actual = spec.format(named_str) assert 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 for named_str, expected in other_segments: actual = spec.format(named_str) assert expected == actual
def main(): parser = argparse.ArgumentParser( description= 'Small config script which can be used to install a spack instance with the correct configuration files and mch spack packages.' ) parser.add_argument( '-s', '--spec', type=str, help='Spack spec from which you want to extract the run environement.') parser.add_argument('-i', '--idircosmo', type=str, help='Cosmo installation directory.') parser.add_argument('-j', '--idireccodes', type=str, help='Eccodes installation directory.') args = parser.parse_args() if not args.spec: print('Need a cosmo spack spec in order to extract the environement!') if not args.idircosmo: print( 'Need an installation directory for installing cosmo and eccodes.') else: args.idircosmo = os.path.abspath(args.idircosmo) # Extract and concretize cosmo and eccodes cosmo_spec = Spec(args.spec).concretized() cosmo_dir = 'cosmo' + cosmo_spec.format('{@version}') + cosmo_spec.format( '{%compiler}') + '-' + cosmo_spec.format( '{variants.real_type.value}') + '-' + cosmo_spec.format( '{variants.cosmo_target.value}') eccodes_dir = 'eccodes' + cosmo_spec.format('{^eccodes.@version}') eccodes_definitions_dir = 'cosmo-eccodes-definitions' + cosmo_spec.format( '{^cosmo-eccodes-definitions.@version}') # Exist if cosmo installation already exists if os.path.exists(os.path.join(args.idircosmo, cosmo_dir)): sys.exit('Exit: The cosmo installation path: ' + os.path.join(args.idircosmo, cosmo_dir) + ' already exists!') print('Installing ' + cosmo_spec.format('{prefix}') + ' to: ' + os.path.join(args.idircosmo, cosmo_dir)) print('COSMO_INSTALLATION_FULL_PATH=' + os.path.join(args.idircosmo, cosmo_dir)) os.system('cp -rf ' + cosmo_spec.format('{prefix}') + ' ' + os.path.join(args.idircosmo, cosmo_dir)) # Warning if eccodes installation already exists if os.path.exists(os.path.join(args.idireccodes, eccodes_dir)): print('Warning: The eccodes installation path: ' + os.path.join(args.idireccodes, eccodes_dir) + ' already exists!') else: print('Installing ' + cosmo_spec.format('{^eccodes.prefix}') + ' to: ' + os.path.join(args.idireccodes, eccodes_dir)) print('ECCODES_INSTALLATION_FULL_PATH=' + os.path.join(args.idireccodes, eccodes_dir)) os.system('cp -rf ' + cosmo_spec.format('{^eccodes.prefix}') + ' ' + os.path.join(args.idireccodes, eccodes_dir)) # Warning if eccodes definitions installation already exists if os.path.exists(os.path.join(args.idireccodes, eccodes_definitions_dir)): print('Warning: The eccodes-definitions installation path: ' + os.path.join(args.idireccodes, eccodes_definitions_dir) + ' already exists!') else: print('Installing ' + cosmo_spec.format('{^cosmo-eccodes-definitions.prefix}') + ' to: ' + os.path.join(args.idireccodes, eccodes_definitions_dir)) print('ECCODES_DEFINITIONS_INSTALLATION_FULL_PATH=' + os.path.join(args.idireccodes, eccodes_definitions_dir)) os.system('cp -rf ' + cosmo_spec.format('{^cosmo-eccodes-definitions.prefix}') + ' ' + os.path.join(args.idireccodes, eccodes_definitions_dir)) with open('run-env', 'w') as outfile: subprocess.run(['spack load --sh ' + args.spec], shell=True, stdout=outfile) with open('run-env', 'r') as outfile: filedata = outfile.read() newdata = filedata.replace(cosmo_spec.format('{prefix}'), os.path.join(args.idircosmo, cosmo_dir)) newdata = newdata.replace(cosmo_spec.format('{^eccodes.prefix}'), os.path.join(args.idireccodes, eccodes_dir)) newdata = newdata.replace( cosmo_spec.format('{^cosmo-eccodes-definitions.prefix}'), os.path.join(args.idireccodes, eccodes_definitions_dir)) newdata = newdata.replace(bin_path + ':', '') with open('run-env', 'w') as outfile: outfile.write(newdata) print('Installing run-env file to: ' + os.path.join(args.idircosmo, cosmo_dir)) os.system('mv run-env ' + os.path.join(args.idircosmo, cosmo_dir))
def main(): parser=argparse.ArgumentParser(description='''Deployement script which can be used to install a package that depends on cosmo-eccodes-defintions at run time, e.g. cosmo or int2lm. The spack instance from which the package should be found needs to be sourced first''') parser.add_argument('-s', '--spec', type=str, help='Spack spec from which you want to extract the run environement.') parser.add_argument('-i', '--idir', type=str, help='Package installation directory') parser.add_argument('-j', '--idireccodes', type=str, help='Eccodes installation directory. Default : same locatino as idir') parser.add_argument('-f', '--force', action='store_true', help='Overwritte package installation if exists') args=parser.parse_args() if not args.spec: sys.exit('Error: missing -s package spack spec in order to extract the environement!') if not args.idir: sys.exit('Error: missing -i installation directory for installing the package and eccodes.') else: args.idir = os.path.abspath(args.idir) if not args.idireccodes: args.idireccodes = args.idir # Extract and concretize cosmo and eccodes package_spec=Spec(args.spec).concretized() print(package_spec.format('{prefix}')) package_name = package_spec.format('{name}') package_dir = package_name + package_spec.format('{@version}') + package_spec.format('{%compiler}') if package_name == 'cosmo': package_dir = package_dir + '-' + package_spec.format('{variants.real_type.value}') + '-' + package_spec.format('{variants.cosmo_target.value}') eccodes_dir = 'eccodes' + package_spec.format('{^eccodes.@version}') eccodes_definitions_dir = 'cosmo-eccodes-definitions' + package_spec.format('{^cosmo-eccodes-definitions.@version}') if os.path.exists(os.path.join(args.idir, package_dir)): if args.force: # Remove if force cosmo installation already exists print('Force : removing existing installation ' + os.path.join(args.idir, package_dir)) os.system('rm -r ' + os.path.join(args.idir, package_dir)) else: # Exit if cosmo installation already exists sys.exit('Error: The installation path: ' + os.path.join(args.idir, package_dir) + ' already exists, use -f to overwrite') print('Installing ' + package_spec.format('{prefix}') + ' to: ' + os.path.join(args.idir, package_dir)) print(package_name.upper() + '_INSTALLATION_FULL_PATH=' + os.path.join(args.idir, package_dir)) os.system('cp -rf ' + package_spec.format('{prefix}') + ' ' + os.path.join(args.idir, package_dir)) # Warning if eccodes installation already exists if os.path.exists(os.path.join(args.idireccodes, eccodes_dir)): print('Warning: The eccodes installation path: ' + os.path.join(args.idireccodes, eccodes_dir) + ' already exists, keep existing') else: print('Installing ' + package_spec.format('{^eccodes.prefix}') + ' to: ' + os.path.join(args.idireccodes, eccodes_dir)) print('ECCODES_INSTALLATION_FULL_PATH=' + os.path.join(args.idireccodes, eccodes_dir)) os.system('cp -rf ' + package_spec.format('{^eccodes.prefix}') + ' ' + os.path.join(args.idireccodes, eccodes_dir)) # Warning if eccodes definitions installation already exists if os.path.exists(os.path.join(args.idireccodes, eccodes_definitions_dir)): print('Warning: The eccodes-definitions installation path: ' + os.path.join(args.idireccodes, eccodes_definitions_dir) + ' already exists, keep existing') else: print('Installing ' + package_spec.format('{^cosmo-eccodes-definitions.prefix}') + ' to: ' + os.path.join(args.idireccodes, eccodes_definitions_dir)) print('ECCODES_DEFINITIONS_INSTALLATION_FULL_PATH=' + os.path.join(args.idireccodes, eccodes_definitions_dir)) os.system('cp -rf ' + package_spec.format('{^cosmo-eccodes-definitions.prefix}') + ' ' + os.path.join(args.idireccodes, eccodes_definitions_dir)) with open('run-env', 'w') as outfile: subprocess.run(['spack load --sh ' + args.spec], shell=True, stdout=outfile) with open('run-env', 'r') as outfile: filedata = outfile.read() newdata = filedata.replace(package_spec.format('{prefix}'), os.path.join(args.idir, package_dir)) newdata = newdata.replace(package_spec.format('{^eccodes.prefix}'), os.path.join(args.idireccodes, eccodes_dir)) newdata = newdata.replace(package_spec.format('{^cosmo-eccodes-definitions.prefix}'), os.path.join(args.idireccodes, eccodes_definitions_dir)) newdata = newdata.replace(bin_path + ':', '') with open('run-env', 'w') as outfile: outfile.write(newdata) print('Installing run-env file to: ' + os.path.join(args.idir, package_dir)) os.system('mv run-env ' + os.path.join(args.idir, package_dir))