mirror of https://github.com/mamba-org/mamba.git
support installing pip dependencies with uv (#3918)
This commit is contained in:
parent
c3681db47f
commit
3111778478
|
@ -105,8 +105,12 @@ namespace mamba
|
|||
|
||||
bool eval_selector(const std::string& selector, const std::string& platform);
|
||||
|
||||
yaml_file_contents
|
||||
read_yaml_file(const Context& ctx, const std::string& yaml_file, const std::string& platform);
|
||||
yaml_file_contents read_yaml_file(
|
||||
const Context& ctx,
|
||||
const std::string& yaml_file,
|
||||
const std::string& platform,
|
||||
bool use_uv
|
||||
);
|
||||
|
||||
inline void to_json(nlohmann::json&, const other_pkg_mgr_spec&)
|
||||
{
|
||||
|
|
|
@ -131,6 +131,7 @@ namespace mamba
|
|||
bool experimental_repodata_parsing = true;
|
||||
bool experimental_matchspec_parsing = false;
|
||||
bool debug = false;
|
||||
bool use_uv = false;
|
||||
|
||||
// TODO check writable and add other potential dirs
|
||||
std::vector<fs::u8path> envs_dirs;
|
||||
|
|
|
@ -1857,6 +1857,13 @@ namespace mamba
|
|||
.set_env_var_names()
|
||||
.description("Defines if PYC files will be compiled or not"));
|
||||
|
||||
insert(Configurable("use_uv", &m_context.use_uv)
|
||||
.group("Extract, Link & Install")
|
||||
.set_rc_configurable()
|
||||
.set_env_var_names()
|
||||
.description("Whether to use uv for installing pip dependencies. Defaults to false."
|
||||
));
|
||||
|
||||
// Output, Prompt and Flow
|
||||
insert(Configurable("always_yes", &m_context.always_yes)
|
||||
.group("Output, Prompt and Flow Control")
|
||||
|
|
|
@ -117,8 +117,12 @@ namespace mamba
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
yaml_file_contents
|
||||
read_yaml_file(const Context& ctx, const std::string& yaml_file, const std::string& platform)
|
||||
yaml_file_contents read_yaml_file(
|
||||
const Context& ctx,
|
||||
const std::string& yaml_file,
|
||||
const std::string& platform,
|
||||
bool use_uv
|
||||
)
|
||||
{
|
||||
// Download content of environment yaml file
|
||||
auto tmp_yaml_file = downloaded_file_from_url(ctx, yaml_file);
|
||||
|
@ -205,7 +209,7 @@ namespace mamba
|
|||
yaml_parent_path = fs::absolute(yaml_file).parent_path().string();
|
||||
}
|
||||
result.others_pkg_mgrs_specs.push_back({
|
||||
"pip",
|
||||
use_uv ? "uv" : "pip",
|
||||
map_el.second.as<std::vector<std::string>>(),
|
||||
yaml_parent_path,
|
||||
});
|
||||
|
@ -233,7 +237,21 @@ namespace mamba
|
|||
throw e;
|
||||
}
|
||||
|
||||
if (has_pip_deps && !std::count(dependencies.begin(), dependencies.end(), "pip"))
|
||||
if (has_pip_deps && use_uv && !std::count(dependencies.begin(), dependencies.end(), "uv"))
|
||||
{
|
||||
dependencies.push_back("uv");
|
||||
}
|
||||
else if (has_pip_deps && std::count(dependencies.begin(), dependencies.end(), "uv"))
|
||||
{
|
||||
for (auto& spec : result.others_pkg_mgrs_specs)
|
||||
{
|
||||
if (spec.pkg_mgr == "pip")
|
||||
{
|
||||
spec.pkg_mgr = "uv";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (has_pip_deps && !std::count(dependencies.begin(), dependencies.end(), "pip"))
|
||||
{
|
||||
dependencies.push_back("pip");
|
||||
}
|
||||
|
@ -890,7 +908,12 @@ namespace mamba
|
|||
}
|
||||
else if (is_yaml_file_name(file))
|
||||
{
|
||||
const auto parse_result = read_yaml_file(context, file, context.platform);
|
||||
const auto parse_result = read_yaml_file(
|
||||
context,
|
||||
file,
|
||||
context.platform,
|
||||
context.use_uv
|
||||
);
|
||||
|
||||
if (parse_result.channels.size() != 0)
|
||||
{
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace mamba
|
|||
{
|
||||
namespace
|
||||
{
|
||||
tl::expected<command_args, std::runtime_error> get_pip_install_command(
|
||||
tl::expected<command_args, std::runtime_error> get_pkg_mgr_install_command(
|
||||
const std::string& name,
|
||||
const std::string& target_prefix,
|
||||
const fs::u8path& spec_file,
|
||||
|
@ -34,8 +34,28 @@ namespace mamba
|
|||
const auto get_python_path = [&]
|
||||
{ return util::which_in("python", util::get_path_dirs(target_prefix)).string(); };
|
||||
|
||||
command_args cmd = { get_python_path(), "-m", "pip", "install" };
|
||||
command_args cmd_extension = { "-r", spec_file, "--no-input", "--quiet" };
|
||||
const auto get_uv_path = [&]
|
||||
{ return util::which_in("uv", util::get_path_dirs(target_prefix)).string(); };
|
||||
|
||||
command_args cmd = [&]
|
||||
{
|
||||
if (name == "uv")
|
||||
{
|
||||
return command_args{ get_uv_path() };
|
||||
}
|
||||
else
|
||||
{
|
||||
return command_args{ get_python_path(), "-m" };
|
||||
}
|
||||
}();
|
||||
|
||||
cmd.insert(cmd.end(), { "pip", "install" });
|
||||
command_args cmd_extension = { "-r", spec_file, "--quiet" };
|
||||
|
||||
if (name != "uv")
|
||||
{
|
||||
cmd_extension.push_back("--no-input");
|
||||
}
|
||||
|
||||
if (update == pip::Update::Yes)
|
||||
{
|
||||
|
@ -50,7 +70,8 @@ namespace mamba
|
|||
cmd.insert(cmd.end(), cmd_extension.begin(), cmd_extension.end());
|
||||
const std::unordered_map<std::string, command_args> pip_install_command{
|
||||
{ "pip", cmd },
|
||||
{ "pip --no-deps", cmd }
|
||||
{ "pip --no-deps", cmd },
|
||||
{ "uv", cmd },
|
||||
};
|
||||
|
||||
auto found_it = pip_install_command.find(name);
|
||||
|
@ -135,7 +156,7 @@ namespace mamba
|
|||
|
||||
command_args command = [&]
|
||||
{
|
||||
const auto maybe_command = get_pip_install_command(
|
||||
const auto maybe_command = get_pkg_mgr_install_command(
|
||||
pkg_mgr,
|
||||
ctx.prefix_params.target_prefix.string(),
|
||||
specs.path(),
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
name: env_4
|
||||
channels: [conda-forge, bioconda]
|
||||
dependencies:
|
||||
- test1
|
||||
- test2
|
||||
- uv
|
||||
- pip:
|
||||
- pytest
|
||||
- numpy
|
|
@ -50,7 +50,8 @@ namespace mamba
|
|||
auto res = detail::read_yaml_file(
|
||||
context,
|
||||
mambatests::test_data_dir / "env_file/env_1.yaml",
|
||||
context.platform
|
||||
context.platform,
|
||||
false
|
||||
);
|
||||
REQUIRE(res.name == "env_1");
|
||||
REQUIRE(res.channels == V({ "conda-forge", "bioconda" }));
|
||||
|
@ -60,7 +61,8 @@ namespace mamba
|
|||
auto res2 = detail::read_yaml_file(
|
||||
context,
|
||||
mambatests::test_data_dir / "env_file/env_2.yaml",
|
||||
context.platform
|
||||
context.platform,
|
||||
false
|
||||
);
|
||||
REQUIRE(res2.name == "env_2");
|
||||
REQUIRE(res2.channels == V({ "conda-forge", "bioconda" }));
|
||||
|
@ -81,7 +83,8 @@ namespace mamba
|
|||
auto res = detail::read_yaml_file(
|
||||
context,
|
||||
mambatests::test_data_dir / "env_file/env_3.yaml",
|
||||
context.platform
|
||||
context.platform,
|
||||
false
|
||||
);
|
||||
REQUIRE(res.name == "env_3");
|
||||
REQUIRE(res.channels == V({ "conda-forge", "bioconda" }));
|
||||
|
@ -103,7 +106,8 @@ namespace mamba
|
|||
auto res = detail::read_yaml_file(
|
||||
context,
|
||||
"https://raw.githubusercontent.com/mamba-org/mamba/refs/heads/main/micromamba/tests/env-create-export.yaml",
|
||||
context.platform
|
||||
context.platform,
|
||||
false
|
||||
);
|
||||
REQUIRE(res.name == "");
|
||||
REQUIRE(res.channels == V({ "https://conda.anaconda.org/conda-forge" }));
|
||||
|
@ -117,7 +121,8 @@ namespace mamba
|
|||
auto res = detail::read_yaml_file(
|
||||
context,
|
||||
"https://raw.githubusercontent.com/mamba-org/mamba/refs/heads/main/libmamba/tests/data/env_file/env_3.yaml",
|
||||
context.platform
|
||||
context.platform,
|
||||
false
|
||||
);
|
||||
REQUIRE(res.name == "env_3");
|
||||
REQUIRE(res.channels == V({ "conda-forge", "bioconda" }));
|
||||
|
@ -132,6 +137,52 @@ namespace mamba
|
|||
);
|
||||
}
|
||||
|
||||
SECTION("env_yaml_file_with_uv_override")
|
||||
{
|
||||
const auto& context = mambatests::context();
|
||||
using V = std::vector<std::string>;
|
||||
auto res = detail::read_yaml_file(
|
||||
context,
|
||||
"https://raw.githubusercontent.com/iisakkirotko/mamba/refs/heads/yaml-install-uv/libmamba/tests/data/env_file/env_4.yaml",
|
||||
context.platform,
|
||||
false
|
||||
);
|
||||
REQUIRE(res.name == "env_4");
|
||||
REQUIRE(res.channels == V({ "conda-forge", "bioconda" }));
|
||||
REQUIRE(res.dependencies == V({ "test1", "test2", "uv" }));
|
||||
|
||||
REQUIRE(res.others_pkg_mgrs_specs.size() == 1);
|
||||
auto o = res.others_pkg_mgrs_specs[0];
|
||||
REQUIRE(o.pkg_mgr == "uv");
|
||||
REQUIRE(o.deps == V({ "pytest", "numpy" }));
|
||||
REQUIRE(
|
||||
o.cwd == "https://raw.githubusercontent.com/iisakkirotko/mamba/refs/heads/yaml-install-uv/libmamba/tests/data/env_file/env_4.yaml"
|
||||
);
|
||||
}
|
||||
|
||||
SECTION("env_yaml_file_with_uv")
|
||||
{
|
||||
const auto& context = mambatests::context();
|
||||
using V = std::vector<std::string>;
|
||||
auto res = detail::read_yaml_file(
|
||||
context,
|
||||
"https://raw.githubusercontent.com/mamba-org/mamba/refs/heads/main/libmamba/tests/data/env_file/env_3.yaml",
|
||||
context.platform,
|
||||
true
|
||||
);
|
||||
REQUIRE(res.name == "env_3");
|
||||
REQUIRE(res.channels == V({ "conda-forge", "bioconda" }));
|
||||
REQUIRE(res.dependencies == V({ "test1", "test2", "test3", "uv" }));
|
||||
|
||||
REQUIRE(res.others_pkg_mgrs_specs.size() == 1);
|
||||
auto o = res.others_pkg_mgrs_specs[0];
|
||||
REQUIRE(o.pkg_mgr == "uv");
|
||||
REQUIRE(o.deps == V({ "pytest", "numpy" }));
|
||||
REQUIRE(
|
||||
o.cwd == "https://raw.githubusercontent.com/mamba-org/mamba/refs/heads/main/libmamba/tests/data/env_file/env_3.yaml"
|
||||
);
|
||||
}
|
||||
|
||||
SECTION("env_yaml_file_with_specs_selection")
|
||||
{
|
||||
const auto& context = mambatests::context();
|
||||
|
@ -139,7 +190,8 @@ namespace mamba
|
|||
auto res = detail::read_yaml_file(
|
||||
context,
|
||||
"https://raw.githubusercontent.com/mamba-org/mamba/refs/heads/main/libmamba/tests/data/env_file/env_2.yaml",
|
||||
context.platform
|
||||
context.platform,
|
||||
false
|
||||
);
|
||||
REQUIRE(res.name == "env_2");
|
||||
REQUIRE(res.channels == V({ "conda-forge", "bioconda" }));
|
||||
|
|
|
@ -88,6 +88,9 @@ init_general_options(CLI::App* subcom, Configuration& config)
|
|||
->add_flag("--experimental", experimental.get_cli_config<bool>(), experimental.description())
|
||||
->group(cli_group);
|
||||
|
||||
auto& use_uv = config.at("use_uv");
|
||||
subcom->add_flag("--use-uv", use_uv.get_cli_config<bool>(), use_uv.description())->group(cli_group);
|
||||
|
||||
auto& debug = config.at("debug");
|
||||
subcom->add_flag("--debug", debug.get_cli_config<bool>(), "Debug mode")->group("");
|
||||
|
||||
|
|
Loading…
Reference in New Issue