mirror of https://github.com/mamba-org/mamba.git
Support multiple env yaml specs (#2993)
* tested and working * docs update * disallow multiple spec types * add test for only one yaml specifies channel * fix install yaml test * Update micromamba/tests/test_create.py Co-authored-by: Jonas Haag <jonas@lophus.org> * Update micromamba/tests/test_create.py Co-authored-by: Jonas Haag <jonas@lophus.org> * suggestions * separate loop * appease the linter * another test --------- Co-authored-by: Jonas Haag <jonas@lophus.org>
This commit is contained in:
parent
212d1e9ad2
commit
57a6a691be
|
@ -1,6 +1,7 @@
|
|||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- python >=3.12
|
||||
# libmamba build dependencies
|
||||
- cxx-compiler
|
||||
- cmake >=3.16
|
||||
|
|
|
@ -188,7 +188,7 @@ To build from source, install the development dependencies, using a Conda compat
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
micromamba create -n mamba --file dev/environment-static.yml
|
||||
micromamba create -n mamba --file dev/environment-micromamba-static.yml
|
||||
micromamba activate -n mamba
|
||||
|
||||
Use CMake from this environment to drive the build:
|
||||
|
|
|
@ -167,8 +167,8 @@ They are used the same way as text files:
|
|||
.. note::
|
||||
CLI options will keep :ref:`precedence<precedence-resolution>` over *target prefix* or *channels* specified in spec files.
|
||||
|
||||
.. warning::
|
||||
``YAML`` spec files do not allow multiple files.
|
||||
.. note::
|
||||
You can pass multiple ``YAML`` spec files by repeating the ``-f,--file`` argument.
|
||||
|
||||
Explicit spec files
|
||||
*******************
|
||||
|
|
|
@ -782,6 +782,14 @@ namespace mamba
|
|||
|
||||
namespace detail
|
||||
{
|
||||
enum SpecType
|
||||
{
|
||||
unknown,
|
||||
env_lockfile,
|
||||
yaml,
|
||||
other
|
||||
};
|
||||
|
||||
void create_empty_target(const Context& context, const fs::u8path& prefix)
|
||||
{
|
||||
detail::create_target_directory(context, prefix);
|
||||
|
@ -816,12 +824,31 @@ namespace mamba
|
|||
return;
|
||||
}
|
||||
|
||||
for (const auto& file : file_specs)
|
||||
mamba::detail::SpecType spec_type = mamba::detail::unknown;
|
||||
for (auto& file : file_specs)
|
||||
{
|
||||
if (is_yaml_file_name(file) && file_specs.size() != 1)
|
||||
mamba::detail::SpecType current_file_spec_type = mamba::detail::unknown;
|
||||
if (is_env_lockfile_name(file))
|
||||
{
|
||||
throw std::runtime_error("Can only handle 1 yaml file!");
|
||||
current_file_spec_type = mamba::detail::env_lockfile;
|
||||
}
|
||||
else if (is_yaml_file_name(file))
|
||||
{
|
||||
current_file_spec_type = mamba::detail::yaml;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_file_spec_type = mamba::detail::other;
|
||||
}
|
||||
|
||||
if (spec_type != mamba::detail::unknown && spec_type != current_file_spec_type)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"found multiple spec file types, all spec files must be of same format (yaml, txt, explicit spec, etc.)"
|
||||
);
|
||||
}
|
||||
|
||||
spec_type = current_file_spec_type;
|
||||
}
|
||||
|
||||
for (auto& file : file_specs)
|
||||
|
@ -858,10 +885,15 @@ namespace mamba
|
|||
channels.set_cli_value(updated_channels);
|
||||
}
|
||||
|
||||
if (parse_result.name.size() != 0)
|
||||
if (parse_result.name.size() != 0 && !env_name.configured())
|
||||
{
|
||||
env_name.set_cli_yaml_value(parse_result.name);
|
||||
}
|
||||
else if (parse_result.name.size() != 0 && parse_result.name != env_name.value<std::string>())
|
||||
{
|
||||
LOG_WARNING << "YAML specs have different environment names. Using "
|
||||
<< env_name.value<std::string>();
|
||||
}
|
||||
|
||||
if (parse_result.dependencies.size() != 0)
|
||||
{
|
||||
|
|
|
@ -318,15 +318,51 @@ def test_multiple_spec_files(tmp_home, tmp_root_prefix, tmp_path, type):
|
|||
|
||||
cmd += ["-f", spec_file]
|
||||
|
||||
if type == "yaml":
|
||||
with pytest.raises(subprocess.CalledProcessError):
|
||||
helpers.create(*cmd, "--print-config-only")
|
||||
else:
|
||||
res = helpers.create(*cmd, "--print-config-only")
|
||||
if type == "classic":
|
||||
assert res["specs"] == specs
|
||||
else: # explicit
|
||||
assert res["specs"] == [explicit_specs[0]]
|
||||
res = helpers.create(*cmd, "--print-config-only")
|
||||
if type == "yaml" or type == "classic":
|
||||
assert res["specs"] == specs
|
||||
else: # explicit
|
||||
assert res["specs"] == [explicit_specs[0]]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("shared_pkgs_dirs", [True], indirect=True)
|
||||
def test_multiple_spec_files_different_types(tmp_home, tmp_root_prefix, tmp_path):
|
||||
env_prefix = tmp_path / "myenv"
|
||||
|
||||
cmd = ["-p", env_prefix]
|
||||
|
||||
spec_file_1 = tmp_path / "env1.yaml"
|
||||
spec_file_1.write_text("dependencies: [xtensor]")
|
||||
|
||||
spec_file_2 = tmp_path / "env2.txt"
|
||||
spec_file_2.write_text("xsimd")
|
||||
|
||||
cmd += ["-f", spec_file_1, "-f", spec_file_2]
|
||||
|
||||
with pytest.raises(subprocess.CalledProcessError) as info:
|
||||
helpers.create(*cmd, "--print-config-only")
|
||||
assert "found multiple spec file types" in info.value.stderr.decode()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("shared_pkgs_dirs", [True], indirect=True)
|
||||
def test_multiple_yaml_specs_only_one_has_channels(tmp_home, tmp_root_prefix, tmp_path):
|
||||
env_prefix = tmp_path / "myenv"
|
||||
|
||||
cmd = ["-p", env_prefix]
|
||||
|
||||
spec_file_1 = tmp_path / "env1.yaml"
|
||||
spec_file_1.write_text("dependencies: [xtensor]")
|
||||
|
||||
spec_file_2 = tmp_path / "env2.yaml"
|
||||
spec_file_2.write_text(
|
||||
"dependencies: [xsimd]\nchannels: [bioconda]",
|
||||
)
|
||||
|
||||
cmd += ["-f", spec_file_1, "-f", spec_file_2]
|
||||
|
||||
res = helpers.create(*cmd, "--print-config-only", default_channel=False)
|
||||
assert res["channels"] == ["bioconda"]
|
||||
assert res["specs"] == ["xtensor", "xsimd"]
|
||||
|
||||
|
||||
def test_multiprocessing():
|
||||
|
|
|
@ -266,15 +266,11 @@ class TestInstall:
|
|||
|
||||
cmd += ["-f", file]
|
||||
|
||||
if type == "yaml":
|
||||
with pytest.raises(subprocess.CalledProcessError):
|
||||
helpers.install(*cmd, "--print-config-only")
|
||||
else:
|
||||
res = helpers.install(*cmd, "--print-config-only")
|
||||
if type == "classic":
|
||||
assert res["specs"] == specs
|
||||
else: # explicit
|
||||
assert res["specs"] == [explicit_specs[0]]
|
||||
res = helpers.install(*cmd, "--print-config-only")
|
||||
if type == "yaml" or type == "classic":
|
||||
assert res["specs"] == specs
|
||||
else: # explicit
|
||||
assert res["specs"] == [explicit_specs[0]]
|
||||
|
||||
@pytest.mark.parametrize("priority", (None, "disabled", "flexible", "strict"))
|
||||
@pytest.mark.parametrize("no_priority", (None, True))
|
||||
|
|
|
@ -461,15 +461,11 @@ class TestUpdateConfig:
|
|||
|
||||
cmd += ["-f", file]
|
||||
|
||||
if type == "yaml":
|
||||
with pytest.raises(helpers.subprocess.CalledProcessError):
|
||||
helpers.install(*cmd, "--print-config-only")
|
||||
else:
|
||||
res = helpers.install(*cmd, "--print-config-only")
|
||||
if type == "classic":
|
||||
assert res["specs"] == specs
|
||||
else: # explicit
|
||||
assert res["specs"] == [explicit_specs[0]]
|
||||
res = helpers.install(*cmd, "--print-config-only")
|
||||
if type == "yaml" or type == "classic":
|
||||
assert res["specs"] == specs
|
||||
else: # explicit
|
||||
assert res["specs"] == [explicit_specs[0]]
|
||||
|
||||
def test_channel_specific(self, env_created):
|
||||
helpers.install("quantstack::sphinx", no_dry_run=True)
|
||||
|
|
Loading…
Reference in New Issue