Skip to content

Commit

Permalink
Merge pull request #19 from Jannik2099/str
Browse files Browse the repository at this point in the history
fix enum __str__, add Usedeps string()
  • Loading branch information
Jannik2099 authored Mar 21, 2024
2 parents 1788f11 + ed50a58 commit bf13a67
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 18 deletions.
6 changes: 5 additions & 1 deletion include/pms-utils/atom/atom.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ struct Usedep {

[[nodiscard]] explicit operator std::string() const;
};
struct Usedeps : public std::vector<Usedep> {};
struct Usedeps : public std::vector<Usedep> {
[[nodiscard]] explicit operator std::string() const;
};

struct PackageExpr {
boost::optional<Blocker> blocker;
Expand Down Expand Up @@ -236,6 +238,8 @@ std::ostream &operator<<(std::ostream &out, UsedepCond usedepCond);

std::ostream &operator<<(std::ostream &out, const Usedep &usedep);

std::ostream &operator<<(std::ostream &out, const Usedeps &usedeps);

std::ostream &operator<<(std::ostream &out, const PackageExpr &package);

// END IO
Expand Down
26 changes: 17 additions & 9 deletions lib/atom/atom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,22 @@ Usedep::operator std::string() const {
}
std::ostream &operator<<(std::ostream &out, const Usedep &usedep) { return out << std::string(usedep); }

Usedeps::operator std::string() const {
std::string ret;
if (empty()) {
return ret;
}
ret += "[";
for (const Usedep &usedep : *this) {
ret += std::string(usedep);
ret += ",";
}
ret.pop_back();
ret += "]";
return ret;
}
std::ostream &operator<<(std::ostream &out, const Usedeps &usedeps) { return out << std::string(usedeps); }

PackageExpr::operator std::string() const {
std::string ret;
if (blocker.has_value()) {
Expand All @@ -221,15 +237,7 @@ PackageExpr::operator std::string() const {
if (slotExpr.has_value()) {
ret += std::string(slotExpr.value());
}
if (!usedeps.empty()) {
ret += "[";
for (const Usedep &usedep : usedeps) {
ret += std::string(usedep);
ret += ",";
}
ret = ret.substr(0, ret.length() - 1);
ret += "]";
}
ret += std::string(usedeps);
return ret;
}

Expand Down
26 changes: 21 additions & 5 deletions subprojects/bindings-python/lib/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <boost/mp11/list.hpp>
#include <boost/optional.hpp>
#include <boost/variant.hpp>
#include <pybind11/attr.h>
#include <pybind11/pybind11.h>
#include <pybind11/pytypes.h>
#include <pybind11/stl.h>
Expand Down Expand Up @@ -40,19 +41,34 @@ template <> struct visit_helper<boost::variant> {

namespace pms_utils::bindings::python {

template <typename Func>
static inline py::object &add_method(py::object &cls, std::string_view name, Func &&func) {
// pybind11 needs a c_str ;/
const std::string name_str(name);
py::cpp_function cfunc(std::forward<Func>(func), py::name(name_str.c_str()), py::is_method(cls),
py::sibling(py::getattr(cls, name_str.c_str(), py::none())));
py::detail::add_class_method(cls, name_str.c_str(), cfunc);
return cls;
}

template <typename T, typename M, typename R = bool>
requires(std::is_enum_v<T> && boost::describe::has_describe_enumerators<T>::value)
static inline py::object create_bindings(M module_, R rule = false, std::string enum_type = "enum.Enum") {
static inline py::object create_bindings(M module_, R rule = false,
std::string_view enum_type = "enum.Enum") {
constexpr std::string_view name = bound_type_name<T>::str;

py::object ret = _internal::bind_enum<M, T>(module_, name, enum_type);

if constexpr (requires(T val) { to_string(val); }) {
add_method(ret, "__str__", [](T val) { return to_string(val); });
}
if constexpr (!std::is_same_v<R, bool>) {
const std::string function_name = std::string("_") + std::string(name) + "_init";
module_.def(function_name.data(), [rule](const py::object &, std::string_view arg) {
const std::string function_name = std::string("_") + std::string(name) + "__missing_";
module_.def(function_name.c_str(), [rule](const py::object &, std::string_view arg) {
return _internal::expr_from_str(rule(), arg);
});
ret.attr("_missing_") =
py::module::import("pydoc").attr("locate")("classmethod")(module_.attr(function_name.data()));
py::module::import("builtins").attr("classmethod")(module_.attr(function_name.c_str()));
}
return ret;
}
Expand Down Expand Up @@ -83,7 +99,7 @@ static inline auto create_bindings(M module_, R rule = false) {
auto ret = pyclass(module_, std::string(name).data());
mp_for_each<boost::describe::describe_members<T, boost::describe::mod_public>>(
[&ret](auto member) { ret.def_readonly(member.name, member.pointer); });
if constexpr (requires(const T &val) { std::string(val); }) {
if constexpr (std::constructible_from<std::string, T>) {
ret.def("__str__", [](const T &val) { return std::string(val); });
}
if constexpr (!std::is_same_v<R, bool>) {
Expand Down
7 changes: 4 additions & 3 deletions subprojects/bindings-python/lib/enum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ namespace py = pybind11;

namespace pms_utils::bindings::python::_internal {

// thanks to
// https://github.com/pybind/pybind11/issues/2332#issuecomment-741061287

// maps enum type to python enum
std::unordered_map<std::type_index, py::object> &enums();

std::size_t &enum_counter();

template <typename T> consteval auto bound_type_name_to_descr() {
constexpr std::array myarr = bound_type_name_v<T>;
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
Expand All @@ -47,7 +48,7 @@ auto bind_enum(M &mod, std::string_view name, std::string_view enum_type) {
py::object &spec = _internal::enums()[typeid(T)];
spec = py::module::import("pydoc").attr("locate")(enum_type)(name, pairs,
py::arg("module") = mod.attr("__name__"));
mod.attr(std::string(name).data()) = spec;
mod.attr(std::string(name).c_str()) = spec;
return spec;
}

Expand Down

0 comments on commit bf13a67

Please sign in to comment.