mirror of https://github.com/mamba-org/mamba.git
Bind text_style and graphic params (#3266)
* Rename binding utils.hpp > bind_utils.hpp * Bind fmt::text_style * Change format type in Unsolvable explain message * Bind attributes * Bind GraphicsParams
This commit is contained in:
parent
b5195d96b0
commit
80f1e84d49
|
@ -26,7 +26,6 @@ namespace mamba
|
||||||
/** Some action is unsafe or not trusted. */
|
/** Some action is unsafe or not trusted. */
|
||||||
fmt::text_style unsafe;
|
fmt::text_style unsafe;
|
||||||
|
|
||||||
|
|
||||||
/** Reference to some input from the user. */
|
/** Reference to some input from the user. */
|
||||||
fmt::text_style user;
|
fmt::text_style user;
|
||||||
/** Input from the user was ignored or has no effect. */
|
/** Input from the user was ignored or has no effect. */
|
||||||
|
|
|
@ -50,11 +50,11 @@ namespace mamba::solver::libsolv
|
||||||
auto explain_problems_to( //
|
auto explain_problems_to( //
|
||||||
Database& pool,
|
Database& pool,
|
||||||
std::ostream& out,
|
std::ostream& out,
|
||||||
const Palette& palette
|
const ProblemsMessageFormat& format
|
||||||
) const -> std::ostream&;
|
) const -> std::ostream&;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
explain_problems(Database& pool, const Palette& palette) const -> std::string;
|
explain_problems(Database& pool, const ProblemsMessageFormat& format) const -> std::string;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -588,7 +588,14 @@ namespace mamba
|
||||||
|
|
||||||
if (auto* unsolvable = std::get_if<solver::libsolv::UnSolvable>(&outcome))
|
if (auto* unsolvable = std::get_if<solver::libsolv::UnSolvable>(&outcome))
|
||||||
{
|
{
|
||||||
unsolvable->explain_problems_to(db, LOG_ERROR, ctx.graphics_params.palette);
|
unsolvable->explain_problems_to(
|
||||||
|
db,
|
||||||
|
LOG_ERROR,
|
||||||
|
{
|
||||||
|
/* .unavailable= */ ctx.graphics_params.palette.failure,
|
||||||
|
/* .available= */ ctx.graphics_params.palette.success,
|
||||||
|
}
|
||||||
|
);
|
||||||
if (retry_clean_cache && !is_retry)
|
if (retry_clean_cache && !is_retry)
|
||||||
{
|
{
|
||||||
ctx.local_repodata_ttl = 2;
|
ctx.local_repodata_ttl = 2;
|
||||||
|
|
|
@ -482,30 +482,26 @@ namespace mamba::solver::libsolv
|
||||||
return ProblemsGraphCreator(Database::Impl::get(pool), *m_solver).problem_graph();
|
return ProblemsGraphCreator(Database::Impl::get(pool), *m_solver).problem_graph();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto
|
auto UnSolvable::explain_problems_to(
|
||||||
UnSolvable::explain_problems_to(Database& pool, std::ostream& out, const Palette& palette) const
|
Database& pool,
|
||||||
-> std::ostream&
|
std::ostream& out,
|
||||||
|
const ProblemsMessageFormat& format
|
||||||
|
) const -> std::ostream&
|
||||||
{
|
{
|
||||||
out << "Could not solve for environment specs\n";
|
out << "Could not solve for environment specs\n";
|
||||||
const auto pbs = problems_graph(pool);
|
const auto pbs = problems_graph(pool);
|
||||||
const auto pbs_simplified = simplify_conflicts(pbs);
|
const auto pbs_simplified = simplify_conflicts(pbs);
|
||||||
const auto cp_pbs = CompressedProblemsGraph::from_problems_graph(pbs_simplified);
|
const auto cp_pbs = CompressedProblemsGraph::from_problems_graph(pbs_simplified);
|
||||||
print_problem_tree_msg(
|
print_problem_tree_msg(out, cp_pbs, format);
|
||||||
out,
|
|
||||||
cp_pbs,
|
|
||||||
{
|
|
||||||
/* .unavailable= */ palette.failure,
|
|
||||||
/* .available= */ palette.success,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto UnSolvable::explain_problems(Database& pool, const Palette& palette) const -> std::string
|
auto
|
||||||
|
UnSolvable::explain_problems(Database& pool, const ProblemsMessageFormat& format) const -> std::string
|
||||||
|
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
explain_problems_to(pool, ss, palette);
|
explain_problems_to(pool, ss, format);
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ pybind11_add_module(
|
||||||
# All bindings used to live in a global module
|
# All bindings used to live in a global module
|
||||||
src/libmambapy/bindings/legacy.cpp
|
src/libmambapy/bindings/legacy.cpp
|
||||||
# Submodules
|
# Submodules
|
||||||
|
src/libmambapy/bindings/utils.cpp
|
||||||
src/libmambapy/bindings/specs.cpp
|
src/libmambapy/bindings/specs.cpp
|
||||||
src/libmambapy/bindings/solver.cpp
|
src/libmambapy/bindings/solver.cpp
|
||||||
src/libmambapy/bindings/solver_libsolv.cpp
|
src/libmambapy/bindings/solver_libsolv.cpp
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Import all submodules so that one can use them directly with `import libmambapy`
|
# Import all submodules so that one can use them directly with `import libmambapy`
|
||||||
|
import libmambapy.utils
|
||||||
import libmambapy.version
|
import libmambapy.version
|
||||||
import libmambapy.specs
|
import libmambapy.specs
|
||||||
import libmambapy.solver
|
import libmambapy.solver
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
//
|
//
|
||||||
// The full license is in the file LICENSE, distributed with this software.
|
// The full license is in the file LICENSE, distributed with this software.
|
||||||
|
|
||||||
#ifndef LIBMAMBAPY_UTILS_HPP
|
#ifndef LIBMAMBAPY_BIND_UTILS_HPP
|
||||||
#define LIBMAMBAPY_UTILS_HPP
|
#define LIBMAMBAPY_BIND_UTILS_HPP
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
PYBIND11_MODULE(bindings, m)
|
PYBIND11_MODULE(bindings, m)
|
||||||
{
|
{
|
||||||
|
mambapy::bind_submodule_utils(m.def_submodule("utils"));
|
||||||
mambapy::bind_submodule_specs(m.def_submodule("specs"));
|
mambapy::bind_submodule_specs(m.def_submodule("specs"));
|
||||||
auto solver_submodule = m.def_submodule("solver");
|
auto solver_submodule = m.def_submodule("solver");
|
||||||
mambapy::bind_submodule_solver(solver_submodule);
|
mambapy::bind_submodule_solver(solver_submodule);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
namespace mambapy
|
namespace mambapy
|
||||||
{
|
{
|
||||||
|
void bind_submodule_utils(pybind11::module_ m);
|
||||||
void bind_submodule_specs(pybind11::module_ m);
|
void bind_submodule_specs(pybind11::module_ m);
|
||||||
void bind_submodule_solver(pybind11::module_ m);
|
void bind_submodule_solver(pybind11::module_ m);
|
||||||
void bind_submodule_solver_libsolv(pybind11::module_ m);
|
void bind_submodule_solver_libsolv(pybind11::module_ m);
|
||||||
|
|
|
@ -35,11 +35,11 @@
|
||||||
#include "mamba/validation/tools.hpp"
|
#include "mamba/validation/tools.hpp"
|
||||||
#include "mamba/validation/update_framework_v0_6.hpp"
|
#include "mamba/validation/update_framework_v0_6.hpp"
|
||||||
|
|
||||||
|
#include "bind_utils.hpp"
|
||||||
#include "bindings.hpp"
|
#include "bindings.hpp"
|
||||||
#include "expected_caster.hpp"
|
#include "expected_caster.hpp"
|
||||||
#include "flat_set_caster.hpp"
|
#include "flat_set_caster.hpp"
|
||||||
#include "path_caster.hpp"
|
#include "path_caster.hpp"
|
||||||
#include "utils.hpp"
|
|
||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
@ -620,7 +620,25 @@ bind_submodule_impl(pybind11::module_ m)
|
||||||
|
|
||||||
py::class_<Palette>(m, "Palette")
|
py::class_<Palette>(m, "Palette")
|
||||||
.def_static("no_color", &Palette::no_color)
|
.def_static("no_color", &Palette::no_color)
|
||||||
.def_static("terminal", &Palette::terminal);
|
.def_static("terminal", &Palette::terminal)
|
||||||
|
.def_readwrite("success", &Palette::success)
|
||||||
|
.def_readwrite("failure", &Palette::failure)
|
||||||
|
.def_readwrite("external", &Palette::external)
|
||||||
|
.def_readwrite("shown", &Palette::shown)
|
||||||
|
.def_readwrite("safe", &Palette::safe)
|
||||||
|
.def_readwrite("unsafe", &Palette::unsafe)
|
||||||
|
.def_readwrite("user", &Palette::user)
|
||||||
|
.def_readwrite("ignored", &Palette::ignored)
|
||||||
|
.def_readwrite("addition", &Palette::addition)
|
||||||
|
.def_readwrite("deletion", &Palette::deletion)
|
||||||
|
.def_readwrite("progress_bar_none", &Palette::progress_bar_none)
|
||||||
|
.def_readwrite("progress_bar_downloaded", &Palette::progress_bar_downloaded)
|
||||||
|
.def_readwrite("progress_bar_extracted", &Palette::progress_bar_extracted);
|
||||||
|
|
||||||
|
py::class_<Context::GraphicsParams>(m, "GraphicsParams")
|
||||||
|
.def(py::init())
|
||||||
|
.def_readwrite("no_progress_bars", &Context::GraphicsParams::no_progress_bars)
|
||||||
|
.def_readwrite("palette", &Context::GraphicsParams::palette);
|
||||||
|
|
||||||
py::class_<Context, std::unique_ptr<Context, py::nodelete>> ctx(m, "Context");
|
py::class_<Context, std::unique_ptr<Context, py::nodelete>> ctx(m, "Context");
|
||||||
ctx //
|
ctx //
|
||||||
|
@ -641,6 +659,7 @@ bind_submodule_impl(pybind11::module_ m)
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
.def_static("use_default_signal_handler", &Context::use_default_signal_handler)
|
.def_static("use_default_signal_handler", &Context::use_default_signal_handler)
|
||||||
|
.def_readwrite("graphics_params", &Context::graphics_params)
|
||||||
.def_readwrite("offline", &Context::offline)
|
.def_readwrite("offline", &Context::offline)
|
||||||
.def_readwrite("local_repodata_ttl", &Context::local_repodata_ttl)
|
.def_readwrite("local_repodata_ttl", &Context::local_repodata_ttl)
|
||||||
.def_readwrite("use_index_cache", &Context::use_index_cache)
|
.def_readwrite("use_index_cache", &Context::use_index_cache)
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
#include "mamba/solver/request.hpp"
|
#include "mamba/solver/request.hpp"
|
||||||
#include "mamba/solver/solution.hpp"
|
#include "mamba/solver/solution.hpp"
|
||||||
|
|
||||||
|
#include "bind_utils.hpp"
|
||||||
#include "bindings.hpp"
|
#include "bindings.hpp"
|
||||||
#include "flat_set_caster.hpp"
|
#include "flat_set_caster.hpp"
|
||||||
#include "utils.hpp"
|
|
||||||
|
|
||||||
namespace mamba::solver
|
namespace mamba::solver
|
||||||
{
|
{
|
||||||
|
@ -388,6 +388,31 @@ namespace mambapy
|
||||||
)
|
)
|
||||||
.def_static("simplify_conflicts", &solver::simplify_conflicts);
|
.def_static("simplify_conflicts", &solver::simplify_conflicts);
|
||||||
|
|
||||||
|
py::class_<ProblemsMessageFormat>(m, "ProblemsMessageFormat")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def(
|
||||||
|
py::init(
|
||||||
|
[](fmt::text_style unavailable,
|
||||||
|
fmt::text_style available,
|
||||||
|
std::array<std::string_view, 4> indents) -> ProblemsMessageFormat
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
/* .unavailable= */ unavailable,
|
||||||
|
/* .available= */ available,
|
||||||
|
/* .indents= */ indents,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
),
|
||||||
|
py::arg("unavailable"),
|
||||||
|
py::arg("available"),
|
||||||
|
py::arg("indents")
|
||||||
|
)
|
||||||
|
.def_readwrite("unavailable", &ProblemsMessageFormat::unavailable)
|
||||||
|
.def_readwrite("available", &ProblemsMessageFormat::available)
|
||||||
|
.def_readwrite("indents", &ProblemsMessageFormat::indents)
|
||||||
|
.def("__copy__", ©<ProblemsMessageFormat>)
|
||||||
|
.def("__deepcopy__", &deepcopy<ProblemsMessageFormat>, py::arg("memo"));
|
||||||
|
|
||||||
auto py_compressed_problems_graph = py::class_<CompressedProblemsGraph>(
|
auto py_compressed_problems_graph = py::class_<CompressedProblemsGraph>(
|
||||||
m,
|
m,
|
||||||
"CompressedProblemsGraph"
|
"CompressedProblemsGraph"
|
||||||
|
@ -481,9 +506,6 @@ namespace mambapy
|
||||||
return std::pair(g.nodes(), g.edges());
|
return std::pair(g.nodes(), g.edges());
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.def(
|
.def("tree_message", &problem_tree_msg, py::arg("format") = ProblemsMessageFormat());
|
||||||
"tree_message",
|
|
||||||
[](const CompressedProblemsGraph& self) { return problem_tree_msg(self); }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,16 @@
|
||||||
#include <pybind11/operators.h>
|
#include <pybind11/operators.h>
|
||||||
#include <pybind11/pybind11.h>
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
#include "mamba/core/palette.hpp"
|
|
||||||
#include "mamba/solver/libsolv/database.hpp"
|
#include "mamba/solver/libsolv/database.hpp"
|
||||||
#include "mamba/solver/libsolv/parameters.hpp"
|
#include "mamba/solver/libsolv/parameters.hpp"
|
||||||
#include "mamba/solver/libsolv/repo_info.hpp"
|
#include "mamba/solver/libsolv/repo_info.hpp"
|
||||||
#include "mamba/solver/libsolv/solver.hpp"
|
#include "mamba/solver/libsolv/solver.hpp"
|
||||||
#include "mamba/solver/libsolv/unsolvable.hpp"
|
#include "mamba/solver/libsolv/unsolvable.hpp"
|
||||||
|
|
||||||
|
#include "bind_utils.hpp"
|
||||||
#include "bindings.hpp"
|
#include "bindings.hpp"
|
||||||
#include "expected_caster.hpp"
|
#include "expected_caster.hpp"
|
||||||
#include "path_caster.hpp"
|
#include "path_caster.hpp"
|
||||||
#include "utils.hpp"
|
|
||||||
|
|
||||||
namespace mambapy
|
namespace mambapy
|
||||||
{
|
{
|
||||||
|
@ -223,7 +222,7 @@ namespace mambapy
|
||||||
"explain_problems",
|
"explain_problems",
|
||||||
&UnSolvable::explain_problems,
|
&UnSolvable::explain_problems,
|
||||||
py::arg("database"),
|
py::arg("database"),
|
||||||
py::arg("palette")
|
py::arg("format")
|
||||||
);
|
);
|
||||||
|
|
||||||
constexpr auto solver_flags_v2_migrator = [](Solver&, py::args, py::kwargs) {
|
constexpr auto solver_flags_v2_migrator = [](Solver&, py::args, py::kwargs) {
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
#include "mamba/specs/version.hpp"
|
#include "mamba/specs/version.hpp"
|
||||||
#include "mamba/specs/version_spec.hpp"
|
#include "mamba/specs/version_spec.hpp"
|
||||||
|
|
||||||
|
#include "bind_utils.hpp"
|
||||||
#include "bindings.hpp"
|
#include "bindings.hpp"
|
||||||
#include "expected_caster.hpp"
|
#include "expected_caster.hpp"
|
||||||
#include "flat_set_caster.hpp"
|
#include "flat_set_caster.hpp"
|
||||||
#include "utils.hpp"
|
|
||||||
#include "weakening_map_bind.hpp"
|
#include "weakening_map_bind.hpp"
|
||||||
|
|
||||||
PYBIND11_MAKE_OPAQUE(mamba::specs::VersionPart);
|
PYBIND11_MAKE_OPAQUE(mamba::specs::VersionPart);
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
// Copyright (c) 2024, 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.
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include <fmt/color.h>
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/stl_bind.h>
|
||||||
|
|
||||||
|
#include "bind_utils.hpp"
|
||||||
|
|
||||||
|
namespace mambapy
|
||||||
|
{
|
||||||
|
void bind_submodule_utils(pybind11::module_ m)
|
||||||
|
{
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
py::enum_<fmt::emphasis>(m, "TextEmphasis")
|
||||||
|
.value("Bold", fmt::emphasis::bold)
|
||||||
|
.value("Faint", fmt::emphasis::faint)
|
||||||
|
.value("Italic", fmt::emphasis::italic)
|
||||||
|
.value("Underline", fmt::emphasis::underline)
|
||||||
|
.value("Blink", fmt::emphasis::blink)
|
||||||
|
.value("Reverse", fmt::emphasis::reverse)
|
||||||
|
.value("Conceal", fmt::emphasis::conceal)
|
||||||
|
.value("Strikethrough", fmt::emphasis::strikethrough)
|
||||||
|
.def(py::init(&enum_from_str<fmt::emphasis>));
|
||||||
|
py::implicitly_convertible<py::str, fmt::emphasis>();
|
||||||
|
|
||||||
|
py::enum_<fmt::terminal_color>(m, "TextTerminalColor")
|
||||||
|
.value("Black", fmt::terminal_color::black)
|
||||||
|
.value("Red", fmt::terminal_color::red)
|
||||||
|
.value("Green", fmt::terminal_color::green)
|
||||||
|
.value("Yellow", fmt::terminal_color::yellow)
|
||||||
|
.value("Blue", fmt::terminal_color::blue)
|
||||||
|
.value("Magenta", fmt::terminal_color::magenta)
|
||||||
|
.value("Cyan", fmt::terminal_color::cyan)
|
||||||
|
.value("White", fmt::terminal_color::white)
|
||||||
|
.value("BrightBlack", fmt::terminal_color::bright_black)
|
||||||
|
.value("BrightRed", fmt::terminal_color::bright_red)
|
||||||
|
.value("BrightGreen", fmt::terminal_color::bright_green)
|
||||||
|
.value("BrightYellow", fmt::terminal_color::bright_yellow)
|
||||||
|
.value("BrightBlue", fmt::terminal_color::bright_blue)
|
||||||
|
.value("BrightMagenta", fmt::terminal_color::bright_magenta)
|
||||||
|
.value("BrightCyan", fmt::terminal_color::bright_cyan)
|
||||||
|
.value("BrightWhite", fmt::terminal_color::bright_white)
|
||||||
|
.def(py::init(&enum_from_str<fmt::terminal_color>));
|
||||||
|
py::implicitly_convertible<py::str, fmt::terminal_color>();
|
||||||
|
|
||||||
|
py::class_<fmt::rgb>(m, "TextRGBColor")
|
||||||
|
.def(py::init())
|
||||||
|
.def(
|
||||||
|
py::init<std::uint8_t, std::uint8_t, std::uint8_t>(),
|
||||||
|
py::arg("red") = 0,
|
||||||
|
py::arg("green") = 0,
|
||||||
|
py::arg("blue") = 0
|
||||||
|
)
|
||||||
|
.def_readwrite("red", &fmt::rgb::r)
|
||||||
|
.def_readwrite("green", &fmt::rgb::g)
|
||||||
|
.def_readwrite("blue", &fmt::rgb::b)
|
||||||
|
.def("__copy__", ©<fmt::rgb>)
|
||||||
|
.def("__deepcopy__", &deepcopy<fmt::rgb>, py::arg("memo"));
|
||||||
|
|
||||||
|
using ColorType = std::variant<fmt::terminal_color, fmt::rgb>;
|
||||||
|
py::class_<fmt::text_style>(m, "TextStyle")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def(
|
||||||
|
// We rely on ``std::optional`` and ``std::variant`` because
|
||||||
|
// ``fmt::detail::color_type`` is semi-private and would lead to introducing
|
||||||
|
// a new intermediary type.
|
||||||
|
// The bitwise ``|`` syntax of fmt is also not Pythonic.
|
||||||
|
// A more elegant option could be to implement a ``type_caster`` for ``color_type``.
|
||||||
|
py::init(
|
||||||
|
[](std::optional<ColorType> fg,
|
||||||
|
std::optional<ColorType> bg,
|
||||||
|
std::optional<fmt::emphasis> em) -> fmt::text_style
|
||||||
|
{
|
||||||
|
auto out = fmt::text_style();
|
||||||
|
if (em)
|
||||||
|
{
|
||||||
|
out = fmt::text_style(em.value());
|
||||||
|
}
|
||||||
|
if (fg)
|
||||||
|
{
|
||||||
|
std::visit([&out](const auto& color) { out |= fmt::fg(color); }, fg.value());
|
||||||
|
}
|
||||||
|
if (bg)
|
||||||
|
{
|
||||||
|
std::visit([&out](const auto& color) { out |= fmt::bg(color); }, bg.value());
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
),
|
||||||
|
py::arg("foreground") = std::nullopt,
|
||||||
|
py::arg("background") = std::nullopt,
|
||||||
|
py::arg("emphasis") = std::nullopt
|
||||||
|
)
|
||||||
|
.def_property_readonly(
|
||||||
|
"foreground",
|
||||||
|
[](const fmt::text_style& style) -> std::optional<ColorType>
|
||||||
|
{
|
||||||
|
if (!style.has_foreground())
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
const auto fg = style.get_foreground();
|
||||||
|
if (fg.is_rgb)
|
||||||
|
{
|
||||||
|
return { { fmt::rgb(fg.value.rgb_color) } };
|
||||||
|
}
|
||||||
|
return { { static_cast<fmt::terminal_color>(fg.value.term_color) } };
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.def_property_readonly(
|
||||||
|
"background",
|
||||||
|
[](const fmt::text_style& style) -> std::optional<ColorType>
|
||||||
|
{
|
||||||
|
if (!style.has_background())
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
const auto bg = style.get_background();
|
||||||
|
if (bg.is_rgb)
|
||||||
|
{
|
||||||
|
return { { fmt::rgb(bg.value.rgb_color) } };
|
||||||
|
}
|
||||||
|
return { { static_cast<fmt::terminal_color>(bg.value.term_color) } };
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.def_property_readonly(
|
||||||
|
"emphasis",
|
||||||
|
|
||||||
|
[](const fmt::text_style& style) -> std::optional<fmt::emphasis>
|
||||||
|
{
|
||||||
|
if (!style.has_emphasis())
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return { style.get_emphasis() };
|
||||||
|
}
|
||||||
|
|
||||||
|
)
|
||||||
|
.def("__copy__", ©<fmt::text_style>)
|
||||||
|
.def("__deepcopy__", &deepcopy<fmt::text_style>, py::arg("memo"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
# This file exists on its own rather than in `__init__.py` to make `import libmambapy.utils` work.
|
||||||
|
from libmambapy.bindings.utils import * # noqa: F403
|
|
@ -221,6 +221,36 @@ def test_Solution():
|
||||||
assert len(other.actions) == len(sol.actions)
|
assert len(other.actions) == len(sol.actions)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ProblemsMessageFormat():
|
||||||
|
ProblemsMessageFormat = libmambapy.solver.ProblemsMessageFormat
|
||||||
|
|
||||||
|
format = ProblemsMessageFormat()
|
||||||
|
|
||||||
|
format = ProblemsMessageFormat(
|
||||||
|
available=libmambapy.utils.TextStyle(foreground="Green"),
|
||||||
|
unavailable=libmambapy.utils.TextStyle(foreground="Red"),
|
||||||
|
indents=["a", "b", "c", "d"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Getters
|
||||||
|
assert format.available.foreground == libmambapy.utils.TextTerminalColor.Green
|
||||||
|
assert format.unavailable.foreground == libmambapy.utils.TextTerminalColor.Red
|
||||||
|
assert format.indents == ["a", "b", "c", "d"]
|
||||||
|
|
||||||
|
# Setters
|
||||||
|
format.available = libmambapy.utils.TextStyle(foreground="White")
|
||||||
|
format.unavailable = libmambapy.utils.TextStyle(foreground="Black")
|
||||||
|
format.indents = ["1", "2", "3", "4"]
|
||||||
|
assert format.available.foreground == libmambapy.utils.TextTerminalColor.White
|
||||||
|
assert format.unavailable.foreground == libmambapy.utils.TextTerminalColor.Black
|
||||||
|
assert format.indents == ["1", "2", "3", "4"]
|
||||||
|
|
||||||
|
# Copy
|
||||||
|
other = copy.deepcopy(format)
|
||||||
|
assert other is not format
|
||||||
|
assert other.indents == format.indents
|
||||||
|
|
||||||
|
|
||||||
def test_ProblemsGraph():
|
def test_ProblemsGraph():
|
||||||
# Create a ProblemsGraph
|
# Create a ProblemsGraph
|
||||||
db = libmambapy.solver.libsolv.Database(libmambapy.specs.ChannelResolveParams())
|
db = libmambapy.solver.libsolv.Database(libmambapy.specs.ChannelResolveParams())
|
||||||
|
@ -278,7 +308,7 @@ def test_ProblemsGraph():
|
||||||
nodes, edges = cp_pbg.graph()
|
nodes, edges = cp_pbg.graph()
|
||||||
assert len(nodes) > 0
|
assert len(nodes) > 0
|
||||||
assert len(edges) > 0
|
assert len(edges) > 0
|
||||||
assert "is not installable" in cp_pbg.tree_message()
|
assert "is not installable" in cp_pbg.tree_message(libmambapy.solver.ProblemsMessageFormat())
|
||||||
|
|
||||||
|
|
||||||
def test_CompressedProblemsGraph_NamedList():
|
def test_CompressedProblemsGraph_NamedList():
|
||||||
|
|
|
@ -278,7 +278,7 @@ def test_Solver_UnSolvable():
|
||||||
assert isinstance(outcome.problems_to_str(db), str)
|
assert isinstance(outcome.problems_to_str(db), str)
|
||||||
assert isinstance(outcome.all_problems_to_str(db), str)
|
assert isinstance(outcome.all_problems_to_str(db), str)
|
||||||
assert "The following package could not be installed" in outcome.explain_problems(
|
assert "The following package could not be installed" in outcome.explain_problems(
|
||||||
db, libmambapy.Palette.no_color()
|
db, libmambapy.solver.ProblemsMessageFormat()
|
||||||
)
|
)
|
||||||
assert outcome.problems_graph(db).graph() is not None
|
assert outcome.problems_graph(db).graph() is not None
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
import copy
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import libmambapy
|
||||||
|
|
||||||
|
|
||||||
|
def test_import_submodule():
|
||||||
|
import libmambapy.utils as utils
|
||||||
|
|
||||||
|
# Dummy execution
|
||||||
|
_p = utils.TextEmphasis
|
||||||
|
|
||||||
|
|
||||||
|
def test_import_recursive():
|
||||||
|
import libmambapy as mamba
|
||||||
|
|
||||||
|
# Dummy execution
|
||||||
|
_p = mamba.utils.TextEmphasis
|
||||||
|
|
||||||
|
|
||||||
|
def test_TextEmphasis():
|
||||||
|
TextEmphasis = libmambapy.utils.TextEmphasis
|
||||||
|
|
||||||
|
assert TextEmphasis.Bold.name == "Bold"
|
||||||
|
assert TextEmphasis.Faint.name == "Faint"
|
||||||
|
assert TextEmphasis.Italic.name == "Italic"
|
||||||
|
assert TextEmphasis.Underline.name == "Underline"
|
||||||
|
assert TextEmphasis.Blink.name == "Blink"
|
||||||
|
assert TextEmphasis.Reverse.name == "Reverse"
|
||||||
|
assert TextEmphasis.Conceal.name == "Conceal"
|
||||||
|
assert TextEmphasis.Strikethrough.name == "Strikethrough"
|
||||||
|
|
||||||
|
assert TextEmphasis("Italic") == TextEmphasis.Italic
|
||||||
|
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
# No parsing, explicit name
|
||||||
|
TextEmphasis(" bold")
|
||||||
|
|
||||||
|
|
||||||
|
def test_TextTerminalColor():
|
||||||
|
TextTerminalColor = libmambapy.utils.TextTerminalColor
|
||||||
|
|
||||||
|
assert TextTerminalColor.Black.name == "Black"
|
||||||
|
assert TextTerminalColor.Red.name == "Red"
|
||||||
|
assert TextTerminalColor.Green.name == "Green"
|
||||||
|
assert TextTerminalColor.Yellow.name == "Yellow"
|
||||||
|
assert TextTerminalColor.Blue.name == "Blue"
|
||||||
|
assert TextTerminalColor.Magenta.name == "Magenta"
|
||||||
|
assert TextTerminalColor.Cyan.name == "Cyan"
|
||||||
|
assert TextTerminalColor.White.name == "White"
|
||||||
|
assert TextTerminalColor.BrightBlack.name == "BrightBlack"
|
||||||
|
assert TextTerminalColor.BrightRed.name == "BrightRed"
|
||||||
|
assert TextTerminalColor.BrightGreen.name == "BrightGreen"
|
||||||
|
assert TextTerminalColor.BrightYellow.name == "BrightYellow"
|
||||||
|
assert TextTerminalColor.BrightBlue.name == "BrightBlue"
|
||||||
|
assert TextTerminalColor.BrightMagenta.name == "BrightMagenta"
|
||||||
|
assert TextTerminalColor.BrightCyan.name == "BrightCyan"
|
||||||
|
assert TextTerminalColor.BrightWhite.name == "BrightWhite"
|
||||||
|
|
||||||
|
assert TextTerminalColor("Red") == TextTerminalColor.Red
|
||||||
|
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
# No parsing, explicit name
|
||||||
|
TextTerminalColor("red ")
|
||||||
|
|
||||||
|
|
||||||
|
def test_TextRGBColor():
|
||||||
|
TextRGBColor = libmambapy.utils.TextRGBColor
|
||||||
|
|
||||||
|
color = TextRGBColor(red=11, blue=33, green=22)
|
||||||
|
|
||||||
|
# Getters
|
||||||
|
assert color.red == 11
|
||||||
|
assert color.green == 22
|
||||||
|
assert color.blue == 33
|
||||||
|
|
||||||
|
# Setters
|
||||||
|
color.red = 1
|
||||||
|
color.green = 2
|
||||||
|
color.blue = 3
|
||||||
|
assert color.red == 1
|
||||||
|
assert color.green == 2
|
||||||
|
assert color.blue == 3
|
||||||
|
|
||||||
|
# Copy
|
||||||
|
other = copy.deepcopy(color)
|
||||||
|
assert other is not color
|
||||||
|
assert other.red == color.red
|
||||||
|
|
||||||
|
|
||||||
|
def test_TextStyle():
|
||||||
|
TextTerminalColor = libmambapy.utils.TextTerminalColor
|
||||||
|
TextRGBColor = libmambapy.utils.TextRGBColor
|
||||||
|
TextEmphasis = libmambapy.utils.TextEmphasis
|
||||||
|
TextStyle = libmambapy.utils.TextStyle
|
||||||
|
|
||||||
|
style = TextStyle()
|
||||||
|
assert style.foreground is None
|
||||||
|
assert style.background is None
|
||||||
|
assert style.emphasis is None
|
||||||
|
|
||||||
|
style = TextStyle(foreground="Red", background=TextRGBColor(red=123), emphasis="Underline")
|
||||||
|
assert style.foreground == TextTerminalColor.Red
|
||||||
|
assert style.background.red == 123
|
||||||
|
assert style.emphasis == TextEmphasis.Underline
|
||||||
|
|
||||||
|
# Copy
|
||||||
|
other = copy.deepcopy(style)
|
||||||
|
assert other is not style
|
||||||
|
assert other.emphasis == style.emphasis
|
Loading…
Reference in New Issue