Example #1
0
    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)
Example #2
0
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)
Example #3
0
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)
Example #4
0
File: graph.py Project: LLNL/spack
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
Example #5
0
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
Example #6
0
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)
Example #7
0
    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
Example #8
0
    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
Example #9
0
    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
Example #10
0
    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
Example #11
0
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))
Example #12
0
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))