mirror of https://github.com/mamba-org/mamba.git
Bind SAT error messages to python (#2127)
* Bind ProblemsGraph and CompressProblemGraph * Rename summary error message * Fix Python static property * Add stubgens for problems bindings * Give a little help to Windows * Windows * Hang in there MSVC * Fix Pybind init * Add graph all successors accessor * Change graph bindings to raw data * Add NamedList remove_duplicates py::arg * Regenerate stubgens
This commit is contained in:
parent
44f7727cf2
commit
0181538e54
|
@ -65,6 +65,8 @@ namespace mamba
|
|||
using typename Base::key_type;
|
||||
using typename Base::value_type;
|
||||
|
||||
conflict_map() = default;
|
||||
|
||||
using Base::empty;
|
||||
using Base::size;
|
||||
bool has_conflict(key_type const& a) const;
|
||||
|
@ -254,8 +256,8 @@ namespace mamba
|
|||
std::array<std::string_view, 4> indents = { "│ ", " ", "├─ ", "└─ " };
|
||||
};
|
||||
|
||||
std::ostream& print_summary_msg(std::ostream& out, CompressedProblemsGraph const& pbs);
|
||||
std::string summary_msg(CompressedProblemsGraph const& pbs);
|
||||
std::ostream& print_problem_summary_msg(std::ostream& out, CompressedProblemsGraph const& pbs);
|
||||
std::string problem_summary_msg(CompressedProblemsGraph const& pbs);
|
||||
|
||||
std::ostream& print_problem_tree_msg(std::ostream& out,
|
||||
CompressedProblemsGraph const& pbs,
|
||||
|
|
|
@ -138,7 +138,9 @@ namespace mamba
|
|||
node_t const& node(node_id id) const;
|
||||
node_t& node(node_id id);
|
||||
const node_id_list& successors(node_id id) const;
|
||||
const adjacency_list& successors() const;
|
||||
const node_id_list& predecessors(node_id id) const;
|
||||
const adjacency_list& predecessors() const;
|
||||
bool has_node(node_id id) const;
|
||||
bool has_edge(node_id from, node_id to) const;
|
||||
|
||||
|
@ -457,12 +459,24 @@ namespace mamba
|
|||
return m_successors[id];
|
||||
}
|
||||
|
||||
template <typename N, typename G>
|
||||
auto DiGraphBase<N, G>::successors() const -> const adjacency_list&
|
||||
{
|
||||
return m_successors;
|
||||
}
|
||||
|
||||
template <typename N, typename G>
|
||||
auto DiGraphBase<N, G>::predecessors(node_id id) const -> const node_id_list&
|
||||
{
|
||||
return m_predecessors[id];
|
||||
}
|
||||
|
||||
template <typename N, typename G>
|
||||
auto DiGraphBase<N, G>::predecessors() const -> const adjacency_list&
|
||||
{
|
||||
return m_predecessors;
|
||||
}
|
||||
|
||||
template <typename N, typename G>
|
||||
auto DiGraphBase<N, G>::has_node(node_id id) const -> bool
|
||||
{
|
||||
|
|
|
@ -963,15 +963,15 @@ namespace mamba
|
|||
* Implementation of summary_msg *
|
||||
***********************************/
|
||||
|
||||
std::ostream& print_summary_msg(std::ostream& out, CompressedProblemsGraph const& pbs)
|
||||
std::ostream& print_problem_summary_msg(std::ostream& out, CompressedProblemsGraph const& pbs)
|
||||
{
|
||||
return out << "Could not solve for environment specs\n";
|
||||
}
|
||||
|
||||
std::string summary_msg(CompressedProblemsGraph const& pbs)
|
||||
std::string problem_summary_msg(CompressedProblemsGraph const& pbs)
|
||||
{
|
||||
std::stringstream ss;
|
||||
print_summary_msg(ss, pbs);
|
||||
print_problem_summary_msg(ss, pbs);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,10 @@ import typing
|
|||
__all__ = [
|
||||
"Channel",
|
||||
"ChannelPriority",
|
||||
"CompressedProblemsGraph",
|
||||
"Configuration",
|
||||
"Context",
|
||||
"DependencyInfo",
|
||||
"DownloadTargetList",
|
||||
"ExtraPkgInfo",
|
||||
"History",
|
||||
|
@ -32,6 +34,7 @@ __all__ = [
|
|||
"PkgMgr",
|
||||
"Pool",
|
||||
"PrefixData",
|
||||
"ProblemsGraph",
|
||||
"Query",
|
||||
"QueryFormat",
|
||||
"Repo",
|
||||
|
@ -210,6 +213,114 @@ class ChannelPriority:
|
|||
kStrict: libmambapy.bindings.ChannelPriority # value = <ChannelPriority.kStrict: 2>
|
||||
pass
|
||||
|
||||
class CompressedProblemsGraph:
|
||||
class ConflictMap:
|
||||
def __bool__(self) -> bool: ...
|
||||
def __contains__(self, arg0: int) -> bool: ...
|
||||
def __init__(self) -> None: ...
|
||||
def __iter__(self) -> typing.Iterator: ...
|
||||
def __len__(self) -> int: ...
|
||||
def add(self, arg0: int, arg1: int) -> None: ...
|
||||
def clear(self) -> None: ...
|
||||
def conflicts(self, arg0: int) -> typing.Set[int]: ...
|
||||
def has_conflict(self, arg0: int) -> bool: ...
|
||||
def in_conflict(self, arg0: int, arg1: int) -> bool: ...
|
||||
pass
|
||||
|
||||
class ConstraintListNode:
|
||||
def __bool__(self) -> bool: ...
|
||||
def __init__(self) -> None: ...
|
||||
def __iter__(self) -> typing.Iterator: ...
|
||||
def __len__(self) -> int: ...
|
||||
def add(self, arg0: ProblemsGraph.ConstraintNode) -> None: ...
|
||||
def build_strings_trunc(
|
||||
self, sep: str = "|", etc: str = "...", remove_duplicates: bool = True
|
||||
) -> str: ...
|
||||
def clear(self) -> None: ...
|
||||
def name(self) -> str: ...
|
||||
def versions_trunc(
|
||||
self, sep: str = "|", etc: str = "...", remove_duplicates: bool = True
|
||||
) -> str: ...
|
||||
pass
|
||||
|
||||
class DependencyListList:
|
||||
def __bool__(self) -> bool: ...
|
||||
def __init__(self) -> None: ...
|
||||
def __iter__(self) -> typing.Iterator: ...
|
||||
def __len__(self) -> int: ...
|
||||
def add(self, arg0: DependencyInfo) -> None: ...
|
||||
def build_strings_trunc(
|
||||
self, sep: str = "|", etc: str = "...", remove_duplicates: bool = True
|
||||
) -> str: ...
|
||||
def clear(self) -> None: ...
|
||||
def name(self) -> str: ...
|
||||
def versions_trunc(
|
||||
self, sep: str = "|", etc: str = "...", remove_duplicates: bool = True
|
||||
) -> str: ...
|
||||
pass
|
||||
|
||||
class PackageListNode:
|
||||
def __bool__(self) -> bool: ...
|
||||
def __init__(self) -> None: ...
|
||||
def __iter__(self) -> typing.Iterator: ...
|
||||
def __len__(self) -> int: ...
|
||||
def add(self, arg0: ProblemsGraph.PackageNode) -> None: ...
|
||||
def build_strings_trunc(
|
||||
self, sep: str = "|", etc: str = "...", remove_duplicates: bool = True
|
||||
) -> str: ...
|
||||
def clear(self) -> None: ...
|
||||
def name(self) -> str: ...
|
||||
def versions_trunc(
|
||||
self, sep: str = "|", etc: str = "...", remove_duplicates: bool = True
|
||||
) -> str: ...
|
||||
pass
|
||||
|
||||
class RootNode:
|
||||
def __init__(self) -> None: ...
|
||||
pass
|
||||
|
||||
class UnresolvedDependencyListNode:
|
||||
def __bool__(self) -> bool: ...
|
||||
def __init__(self) -> None: ...
|
||||
def __iter__(self) -> typing.Iterator: ...
|
||||
def __len__(self) -> int: ...
|
||||
def add(self, arg0: ProblemsGraph.UnresolvedDependencyNode) -> None: ...
|
||||
def build_strings_trunc(
|
||||
self, sep: str = "|", etc: str = "...", remove_duplicates: bool = True
|
||||
) -> str: ...
|
||||
def clear(self) -> None: ...
|
||||
def name(self) -> str: ...
|
||||
def versions_trunc(
|
||||
self, sep: str = "|", etc: str = "...", remove_duplicates: bool = True
|
||||
) -> str: ...
|
||||
pass
|
||||
def conflicts(self) -> ProblemsGraph.ConflictMap: ...
|
||||
@staticmethod
|
||||
@typing.overload
|
||||
def from_problems_graph(arg0: ProblemsGraph) -> CompressedProblemsGraph: ...
|
||||
@staticmethod
|
||||
@typing.overload
|
||||
def from_problems_graph(
|
||||
arg0: ProblemsGraph, arg1: typing.Callable[[ProblemsGraph, int, int], bool]
|
||||
) -> CompressedProblemsGraph: ...
|
||||
def graph(
|
||||
self,
|
||||
) -> typing.Tuple[
|
||||
typing.List[
|
||||
typing.Union[
|
||||
ProblemsGraph.RootNode,
|
||||
CompressedProblemsGraph.PackageListNode,
|
||||
CompressedProblemsGraph.UnresolvedDependencyListNode,
|
||||
CompressedProblemsGraph.ConstraintListNode,
|
||||
]
|
||||
],
|
||||
typing.Dict[typing.Tuple[int, int], CompressedProblemsGraph.DependencyListList],
|
||||
]: ...
|
||||
def root_node(self) -> int: ...
|
||||
def summary_message(self) -> str: ...
|
||||
def tree_message(self) -> str: ...
|
||||
pass
|
||||
|
||||
class Configuration:
|
||||
def __init__(self) -> None: ...
|
||||
@property
|
||||
|
@ -484,6 +595,28 @@ class Context:
|
|||
pass
|
||||
pass
|
||||
|
||||
class DependencyInfo:
|
||||
def __eq__(self, arg0: DependencyInfo) -> bool: ...
|
||||
def __init__(self, arg0: str) -> None: ...
|
||||
def __str__(self) -> str: ...
|
||||
@property
|
||||
def build_string(self) -> str:
|
||||
"""
|
||||
:type: str
|
||||
"""
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""
|
||||
:type: str
|
||||
"""
|
||||
@property
|
||||
def version(self) -> str:
|
||||
"""
|
||||
:type: str
|
||||
"""
|
||||
__hash__ = None
|
||||
pass
|
||||
|
||||
class DownloadTargetList:
|
||||
def __init__(self) -> None: ...
|
||||
def add(self, arg0: SubdirData) -> None: ...
|
||||
|
@ -852,6 +985,49 @@ class PrefixData:
|
|||
"""
|
||||
pass
|
||||
|
||||
class ProblemsGraph:
|
||||
class ConflictMap:
|
||||
pass
|
||||
|
||||
class ConstraintNode(DependencyInfo):
|
||||
problem_type: libmambapy.bindings.SolverRuleinfo # value = <SolverRuleinfo.SOLVER_RULE_PKG_CONSTRAINS: 267>
|
||||
pass
|
||||
|
||||
class PackageNode(PackageInfo):
|
||||
pass
|
||||
|
||||
class RootNode:
|
||||
pass
|
||||
|
||||
class UnresolvedDependencyNode(DependencyInfo):
|
||||
@property
|
||||
def problem_type(self) -> SolverRuleinfo:
|
||||
"""
|
||||
:type: SolverRuleinfo
|
||||
"""
|
||||
@problem_type.setter
|
||||
def problem_type(self, arg0: SolverRuleinfo) -> None:
|
||||
pass
|
||||
pass
|
||||
def conflicts(self) -> ProblemsGraph.ConflictMap: ...
|
||||
@staticmethod
|
||||
def from_solver(arg0: Solver, arg1: Pool) -> ProblemsGraph: ...
|
||||
def graph(
|
||||
self,
|
||||
) -> typing.Tuple[
|
||||
typing.List[
|
||||
typing.Union[
|
||||
ProblemsGraph.RootNode,
|
||||
ProblemsGraph.PackageNode,
|
||||
ProblemsGraph.UnresolvedDependencyNode,
|
||||
ProblemsGraph.ConstraintNode,
|
||||
]
|
||||
],
|
||||
typing.Dict[typing.Tuple[int, int], DependencyInfo],
|
||||
]: ...
|
||||
def root_node(self) -> int: ...
|
||||
pass
|
||||
|
||||
class Query:
|
||||
def __init__(self, arg0: Pool) -> None: ...
|
||||
def depends(self, arg0: str, arg1: QueryFormat) -> str: ...
|
||||
|
|
|
@ -4,9 +4,13 @@
|
|||
//
|
||||
// The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <pybind11/iostream.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/operators.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <fmt/format.h>
|
||||
|
@ -30,8 +34,8 @@
|
|||
#include "mamba/core/virtual_packages.hpp"
|
||||
#include "mamba/core/output.hpp"
|
||||
#include "mamba/core/execution.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include "mamba/core/util_graph.hpp"
|
||||
#include "mamba/core/satisfiability_error.hpp"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
|
@ -46,6 +50,18 @@ namespace query
|
|||
};
|
||||
}
|
||||
|
||||
namespace PYBIND11_NAMESPACE
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename Key, typename Compare, typename Allocator>
|
||||
struct type_caster<mamba::vector_set<Key, Compare, Allocator>>
|
||||
: set_caster<mamba::vector_set<Key, Compare, Allocator>, Key>
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
deprecated(char const* message)
|
||||
{
|
||||
|
@ -54,6 +70,34 @@ deprecated(char const* message)
|
|||
warnings.attr("warn")(message, builtins.attr("DeprecationWarning"), py::arg("stacklevel") = 2);
|
||||
}
|
||||
|
||||
template <typename PyClass>
|
||||
auto
|
||||
bind_NamedList(PyClass pyclass)
|
||||
{
|
||||
using type = typename PyClass::type;
|
||||
pyclass.def(py::init())
|
||||
.def("__len__", [](type const& self) { return self.size(); })
|
||||
.def("__bool__", [](type const& self) { return !self.empty(); })
|
||||
.def(
|
||||
"__iter__",
|
||||
[](type const& self) { return py::make_iterator(self.begin(), self.end()); },
|
||||
py::keep_alive<0, 1>())
|
||||
.def("clear", [](type& self) { return self.clear(); })
|
||||
.def("add", [](type& self, typename type::value_type const& v) { self.insert(v); })
|
||||
.def("name", &type::name)
|
||||
.def("versions_trunc",
|
||||
&type::versions_trunc,
|
||||
py::arg("sep") = "|",
|
||||
py::arg("etc") = "...",
|
||||
py::arg("remove_duplicates") = true)
|
||||
.def("build_strings_trunc",
|
||||
&type::build_strings_trunc,
|
||||
py::arg("sep") = "|",
|
||||
py::arg("etc") = "...",
|
||||
py::arg("remove_duplicates") = true);
|
||||
return pyclass;
|
||||
}
|
||||
|
||||
PYBIND11_MODULE(bindings, m)
|
||||
{
|
||||
using namespace mamba;
|
||||
|
@ -188,6 +232,78 @@ PYBIND11_MODULE(bindings, m)
|
|||
.def_readwrite("description", &MSolverProblem::description)
|
||||
.def("__str__", [](MSolverProblem const& self) { return self.description; });
|
||||
|
||||
py::class_<DependencyInfo>(m, "DependencyInfo")
|
||||
.def(py::init<std::string const&>())
|
||||
.def_property_readonly("name", &DependencyInfo::name)
|
||||
.def_property_readonly("version", &DependencyInfo::version)
|
||||
.def_property_readonly("build_string", &DependencyInfo::build_string)
|
||||
.def("__str__", &DependencyInfo::str)
|
||||
.def(py::self == py::self);
|
||||
|
||||
using PbGraph = ProblemsGraph;
|
||||
auto pyPbGraph = py::class_<PbGraph>(m, "ProblemsGraph");
|
||||
|
||||
py::class_<PbGraph::RootNode>(pyPbGraph, "RootNode").def(py::init<>());
|
||||
py::class_<PbGraph::PackageNode, PackageInfo>(pyPbGraph, "PackageNode");
|
||||
py::class_<PbGraph::UnresolvedDependencyNode, DependencyInfo>(pyPbGraph,
|
||||
"UnresolvedDependencyNode")
|
||||
.def_readwrite("problem_type", &PbGraph::UnresolvedDependencyNode::problem_type);
|
||||
py::class_<PbGraph::ConstraintNode, DependencyInfo>(pyPbGraph, "ConstraintNode")
|
||||
.def_readonly_static("problem_type", &PbGraph::ConstraintNode::problem_type);
|
||||
|
||||
py::class_<PbGraph::conflicts_t>(pyPbGraph, "ConflictMap")
|
||||
.def(py::init([]() { return PbGraph::conflicts_t(); }))
|
||||
.def("__len__", [](PbGraph::conflicts_t const& self) { return self.size(); })
|
||||
.def("__bool__", [](PbGraph::conflicts_t const& self) { return !self.empty(); })
|
||||
.def(
|
||||
"__iter__",
|
||||
[](PbGraph::conflicts_t const& self)
|
||||
{ return py::make_iterator(self.begin(), self.end()); },
|
||||
py::keep_alive<0, 1>())
|
||||
.def("has_conflict", &PbGraph::conflicts_t::has_conflict)
|
||||
.def("__contains__", &PbGraph::conflicts_t::has_conflict)
|
||||
.def("conflicts", &PbGraph::conflicts_t::conflicts)
|
||||
.def("in_conflict", &PbGraph::conflicts_t::in_conflict)
|
||||
.def("clear", [](PbGraph::conflicts_t& self) { return self.clear(); })
|
||||
.def("add", &PbGraph::conflicts_t::add);
|
||||
|
||||
pyPbGraph.def_static("from_solver", &PbGraph::from_solver)
|
||||
.def("root_node", &PbGraph::root_node)
|
||||
.def("conflicts", &PbGraph::conflicts)
|
||||
.def("graph",
|
||||
[](PbGraph const& self)
|
||||
{
|
||||
auto const& g = self.graph();
|
||||
return std::pair(g.nodes(), g.edges());
|
||||
});
|
||||
|
||||
using CpPbGraph = CompressedProblemsGraph;
|
||||
auto pyCpPbGraph = py::class_<CpPbGraph>(m, "CompressedProblemsGraph");
|
||||
|
||||
pyCpPbGraph.def_property_readonly_static(
|
||||
"RootNode", [](py::handle) { return py::type::of<PbGraph::RootNode>(); });
|
||||
bind_NamedList(py::class_<CpPbGraph::PackageListNode>(pyCpPbGraph, "PackageListNode"));
|
||||
bind_NamedList(py::class_<CpPbGraph::UnresolvedDependencyListNode>(
|
||||
pyCpPbGraph, "UnresolvedDependencyListNode"));
|
||||
bind_NamedList(py::class_<CpPbGraph::ConstraintListNode>(pyCpPbGraph, "ConstraintListNode"));
|
||||
bind_NamedList(py::class_<CpPbGraph::edge_t>(pyCpPbGraph, "DependencyListList"));
|
||||
pyCpPbGraph.def_property_readonly_static(
|
||||
"ConflictMap", [](py::handle) { return py::type::of<PbGraph::conflicts_t>(); });
|
||||
|
||||
pyCpPbGraph.def_static("from_problems_graph", &CpPbGraph::from_problems_graph)
|
||||
.def_static("from_problems_graph",
|
||||
[](PbGraph const& pbs) { return CpPbGraph::from_problems_graph(pbs); })
|
||||
.def("root_node", &CpPbGraph::root_node)
|
||||
.def("conflicts", &CpPbGraph::conflicts)
|
||||
.def("graph",
|
||||
[](CpPbGraph const& self)
|
||||
{
|
||||
auto const& g = self.graph();
|
||||
return std::pair(g.nodes(), g.edges());
|
||||
})
|
||||
.def("summary_message", [](CpPbGraph const& self) { return problem_summary_msg(self); })
|
||||
.def("tree_message", [](CpPbGraph const& self) { return problem_tree_msg(self); });
|
||||
|
||||
py::class_<History>(m, "History")
|
||||
.def(py::init<const fs::u8path&>())
|
||||
.def("get_requested_specs_map", &History::get_requested_specs_map);
|
||||
|
|
Loading…
Reference in New Issue