mirror of https://github.com/mamba-org/mamba.git
fix: JSON output for environment export (#3559)
Signed-off-by: Julien Jerphanion <git@jjerphan.xyz> Co-authored-by: Johan Mabille <johan.mabille@gmail.com>
This commit is contained in:
parent
d26c7f5632
commit
d2d16517ed
|
@ -130,6 +130,16 @@ set_env_command(CLI::App* com, Configuration& config)
|
|||
config.load();
|
||||
|
||||
auto channel_context = mamba::ChannelContext::make_conda_compatible(ctx);
|
||||
|
||||
auto json_format = config.at("json").get_cli_config<bool>();
|
||||
|
||||
// Raise a warning if `--json` and `--explicit` are used together.
|
||||
if (json_format && explicit_format)
|
||||
{
|
||||
std::cerr << "Warning: `--json` and `--explicit` are used together but are incompatible. The `--json` flag will be ignored."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (explicit_format)
|
||||
{
|
||||
// TODO: handle error
|
||||
|
@ -164,6 +174,83 @@ set_env_command(CLI::App* com, Configuration& config)
|
|||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
else if (json_format)
|
||||
{
|
||||
auto pd = PrefixData::create(ctx.prefix_params.target_prefix, channel_context).value();
|
||||
History& hist = pd.history();
|
||||
|
||||
const auto& versions_map = pd.records();
|
||||
auto requested_specs_map = hist.get_requested_specs_map();
|
||||
std::stringstream dependencies;
|
||||
std::set<std::string> channels;
|
||||
|
||||
for (auto it = versions_map.begin(); it != versions_map.end(); ++it)
|
||||
{
|
||||
auto k = it->first;
|
||||
auto v = it->second;
|
||||
if (from_history && requested_specs_map.find(k) == requested_specs_map.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto chans = channel_context.make_channel(v.channel);
|
||||
|
||||
if (from_history)
|
||||
{
|
||||
dependencies << " \"" << requested_specs_map[k].str() << "\",\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
dependencies << " \"";
|
||||
if (channel_subdir)
|
||||
{
|
||||
dependencies
|
||||
// If the size is not one, it's a custom multi channel
|
||||
<< ((chans.size() == 1) ? chans.front().display_name() : v.channel)
|
||||
<< "/" << v.platform << "::";
|
||||
}
|
||||
dependencies << v.name << "=" << v.version;
|
||||
if (!no_build)
|
||||
{
|
||||
dependencies << "=" << v.build_string;
|
||||
}
|
||||
if (no_md5 == -1)
|
||||
{
|
||||
dependencies << "[md5=" << v.md5 << "]";
|
||||
}
|
||||
auto last_dep = std::next(it) == versions_map.end();
|
||||
dependencies << "\"" << (last_dep ? "" : ",") << "\n";
|
||||
}
|
||||
|
||||
for (const auto& chan : chans)
|
||||
{
|
||||
channels.insert(chan.display_name());
|
||||
}
|
||||
}
|
||||
std::cout << "{\n";
|
||||
|
||||
if (!channels.empty())
|
||||
{
|
||||
std::cout << " \"channels\": [\n";
|
||||
for (auto channel_it = channels.begin(); channel_it != channels.end();
|
||||
++channel_it)
|
||||
{
|
||||
auto last_channel = std::next(channel_it) == channels.end();
|
||||
std::cout << " \"" << *channel_it << "\"" << (last_channel ? "" : ",")
|
||||
<< "\n";
|
||||
}
|
||||
std::cout << " ],\n";
|
||||
}
|
||||
std::cout << " \"dependencies\": [\n" << dependencies.str() << " ],\n";
|
||||
|
||||
std::cout << " \"name\": \"" << get_env_name(ctx, ctx.prefix_params.target_prefix)
|
||||
<< "\",\n";
|
||||
std::cout << " \"prefix\": " << ctx.prefix_params.target_prefix << "\n";
|
||||
|
||||
std::cout << "}\n";
|
||||
|
||||
std::cout.flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto pd = PrefixData::create(ctx.prefix_params.target_prefix, channel_context).value();
|
||||
|
@ -177,6 +264,7 @@ set_env_command(CLI::App* com, Configuration& config)
|
|||
auto requested_specs_map = hist.get_requested_specs_map();
|
||||
std::stringstream dependencies;
|
||||
std::set<std::string> channels;
|
||||
|
||||
for (const auto& [k, v] : versions_map)
|
||||
{
|
||||
if (from_history && requested_specs_map.find(k) == requested_specs_map.end())
|
||||
|
|
|
@ -74,29 +74,39 @@ def export_env():
|
|||
@pytest.mark.parametrize("md5_flag", [None, "--md5", "--no-md5"])
|
||||
@pytest.mark.parametrize("explicit_flag", [None, "--explicit"])
|
||||
@pytest.mark.parametrize("no_build_flag", [None, "--no-build", "--no-builds"])
|
||||
def test_env_export(export_env, no_build_flag, explicit_flag, md5_flag, channel_subdir_flag):
|
||||
flags = filter(None, [explicit_flag, md5_flag, channel_subdir_flag])
|
||||
@pytest.mark.parametrize("json_flag", [None, "--json"])
|
||||
def test_env_export(
|
||||
export_env, json_flag, no_build_flag, explicit_flag, md5_flag, channel_subdir_flag
|
||||
):
|
||||
if explicit_flag and json_flag:
|
||||
# `--explicit` has precedence over `--json`, which is tested bellow.
|
||||
# But we need to omit here to avoid `helpers.run_env` to parse the output as JSON and fail.
|
||||
json_flag = None
|
||||
|
||||
flags = filter(None, [no_build_flag, json_flag, explicit_flag, md5_flag, channel_subdir_flag])
|
||||
output = helpers.run_env("export", "-n", export_env, *flags)
|
||||
if explicit_flag:
|
||||
assert "/micromamba-0.24.0-0." in output
|
||||
if md5_flag != "--no-md5":
|
||||
assert re.search("#[a-f0-9]{32}$", output.replace("\r", ""))
|
||||
else:
|
||||
ret = yaml.safe_load(output)
|
||||
if json_flag:
|
||||
# Already parsed
|
||||
ret = output
|
||||
else:
|
||||
ret = yaml.safe_load(output)
|
||||
assert ret["name"] == export_env
|
||||
assert "env-create-export" in ret["prefix"]
|
||||
assert set(ret["channels"]) == {"conda-forge"}
|
||||
assert (
|
||||
"micromamba=0.24.0\n"
|
||||
if no_build_flag
|
||||
else "micromamba=0.24.0=0" in str(ret["dependencies"])
|
||||
)
|
||||
if md5_flag == "--md5":
|
||||
micromamba_spec_prefix = "micromamba=0.24.0" if no_build_flag else "micromamba=0.24.0=0"
|
||||
assert micromamba_spec_prefix in str(ret["dependencies"])
|
||||
if md5_flag == "--md5" and no_build_flag:
|
||||
assert re.search(r"micromamba=0.24.0\[md5=[a-f0-9]{32}\]", str(ret["dependencies"]))
|
||||
if md5_flag == "--md5" and no_build_flag is None:
|
||||
assert re.search(r"micromamba=0.24.0=0\[md5=[a-f0-9]{32}\]", str(ret["dependencies"]))
|
||||
|
||||
if channel_subdir_flag:
|
||||
assert re.search(
|
||||
r"conda-forge/[a-z0-9-]+::micromamba=0.24.0=0", str(ret["dependencies"])
|
||||
)
|
||||
assert re.search(r"conda-forge/[a-z0-9-]+::micromamba=0.24.0", str(ret["dependencies"]))
|
||||
|
||||
|
||||
def test_create():
|
||||
|
|
Loading…
Reference in New Issue