diff --git a/libmamba/include/mamba/core/solver.hpp b/libmamba/include/mamba/core/solver.hpp index aff90ad83c..27cdf15f65 100644 --- a/libmamba/include/mamba/core/solver.hpp +++ b/libmamba/include/mamba/core/solver.hpp @@ -48,19 +48,9 @@ namespace mamba { public: - struct Flags - { - /** Keep the dependencies of the install package in the solution. */ - bool keep_dependencies = true; - /** Keep the original required package in the solution. */ - bool keep_specs = true; - /** Force reinstallation of jobs. */ - bool force_reinstall = false; - }; - using Request = solver::Request; - MSolver(MPool pool, std::vector> flags = {}); + MSolver(MPool pool); ~MSolver(); MSolver(const MSolver&) = delete; @@ -68,10 +58,6 @@ namespace mamba MSolver(MSolver&&); MSolver& operator=(MSolver&&); - void set_flags(const Flags& flags); // TODO temporary Itf meant to be passed in ctor - [[nodiscard]] auto flags() const -> const Flags&; - [[deprecated]] void py_set_libsolv_flags(const std::vector>& flags); - [[nodiscard]] bool try_solve(); void must_solve(); [[nodiscard]] bool is_solved() const; @@ -96,13 +82,11 @@ namespace mamba private: - std::vector> m_libsolv_flags; Request m_request; // Order of m_pool and m_solver is critical since m_pool must outlive m_solver. MPool m_pool; // Temporary Pimpl all libsolv to keep it private std::unique_ptr m_solver; - Flags m_flags = {}; bool m_is_solved; void apply_libsolv_flags(); diff --git a/libmamba/include/mamba/solver/request.hpp b/libmamba/include/mamba/solver/request.hpp index 337ba77817..3556a08dd2 100644 --- a/libmamba/include/mamba/solver/request.hpp +++ b/libmamba/include/mamba/solver/request.hpp @@ -18,6 +18,22 @@ namespace mamba::solver { struct Request { + struct Flags + { + /** Keep the dependencies of the install package in the solution. */ + bool keep_dependencies = true; + /** Keep the original user requested package in the solution. */ + bool keep_user_specs = true; + /** Force reinstallation of jobs. */ + bool force_reinstall = false; + /** Allow downgrading packages to satisfy requirements. */ + bool allow_downgrade = true; + /** Allow uninstalling packages to satisfy requirements. */ + bool allow_uninstall = true; + /** Prefer packages by repoitory order. */ + bool strict_repo_priority = true; + }; + /** Instruct to install a package matching the given spec. */ struct Install { @@ -64,6 +80,7 @@ namespace mamba::solver using Item = std::variant; using item_list = std::vector; + Flags flags = {}; item_list items = {}; }; diff --git a/libmamba/src/api/install.cpp b/libmamba/src/api/install.cpp index b8d9c76e35..f87390dba2 100644 --- a/libmamba/src/api/install.cpp +++ b/libmamba/src/api/install.cpp @@ -559,24 +559,17 @@ namespace mamba load_installed_packages_in_pool(ctx, pool, prefix_data); - MSolver solver( - pool, - { - { SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall }, - { SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade }, - { SOLVER_FLAG_STRICT_REPO_PRIORITY, - ctx.channel_priority == ChannelPriority::Strict }, - } - ); - - solver.set_flags({ - /* .keep_dependencies= */ !no_deps, - /* .keep_specs= */ !only_deps, - /* .force_reinstall= */ force_reinstall, - }); auto request = create_install_request(prefix_data, specs, freeze_installed); add_pins_to_request(request, ctx, prefix_data, specs, no_pin, no_py_pin); + request.flags = { + /* .keep_dependencies= */ !no_deps, + /* .keep_user_specs= */ !only_deps, + /* .force_reinstall= */ force_reinstall, + /* .allow_downgrade= */ ctx.allow_downgrade, + /* .allow_uninstall= */ ctx.allow_uninstall, + /* .strict_repo_priority= */ ctx.channel_priority == ChannelPriority::Strict, + }; { auto out = Console::stream(); @@ -584,6 +577,7 @@ namespace mamba // Console stream prints on destrucion } + auto solver = MSolver(pool); solver.set_request(std::move(request)); bool success = solver.try_solve(); diff --git a/libmamba/src/api/remove.cpp b/libmamba/src/api/remove.cpp index 457d28c163..0521a4bcdf 100644 --- a/libmamba/src/api/remove.cpp +++ b/libmamba/src/api/remove.cpp @@ -161,18 +161,18 @@ namespace mamba } else { - MSolver solver( - pool, - { - { SOLVER_FLAG_ALLOW_DOWNGRADE, 1 }, - { SOLVER_FLAG_ALLOW_UNINSTALL, 1 }, - { SOLVER_FLAG_STRICT_REPO_PRIORITY, - ctx.channel_priority == ChannelPriority::Strict }, - } - ); - - solver.set_request(build_remove_request(ctx, channel_context, raw_specs, prune)); - + auto request = build_remove_request(ctx, channel_context, raw_specs, prune); + request.flags = { + /* .keep_dependencies= */ true, + /* .keep_user_specs= */ true, + /* .force_reinstall= */ false, + /* .allow_downgrade= */ true, + /* .allow_uninstall= */ true, + /* .strict_repo_priority= */ ctx.channel_priority == ChannelPriority::Strict, + }; + + auto solver = MSolver(pool); + solver.set_request(std::move(request)); solver.must_solve(); MTransaction transaction(pool, solver, package_caches); diff --git a/libmamba/src/api/update.cpp b/libmamba/src/api/update.cpp index 2865eba20f..8cfc65e84c 100644 --- a/libmamba/src/api/update.cpp +++ b/libmamba/src/api/update.cpp @@ -131,15 +131,6 @@ namespace mamba load_installed_packages_in_pool(ctx, pool, prefix_data); - MSolver solver( - pool, - { - { SOLVER_FLAG_ALLOW_DOWNGRADE, ctx.allow_downgrade }, - { SOLVER_FLAG_ALLOW_UNINSTALL, ctx.allow_uninstall }, - { SOLVER_FLAG_STRICT_REPO_PRIORITY, ctx.channel_priority == ChannelPriority::Strict }, - } - ); - auto request = create_update_request( prefix_data, raw_update_specs, @@ -155,6 +146,14 @@ namespace mamba /* no_pin= */ config.at("no_pin").value(), /* no_py_pin = */ config.at("no_py_pin").value() ); + request.flags = { + /* .keep_dependencies= */ true, + /* .keep_user_specs= */ true, + /* .force_reinstall= */ false, + /* .allow_downgrade= */ ctx.allow_downgrade, + /* .allow_uninstall= */ ctx.allow_uninstall, + /* .strict_repo_priority= */ ctx.channel_priority == ChannelPriority::Strict, + }; { auto out = Console::stream(); @@ -162,8 +161,8 @@ namespace mamba // Console stream prints on destrucion } + auto solver = MSolver(pool); solver.set_request(std::move(request)); - solver.must_solve(); auto execute_transaction = [&](MTransaction& transaction) diff --git a/libmamba/src/core/solver.cpp b/libmamba/src/core/solver.cpp index dad0bf8a62..32f371c8f9 100644 --- a/libmamba/src/core/solver.cpp +++ b/libmamba/src/core/solver.cpp @@ -28,9 +28,8 @@ namespace mamba { - MSolver::MSolver(MPool pool, std::vector> flags) - : m_libsolv_flags(std::move(flags)) - , m_pool(std::move(pool)) + MSolver::MSolver(MPool pool) + : m_pool(std::move(pool)) , m_solver(nullptr) , m_is_solved(false) { @@ -57,30 +56,6 @@ namespace mamba m_request = std::move(request); } - void MSolver::set_flags(const Flags& flags) - { - m_flags = flags; - } - - auto MSolver::flags() const -> const Flags& - { - return m_flags; - } - - void MSolver::py_set_libsolv_flags(const std::vector>& flags) - { - m_libsolv_flags = flags; - } - - void MSolver::apply_libsolv_flags() - { - // TODO use new API - for (const auto& option : m_libsolv_flags) - { - solver_set_flag(m_solver->raw(), option.first, option.second); - } - } - bool MSolver::is_solved() const { return m_is_solved; @@ -106,13 +81,23 @@ namespace mamba return m_request; } + namespace + { + void set_solver_flags(solv::ObjSolver& solver, const solver::Request::Flags& flags) + { + ::solver_set_flag(solver.raw(), SOLVER_FLAG_ALLOW_DOWNGRADE, flags.allow_downgrade); + ::solver_set_flag(solver.raw(), SOLVER_FLAG_ALLOW_UNINSTALL, flags.allow_uninstall); + ::solver_set_flag(solver.raw(), SOLVER_FLAG_STRICT_REPO_PRIORITY, flags.strict_repo_priority); + } + } + bool MSolver::try_solve() { auto solv_jobs = solver::libsolv::request_to_decision_queue( m_request, m_pool.pool(), m_pool.channel_context().params(), - m_flags.force_reinstall + m_request.flags.force_reinstall ); if (!solv_jobs) { @@ -120,7 +105,7 @@ namespace mamba } m_solver = std::make_unique(m_pool.pool()); - apply_libsolv_flags(); + set_solver_flags(*m_solver, m_request.flags); const bool success = solver().solve(m_pool.pool(), solv_jobs.value()); m_is_solved = true; diff --git a/libmamba/src/core/transaction.cpp b/libmamba/src/core/transaction.cpp index e2f2bcad93..2953102977 100644 --- a/libmamba/src/core/transaction.cpp +++ b/libmamba/src/core/transaction.cpp @@ -224,12 +224,12 @@ namespace mamba auto trans = solv::ObjTransaction::from_solver(pool, solver.solver()); trans.order(pool); - const auto& flags = solver.flags(); - if (flags.keep_specs && flags.keep_dependencies) + const auto& flags = solver.request().flags; + if (flags.keep_user_specs && flags.keep_dependencies) { m_solution = solver::libsolv::transaction_to_solution(m_pool.pool(), trans); } - else if (flags.keep_specs && !flags.keep_dependencies) + else if (flags.keep_user_specs && !flags.keep_dependencies) { m_solution = solver::libsolv::transaction_to_solution_no_deps( m_pool.pool(), @@ -237,7 +237,7 @@ namespace mamba solver.request() ); } - else if (!flags.keep_specs && flags.keep_dependencies) + else if (!flags.keep_user_specs && flags.keep_dependencies) { m_solution = solver::libsolv::transaction_to_solution_only_deps( m_pool.pool(), @@ -246,7 +246,7 @@ namespace mamba ); } - if (solver.flags().keep_specs) + if (flags.keep_user_specs) { using Request = solver::Request; solver::for_each_of( diff --git a/libmamba/tests/src/core/test_satisfiability_error.cpp b/libmamba/tests/src/core/test_satisfiability_error.cpp index 783157cd79..b57eb3def7 100644 --- a/libmamba/tests/src/core/test_satisfiability_error.cpp +++ b/libmamba/tests/src/core/test_satisfiability_error.cpp @@ -155,10 +155,7 @@ namespace auto pool = MPool{ ctx, channel_context }; pool.add_repo_from_repodata_json(repodata_f, "some-url"); - auto solver = MSolver( - std::move(pool), - std::vector{ std::pair{ SOLVER_FLAG_ALLOW_DOWNGRADE, 1 } } - ); + auto solver = MSolver(std::move(pool)); solver.set_request(std::move(request)); return solver; @@ -173,7 +170,7 @@ TEST_CASE("Test create_problem utility") ctx, channel_context, std::array{ mkpkg("foo", "0.1.0", {}) }, - { { Request::Install{ "foo"_ms } } } + { {}, { Request::Install{ "foo"_ms } } } ); const auto solved = solver.try_solve(); REQUIRE(solved); @@ -187,7 +184,7 @@ TEST_CASE("Test empty specs") ctx, channel_context, std::array{ mkpkg("foo", "0.1.0", {}), mkpkg("", "", {}) }, - { { Request::Install{ "foo"_ms } } } + { {}, { Request::Install{ "foo"_ms } } } ); const auto solved = solver.try_solve(); REQUIRE(solved); @@ -205,7 +202,7 @@ namespace mkpkg("A", "0.2.0"), mkpkg("A", "0.3.0"), }, - { { Request::Install{ "A=0.4.0"_ms } } } + { {}, { Request::Install{ "A=0.4.0"_ms } } } ); } @@ -238,11 +235,12 @@ namespace mkpkg("intl", "4.0.0"), mkpkg("intl", "3.0.0"), }, - { { - Request::Install{ "menu"_ms }, - Request::Install{ "icons=1.*"_ms }, - Request::Install{ "intl=5.*"_ms }, - } } + { {}, + { + Request::Install{ "menu"_ms }, + Request::Install{ "icons=1.*"_ms }, + Request::Install{ "intl=5.*"_ms }, + } } ); } @@ -300,13 +298,14 @@ namespace ctx, channel_context, packages, - { { - Request::Install{ "menu"_ms }, - Request::Install{ "pyicons=1.*"_ms }, - Request::Install{ "intl=5.*"_ms }, - Request::Install{ "intl-mod"_ms }, - Request::Install{ "pretty>=1.0"_ms }, - } } + { {}, + { + Request::Install{ "menu"_ms }, + Request::Install{ "pyicons=1.*"_ms }, + Request::Install{ "intl=5.*"_ms }, + Request::Install{ "intl-mod"_ms }, + Request::Install{ "pretty>=1.0"_ms }, + } } ); } @@ -413,10 +412,7 @@ namespace load_channels(ctx, pool, cache, make_platform_channels(std::move(channels), platforms)); ctx.graphics_params.no_progress_bars = prev_progress_bars_value; - auto solver = MSolver( - std::move(pool), - std::vector{ std::pair{ SOLVER_FLAG_ALLOW_DOWNGRADE, 1 } } - ); + auto solver = MSolver(std::move(pool)); solver.set_request(std::move(request)); return solver; @@ -427,7 +423,11 @@ TEST_CASE("Test create_conda_forge utility") { auto& ctx = mambatests::context(); auto channel_context = ChannelContext::make_conda_compatible(ctx); - auto solver = create_conda_forge(ctx, channel_context, { { Request::Install{ "xtensor>=0.7"_ms } } }); + auto solver = create_conda_forge( + ctx, + channel_context, + { {}, { Request::Install{ "xtensor>=0.7"_ms } } } + ); const auto solved = solver.try_solve(); REQUIRE(solved); } @@ -439,7 +439,7 @@ namespace return create_conda_forge( ctx, channel_context, - { { Request::Install{ "python=2.7"_ms }, Request::Install{ "pytorch=1.12"_ms } } } + { {}, { Request::Install{ "python=2.7"_ms }, Request::Install{ "pytorch=1.12"_ms } } } ); } @@ -448,7 +448,7 @@ namespace return create_conda_forge( ctx, channel_context, - { { Request::Install{ "python=2.7"_ms }, Request::Install{ "pytorch=1.12"_ms } } }, + { {}, { Request::Install{ "python=2.7"_ms }, Request::Install{ "pytorch=1.12"_ms } } }, { mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "10.2.0") } ); } @@ -458,13 +458,14 @@ namespace return create_conda_forge( ctx, channel_context, - { { - Request::Install{ "python=3.7"_ms }, - Request::Install{ "cudatoolkit=11.1"_ms }, - Request::Install{ "cudnn=8.0"_ms }, - Request::Install{ "pytorch=1.8"_ms }, - Request::Install{ "torchvision=0.9=*py37_cu111*"_ms }, - } }, + { {}, + { + Request::Install{ "python=3.7"_ms }, + Request::Install{ "cudatoolkit=11.1"_ms }, + Request::Install{ "cudnn=8.0"_ms }, + Request::Install{ "pytorch=1.8"_ms }, + Request::Install{ "torchvision=0.9=*py37_cu111*"_ms }, + } }, { mkpkg("__glibc", "2.17.0"), mkpkg("__cuda", "11.1") } ); } @@ -474,7 +475,7 @@ namespace return create_conda_forge( ctx, channel_context, - { { Request::Install{ "python=3.7"_ms }, Request::Install{ "jpeg=9b"_ms } } } + { {}, { Request::Install{ "python=3.7"_ms }, Request::Install{ "jpeg=9b"_ms } } } ); } @@ -483,13 +484,14 @@ namespace return create_conda_forge( ctx, channel_context, - { { - Request::Install{ "r-base=3.5.* "_ms }, - Request::Install{ "pandas=0"_ms }, - Request::Install{ "numpy<1.20.0"_ms }, - Request::Install{ "matplotlib=2"_ms }, - Request::Install{ "r-matchit=4.*"_ms }, - } } + { {}, + { + Request::Install{ "r-base=3.5.* "_ms }, + Request::Install{ "pandas=0"_ms }, + Request::Install{ "numpy<1.20.0"_ms }, + Request::Install{ "matplotlib=2"_ms }, + Request::Install{ "r-matchit=4.*"_ms }, + } } ); } @@ -498,7 +500,7 @@ namespace return create_conda_forge( ctx, channel_context, - { { Request::Install{ "scip=8.*"_ms }, Request::Install{ "pyscipopt<4.0"_ms } } } + { {}, { Request::Install{ "scip=8.*"_ms }, Request::Install{ "pyscipopt<4.0"_ms } } } ); } @@ -507,7 +509,7 @@ namespace return create_conda_forge( ctx, channel_context, - { { Request::Install{ "python=3.9.*"_ms }, Request::Install{ "python=3.10.*"_ms } } } + { {}, { Request::Install{ "python=3.9.*"_ms }, Request::Install{ "python=3.10.*"_ms } } } ); } @@ -516,7 +518,7 @@ namespace return create_conda_forge( ctx, channel_context, - { { Request::Install{ "python=3.11"_ms }, Request::Install{ "numba<0.56"_ms } } } + { {}, { Request::Install{ "python=3.11"_ms }, Request::Install{ "numba<0.56"_ms } } } ); } diff --git a/libmambapy/src/libmambapy/bindings/legacy.cpp b/libmambapy/src/libmambapy/bindings/legacy.cpp index 93ef483d1b..455ed9bad0 100644 --- a/libmambapy/src/libmambapy/bindings/legacy.cpp +++ b/libmambapy/src/libmambapy/bindings/legacy.cpp @@ -310,9 +310,79 @@ bind_submodule_impl(pybind11::module_ m) } )); - m.attr("MAMBA_NO_DEPS") = "V2 Migration: Use Solver.Flags instead"; - m.attr("MAMBA_ONLY_DEPS") = "V2 Migration: Use Solver.Flags instead"; - m.attr("MAMBA_FORCE_REINSTALL") = "V2 Migration: Use Solver.Flags instead"; + constexpr auto global_solver_flag_v2_migrator = "V2 Migration: Solver flags set in libmambapy.solver.Request.flags."; + m.attr("MAMBA_NO_DEPS") = global_solver_flag_v2_migrator; + m.attr("MAMBA_ONLY_DEPS") = global_solver_flag_v2_migrator; + m.attr("MAMBA_FORCE_REINSTALL") = global_solver_flag_v2_migrator; + + m.attr("SOLVER_FLAG_ALLOW_DOWNGRADE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_ALLOW_ARCHCHANGE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_ALLOW_VENDORCHANGE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_ALLOW_UNINSTALL") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_NO_UPDATEPROVIDE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_SPLITPROVIDES") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_IGNORE_RECOMMENDED") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_ADD_ALREADY_RECOMMENDED") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_NO_INFARCHCHECK") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_ALLOW_NAMECHANGE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_BEST_OBEY_POLICY") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_NO_AUTOTARGET") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_DUP_ALLOW_DOWNGRADE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_DUP_ALLOW_NAMECHANGE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_KEEP_ORPHANS") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_BREAK_ORPHANS") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_FOCUS_INSTALLED") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_YUM_OBSOLETES") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_NEED_UPDATEPROVIDE") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_URPM_REORDER") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_FOCUS_BEST") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_STRONG_RECOMMENDS") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_INSTALL_ALSO_UPDATES") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED") = global_solver_flag_v2_migrator; + m.attr("SOLVER_FLAG_STRICT_REPO_PRIORITY") = global_solver_flag_v2_migrator; + + + constexpr auto global_solver_job_v2_migrator = "V2 Migration: job types are explicitly set in libmambapy.solver.Request."; + m.attr("SOLVER_SOLVABLE") = global_solver_job_v2_migrator; + m.attr("SOLVER_SOLVABLE_NAME") = global_solver_job_v2_migrator; + m.attr("SOLVER_SOLVABLE_PROVIDES") = global_solver_job_v2_migrator; + m.attr("SOLVER_SOLVABLE_ONE_OF") = global_solver_job_v2_migrator; + m.attr("SOLVER_SOLVABLE_REPO") = global_solver_job_v2_migrator; + m.attr("SOLVER_SOLVABLE_ALL") = global_solver_job_v2_migrator; + m.attr("SOLVER_SELECTMASK") = global_solver_job_v2_migrator; + m.attr("SOLVER_NOOP") = global_solver_job_v2_migrator; + m.attr("SOLVER_INSTALL") = global_solver_job_v2_migrator; + m.attr("SOLVER_ERASE") = global_solver_job_v2_migrator; + m.attr("SOLVER_UPDATE") = global_solver_job_v2_migrator; + m.attr("SOLVER_WEAKENDEPS") = global_solver_job_v2_migrator; + m.attr("SOLVER_MULTIVERSION") = global_solver_job_v2_migrator; + m.attr("SOLVER_LOCK") = global_solver_job_v2_migrator; + m.attr("SOLVER_DISTUPGRADE") = global_solver_job_v2_migrator; + m.attr("SOLVER_VERIFY") = global_solver_job_v2_migrator; + m.attr("SOLVER_DROP_ORPHANED") = global_solver_job_v2_migrator; + m.attr("SOLVER_USERINSTALLED") = global_solver_job_v2_migrator; + m.attr("SOLVER_ALLOWUNINSTALL") = global_solver_job_v2_migrator; + m.attr("SOLVER_FAVOR") = global_solver_job_v2_migrator; + m.attr("SOLVER_DISFAVOR") = global_solver_job_v2_migrator; + m.attr("SOLVER_JOBMASK") = global_solver_job_v2_migrator; + m.attr("SOLVER_WEAK") = global_solver_job_v2_migrator; + m.attr("SOLVER_ESSENTIAL") = global_solver_job_v2_migrator; + m.attr("SOLVER_CLEANDEPS") = global_solver_job_v2_migrator; + m.attr("SOLVER_ORUPDATE") = global_solver_job_v2_migrator; + m.attr("SOLVER_FORCEBEST") = global_solver_job_v2_migrator; + m.attr("SOLVER_TARGETED") = global_solver_job_v2_migrator; + m.attr("SOLVER_NOTBYUSER") = global_solver_job_v2_migrator; + m.attr("SOLVER_SETEV") = global_solver_job_v2_migrator; + m.attr("SOLVER_SETEVR") = global_solver_job_v2_migrator; + m.attr("SOLVER_SETARCH") = global_solver_job_v2_migrator; + m.attr("SOLVER_SETVENDOR") = global_solver_job_v2_migrator; + m.attr("SOLVER_SETREPO") = global_solver_job_v2_migrator; + m.attr("SOLVER_NOAUTOSET") = global_solver_job_v2_migrator; + m.attr("SOLVER_SETNAME") = global_solver_job_v2_migrator; + m.attr("SOLVER_SETMASK") = global_solver_job_v2_migrator; /************** * Bindings * @@ -456,64 +526,18 @@ bind_submodule_impl(pybind11::module_ m) .def_readwrite("description", &SolverProblem::description) .def("__str__", [](const SolverProblem& self) { return self.description; }); - py::class_(pySolver, "Flags") - .def(py::init( - [](bool keep_dependencies, bool keep_specs, bool force_reinstall) -> MSolver::Flags - { - return { - /* .keep_dependencies= */ keep_dependencies, - /* .keep_specs= */ keep_specs, - /* .force_reinstall= */ force_reinstall, - }; - } - )) - .def_readwrite("keep_dependencies", &MSolver::Flags::keep_dependencies) - .def_readwrite("keep_specs", &MSolver::Flags::keep_specs) - .def_readwrite("force_reinstall", &MSolver::Flags::force_reinstall); - - pySolver.def(py::init>>(), py::keep_alive<1, 2>()) - .def( - "add_jobs", - [](MSolver&, int) - { - // V2 migrator - throw std::runtime_error("All jobs must be provided in a single Request."); - } - ) - .def( - "add_global_job", - [](MSolver&, int) - { - // V2 migrator - throw std::runtime_error("All jobs must be provided in a single Request."); - } - ) - .def( - "add_pin", - [](MSolver&, int) - { - // V2 migrator - throw std::runtime_error("All jobs must be provided in a single Request."); - } - ) - .def("set_libsolv_flags", &MSolver::py_set_libsolv_flags) - .def( - "set_flags", - [](MSolver&, const std::vector>&) - { - // V2 migrator - throw std::runtime_error("Use Solver.set_libsolv_flags instead."); - } - ) - .def("set_flags", &MSolver::set_flags) - .def( - "set_postsolve_flags", - [](MSolver&, const std::vector>&) - { - // V2 migrator - throw std::runtime_error("Use Solver.set_flags with Solver.Flags object instead."); - } - ) + constexpr auto flags_v2_migrator = [](MSolver&, py::args, py::kwargs) + { throw std::runtime_error("All flags need to be passed in the libmambapy.solver.Request."); }; + constexpr auto job_v2_migrator = [](MSolver&, py::args, py::kwargs) + { throw std::runtime_error("All jobs need to be passed in the libmambapy.solver.Request."); }; + + pySolver.def(py::init(), py::keep_alive<1, 2>()) + .def("add_jobs", job_v2_migrator) + .def("add_global_job", job_v2_migrator) + .def("add_pin", job_v2_migrator) + .def("set_flags", flags_v2_migrator) + .def("set_libsolv_flags", flags_v2_migrator) + .def("set_postsolve_flags", flags_v2_migrator) .def("is_solved", &MSolver::is_solved) .def("problems_to_str", &MSolver::problems_to_str) .def("all_problems_to_str", &MSolver::all_problems_to_str) @@ -1351,74 +1375,6 @@ bind_submodule_impl(pybind11::module_ m) m.def("cancel_json_output", [] { Console::instance().cancel_json_print(); }); - m.attr("SOLVER_SOLVABLE") = SOLVER_SOLVABLE; - m.attr("SOLVER_SOLVABLE_NAME") = SOLVER_SOLVABLE_NAME; - m.attr("SOLVER_SOLVABLE_PROVIDES") = SOLVER_SOLVABLE_PROVIDES; - m.attr("SOLVER_SOLVABLE_ONE_OF") = SOLVER_SOLVABLE_ONE_OF; - m.attr("SOLVER_SOLVABLE_REPO") = SOLVER_SOLVABLE_REPO; - m.attr("SOLVER_SOLVABLE_ALL") = SOLVER_SOLVABLE_ALL; - m.attr("SOLVER_SELECTMASK") = SOLVER_SELECTMASK; - m.attr("SOLVER_NOOP") = SOLVER_NOOP; - m.attr("SOLVER_INSTALL") = SOLVER_INSTALL; - m.attr("SOLVER_ERASE") = SOLVER_ERASE; - m.attr("SOLVER_UPDATE") = SOLVER_UPDATE; - m.attr("SOLVER_WEAKENDEPS") = SOLVER_WEAKENDEPS; - m.attr("SOLVER_MULTIVERSION") = SOLVER_MULTIVERSION; - m.attr("SOLVER_LOCK") = SOLVER_LOCK; - m.attr("SOLVER_DISTUPGRADE") = SOLVER_DISTUPGRADE; - m.attr("SOLVER_VERIFY") = SOLVER_VERIFY; - m.attr("SOLVER_DROP_ORPHANED") = SOLVER_DROP_ORPHANED; - m.attr("SOLVER_USERINSTALLED") = SOLVER_USERINSTALLED; - m.attr("SOLVER_ALLOWUNINSTALL") = SOLVER_ALLOWUNINSTALL; - m.attr("SOLVER_FAVOR") = SOLVER_FAVOR; - m.attr("SOLVER_DISFAVOR") = SOLVER_DISFAVOR; - m.attr("SOLVER_JOBMASK") = SOLVER_JOBMASK; - m.attr("SOLVER_WEAK") = SOLVER_WEAK; - m.attr("SOLVER_ESSENTIAL") = SOLVER_ESSENTIAL; - m.attr("SOLVER_CLEANDEPS") = SOLVER_CLEANDEPS; - m.attr("SOLVER_ORUPDATE") = SOLVER_ORUPDATE; - m.attr("SOLVER_FORCEBEST") = SOLVER_FORCEBEST; - m.attr("SOLVER_TARGETED") = SOLVER_TARGETED; - m.attr("SOLVER_NOTBYUSER") = SOLVER_NOTBYUSER; - m.attr("SOLVER_SETEV") = SOLVER_SETEV; - m.attr("SOLVER_SETEVR") = SOLVER_SETEVR; - m.attr("SOLVER_SETARCH") = SOLVER_SETARCH; - m.attr("SOLVER_SETVENDOR") = SOLVER_SETVENDOR; - m.attr("SOLVER_SETREPO") = SOLVER_SETREPO; - m.attr("SOLVER_NOAUTOSET") = SOLVER_NOAUTOSET; - m.attr("SOLVER_SETNAME") = SOLVER_SETNAME; - m.attr("SOLVER_SETMASK") = SOLVER_SETMASK; - - // Solver flags - m.attr("SOLVER_FLAG_ALLOW_DOWNGRADE") = SOLVER_FLAG_ALLOW_DOWNGRADE; - m.attr("SOLVER_FLAG_ALLOW_ARCHCHANGE") = SOLVER_FLAG_ALLOW_ARCHCHANGE; - m.attr("SOLVER_FLAG_ALLOW_VENDORCHANGE") = SOLVER_FLAG_ALLOW_VENDORCHANGE; - m.attr("SOLVER_FLAG_ALLOW_UNINSTALL") = SOLVER_FLAG_ALLOW_UNINSTALL; - m.attr("SOLVER_FLAG_NO_UPDATEPROVIDE") = SOLVER_FLAG_NO_UPDATEPROVIDE; - m.attr("SOLVER_FLAG_SPLITPROVIDES") = SOLVER_FLAG_SPLITPROVIDES; - m.attr("SOLVER_FLAG_IGNORE_RECOMMENDED") = SOLVER_FLAG_IGNORE_RECOMMENDED; - m.attr("SOLVER_FLAG_ADD_ALREADY_RECOMMENDED") = SOLVER_FLAG_ADD_ALREADY_RECOMMENDED; - m.attr("SOLVER_FLAG_NO_INFARCHCHECK") = SOLVER_FLAG_NO_INFARCHCHECK; - m.attr("SOLVER_FLAG_ALLOW_NAMECHANGE") = SOLVER_FLAG_ALLOW_NAMECHANGE; - m.attr("SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES") = SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES; - m.attr("SOLVER_FLAG_BEST_OBEY_POLICY") = SOLVER_FLAG_BEST_OBEY_POLICY; - m.attr("SOLVER_FLAG_NO_AUTOTARGET") = SOLVER_FLAG_NO_AUTOTARGET; - m.attr("SOLVER_FLAG_DUP_ALLOW_DOWNGRADE") = SOLVER_FLAG_DUP_ALLOW_DOWNGRADE; - m.attr("SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE") = SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE; - m.attr("SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE") = SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE; - m.attr("SOLVER_FLAG_DUP_ALLOW_NAMECHANGE") = SOLVER_FLAG_DUP_ALLOW_NAMECHANGE; - m.attr("SOLVER_FLAG_KEEP_ORPHANS") = SOLVER_FLAG_KEEP_ORPHANS; - m.attr("SOLVER_FLAG_BREAK_ORPHANS") = SOLVER_FLAG_BREAK_ORPHANS; - m.attr("SOLVER_FLAG_FOCUS_INSTALLED") = SOLVER_FLAG_FOCUS_INSTALLED; - m.attr("SOLVER_FLAG_YUM_OBSOLETES") = SOLVER_FLAG_YUM_OBSOLETES; - m.attr("SOLVER_FLAG_NEED_UPDATEPROVIDE") = SOLVER_FLAG_NEED_UPDATEPROVIDE; - m.attr("SOLVER_FLAG_URPM_REORDER") = SOLVER_FLAG_URPM_REORDER; - m.attr("SOLVER_FLAG_FOCUS_BEST") = SOLVER_FLAG_FOCUS_BEST; - m.attr("SOLVER_FLAG_STRONG_RECOMMENDS") = SOLVER_FLAG_STRONG_RECOMMENDS; - m.attr("SOLVER_FLAG_INSTALL_ALSO_UPDATES") = SOLVER_FLAG_INSTALL_ALSO_UPDATES; - m.attr("SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED") = SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED; - m.attr("SOLVER_FLAG_STRICT_REPO_PRIORITY") = SOLVER_FLAG_STRICT_REPO_PRIORITY; - // Solver rule flags py::enum_(m, "SolverRuleinfo") .value("SOLVER_RULE_UNKNOWN", SolverRuleinfo::SOLVER_RULE_UNKNOWN) diff --git a/libmambapy/src/libmambapy/bindings/solver.cpp b/libmambapy/src/libmambapy/bindings/solver.cpp index fc5d69d5d3..3f8739cf1d 100644 --- a/libmambapy/src/libmambapy/bindings/solver.cpp +++ b/libmambapy/src/libmambapy/bindings/solver.cpp @@ -1,5 +1,3 @@ -// Copyright (c) 2023, QuantStack and Mamba Contributors -// // Distributed under the terms of the BSD 3-Clause License. // // The full license is in the file LICENSE, distributed with this software. @@ -107,10 +105,50 @@ namespace mambapy // Type made opaque at the top of this file py::bind_vector(py_request, "ItemList"); + py::class_(py_request, "Flags") + .def( + py::init( + [](bool keep_dependencies, + bool keep_user_specs, + bool force_reinstall, + bool allow_downgrade, + bool allow_uninstall, + bool strict_repo_priority) -> Request::Flags + { + return { + /* .keep_dependencies= */ keep_dependencies, + /* .keep_user_specs= */ keep_user_specs, + /* .force_reinstall= */ force_reinstall, + /* .allow_downgrade= */ allow_downgrade, + /* .allow_uninstall= */ allow_uninstall, + /* .strict_repo_priority= */ strict_repo_priority, + }; + } + ), + py::arg("keep_dependencies") = true, + py::arg("keep_user_specs") = true, + py::arg("force_reinstall") = false, + py::arg("allow_downgrade") = true, + py::arg("allow_uninstall") = true, + py::arg("strict_repo_priority") = true + ) + .def_readwrite("keep_dependencies", &Request::Flags::keep_dependencies) + .def_readwrite("keep_user_specs", &Request::Flags::keep_user_specs) + .def_readwrite("force_reinstall", &Request::Flags::force_reinstall) + .def_readwrite("allow_downgrade", &Request::Flags::allow_downgrade) + .def_readwrite("allow_uninstall", &Request::Flags::allow_uninstall) + .def_readwrite("strict_repo_priority", &Request::Flags::strict_repo_priority) + .def("__copy__", ©) + .def("__deepcopy__", &deepcopy, py::arg("memo")); + py_request .def( // Big copy unfortunately - py::init([](Request::item_list items) -> Request { return { std::move(items) }; }) + py::init( + [](Request::Flags flags, Request::item_list items) -> Request { + return { std::move(flags), std::move(items) }; + } + ) ) .def(py::init( [](py::iterable items) -> Request @@ -124,6 +162,7 @@ namespace mambapy return request; } )) + .def_readwrite("flags", &Request::flags) .def_readwrite("items", &Request::items) .def("__copy__", ©) .def("__deepcopy__", &deepcopy, py::arg("memo")); diff --git a/libmambapy/tests/test_solver.py b/libmambapy/tests/test_solver.py index b44adc4d45..7f5dc9ceaa 100644 --- a/libmambapy/tests/test_solver.py +++ b/libmambapy/tests/test_solver.py @@ -1,3 +1,4 @@ +import random import copy import pytest @@ -65,3 +66,28 @@ def test_Request_Item_clean(Item, kwargs): other = copy.deepcopy(itm) assert other is not itm assert other.clean_dependencies == itm.clean_dependencies + + +@pytest.mark.parametrize( + "attr", + [ + "keep_dependencies", + "keep_user_specs", + "force_reinstall", + "allow_downgrade", + "allow_uninstall", + "strict_repo_priority", + ], +) +def test_Request_Flags_boolean(attr): + Flags = libmambapy.solver.Request.Flags + + for _ in range(10): + val = bool(random.randint(0, 1)) + flags = Flags(**{attr: val}) + + assert getattr(flags, attr) == val + + val = bool(random.randint(0, 1)) + setattr(flags, attr, val) + assert getattr(flags, attr) == val