24 #include "pybind11/pybind11.h"
25 #include "pybind11/stl.h"
42 template <
typename... Ts>
43 struct type_caster<
boost::variant<Ts...>> : variant_caster<boost::variant<Ts...>> {};
45 struct visit_helper<
boost::variant> {
46 template <
typename... Args>
47 static auto call(Args&&...
args) -> decltype(boost::apply_visitor(
args...)) {
48 return boost::apply_visitor(
args...);
55 using namespace py::literals;
59 namespace typehandling {
66 class Publicist :
public MutableGenericMap<K> {
68 using typename GenericMap<K>::ConstValueReference;
69 using GenericMap<K>::unsafeLookup;
70 using MutableGenericMap<K>::unsafeErase;
74 py::object get(GenericMap<K>&
self, K
const&
key) {
75 auto callable =
static_cast<typename Publicist<K>::ConstValueReference (GenericMap<K>::*)(K) const
>(
76 &Publicist<K>::unsafeLookup);
77 auto variant = (
self.*callable)(
key);
80 PolymorphicValue
const* storableHolder = boost::get<PolymorphicValue const&>(&variant);
82 Storable
const& value = *storableHolder;
85 return py::cast(value.cloneStorable());
87 return py::cast(variant);
92 void declareGenericMap(utils::python::WrapperCollection& wrappers,
std::string const& suffix,
94 using Class = GenericMap<K>;
95 using PyClass = py::class_<Class, std::shared_ptr<Class>>;
100 "An abstract `~collections.abc.Mapping` for use when sharing a map between C++ and Python.\n" +
102 wrappers.wrapType(
PyClass(wrappers.module, className.
c_str(), docstring.
c_str()), [](
auto& mod,
110 cls.def(
"__contains__", static_cast<bool (Class::*)(K const&) const>(&Class::contains),
"key"_a);
112 cls.def(
"__getitem__",
113 [](Class& self, K const& key) {
115 return get(self, key);
116 } catch (pex::exceptions::OutOfRangeError const& e) {
118 std::stringstream buffer;
119 buffer <<
"Unknown key: " << key;
120 std::throw_with_nested(py::key_error(buffer.str()));
125 [](Class&
self, K
const&
key, py::object
const& def) {
127 return get(
self,
key);
128 }
catch (pex::exceptions::OutOfRangeError
const& e) {
134 "key"_a,
"default"_a = py::none(), py::return_value_policy::copy);
136 [](Class
const&
self) {
return py::make_iterator(
self.
keys().
begin(),
self.
keys().
end()); },
137 py::keep_alive<0, 1>());
138 cls.def(
"__len__", &Class::size);
139 cls.def(
"__bool__", [](Class
const&
self) {
return !
self.empty(); });
146 template <
typename V,
class PyClass>
147 void declareMutableGenericMapTypedMethods(
PyClass&
cls) {
149 cls.def(
"__setitem__",
150 [](Class&
self,
typename Class::key_type
const&
key, V
const& value) {
154 auto callable = &Publicist<typename Class::key_type>::unsafeErase;
155 (
self.*callable)(
key);
157 self.insert(
key, value);
164 template <
typename K>
165 void declareMutableGenericMap(utils::python::WrapperCollection& wrappers,
std::string const& suffix,
167 using Class = MutableGenericMap<K>;
168 using PyClass = py::class_<Class, std::shared_ptr<Class>, GenericMap<K>>;
170 std::string className =
"MutableGenericMap" + suffix;
173 "An abstract `~collections.abc.MutableMapping` for use when sharing a map between C++ and "
176 wrappers.wrapType(
PyClass(wrappers.module, className.
c_str(), docstring.
c_str()),
177 [](
auto& mod,
auto&
cls) {
179 declareMutableGenericMapTypedMethods<std::shared_ptr<Storable const>>(cls);
180 declareMutableGenericMapTypedMethods<bool>(cls);
182 declareMutableGenericMapTypedMethods<std::int64_t>(cls);
183 declareMutableGenericMapTypedMethods<std::int32_t>(cls);
184 declareMutableGenericMapTypedMethods<double>(cls);
185 declareMutableGenericMapTypedMethods<float>(cls);
186 declareMutableGenericMapTypedMethods<std::string>(cls);
187 cls.def(
"__delitem__",
188 [](Class& self, K const& key) {
189 if (self.contains(key)) {
190 auto callable = &Publicist<K>::unsafeErase;
191 (self.*callable)(key);
193 std::stringstream buffer;
194 buffer <<
"Unknown key: " << key;
195 throw py::key_error(buffer.str());
199 cls.def(
"popitem", [](Class&
self) {
201 K
key =
self.keys().back();
203 auto callable = &Publicist<K>::unsafeErase;
204 (
self.*callable)(
key);
207 throw py::key_error(
"Cannot pop from empty GenericMap.");
210 cls.def(
"clear", &Class::clear);
217 declareGenericMap<std::string>(wrappers,
"S",
"strings");
218 declareMutableGenericMap<std::string>(wrappers,
"S",
"strings");