24#include "pybind11/pybind11.h"
25#include "pybind11/stl.h"
40using namespace py::literals;
44namespace typehandling {
51class Publicist :
public MutableGenericMap<K> {
55 using GenericMap<K>::unsafeLookup;
56 using MutableGenericMap<K>::unsafeErase;
76 return py::cast(copy);
83 Storable
const& storable =
value.get();
84 return py::cast(storable.cloneStorable());
87 py::object apply(GenericMap<K>& self, K
const& key)
const {
88 auto callable =
static_cast<typename Publicist<K>::ConstValueReference (GenericMap<K>::*)(K) const
>(
89 &Publicist<K>::unsafeLookup);
90 auto variant = (self.*callable)(key);
91 return std::visit(*
this, variant);
97void declareGenericMap(cpputils::python::WrapperCollection& wrappers,
std::string const& suffix,
99 using Class = GenericMap<K>;
100 using PyClass = py::class_<Class, std::shared_ptr<Class>>;
105 "An abstract `~collections.abc.Mapping` for use when sharing a map between C++ and Python.\n" +
107 wrappers.wrapType(
PyClass(wrappers.module, className.
c_str(), docstring.
c_str()), [](
auto& mod,
115 cls.def(
"__contains__", static_cast<bool (Class::*)(K const&) const>(&Class::contains),
"key"_a);
117 cls.def(
"__getitem__",
118 [](Class& self, K const& key) {
120 return Getter<K>().apply(self, key);
121 } catch (pex::exceptions::OutOfRangeError const& e) {
123 std::stringstream buffer;
124 buffer <<
"Unknown key: " << key;
125 std::throw_with_nested(py::key_error(buffer.str()));
130 [](Class& self, K
const& key, py::object
const& def) {
132 return Getter<K>().apply(self, key);
133 }
catch (pex::exceptions::OutOfRangeError
const& e) {
139 "key"_a,
"default"_a = py::none(), py::return_value_policy::copy);
141 [](Class
const& self) {
return py::make_iterator(self.keys().begin(), self.keys().end()); },
142 py::keep_alive<0, 1>());
143 cls.def(
"__len__", &Class::size);
144 cls.def(
"__bool__", [](Class
const& self) {
return !self.empty(); });
151template <
typename V,
class PyClass>
152void declareMutableGenericMapTypedMethods(PyClass& cls) {
153 using Class =
typename PyClass::type;
154 cls.def(
"__setitem__",
155 [](Class& self,
typename Class::key_type
const& key, V
const& value) {
158 if (self.contains(key)) {
159 auto callable = &Publicist<typename Class::key_type>::unsafeErase;
160 (self.*callable)(key);
162 self.insert(key, value);
170void declareMutableGenericMap(cpputils::python::WrapperCollection& wrappers,
std::string const& suffix,
172 using Class = MutableGenericMap<K>;
173 using PyClass = py::class_<Class, std::shared_ptr<Class>, GenericMap<K>>;
175 std::string className =
"MutableGenericMap" + suffix;
178 "An abstract `~collections.abc.MutableMapping` for use when sharing a map between C++ and "
181 wrappers.wrapType(
PyClass(wrappers.module, className.
c_str(), docstring.
c_str()),
182 [](
auto& mod,
auto& cls) {
184 declareMutableGenericMapTypedMethods<std::shared_ptr<Storable const>>(cls);
185 declareMutableGenericMapTypedMethods<bool>(cls);
187 declareMutableGenericMapTypedMethods<std::int64_t>(cls);
188 declareMutableGenericMapTypedMethods<std::int32_t>(cls);
189 declareMutableGenericMapTypedMethods<double>(cls);
190 declareMutableGenericMapTypedMethods<float>(cls);
191 declareMutableGenericMapTypedMethods<std::string>(cls);
192 cls.def(
"__delitem__",
193 [](Class& self, K const& key) {
194 if (self.contains(key)) {
195 auto callable = &Publicist<K>::unsafeErase;
196 (self.*callable)(key);
198 std::stringstream buffer;
199 buffer <<
"Unknown key: " << key;
200 throw py::key_error(buffer.str());
204 cls.def(
"popitem", [](Class& self) {
206 K key = self.keys().back();
207 auto result = std::make_pair(key, Getter<K>().apply(self, key));
208 auto callable = &Publicist<K>::unsafeErase;
209 (self.*callable)(key);
212 throw py::key_error(
"Cannot pop from empty GenericMap.");
215 cls.def(
"clear", &Class::clear);
222 declareGenericMap<std::string>(wrappers,
"S",
"strings");
223 declareMutableGenericMap<std::string>(wrappers,
"S",
"strings");
std::variant< bool, int, long, long long, float, double, std::string, PolymorphicValue, std::shared_ptr< Storable const > > StorableType
The types that can be stored in a map.
decltype(_typeToConstRef(std::declval< StorableType >())) ConstValueReference
A type-agnostic reference to the value stored inside the map.
A helper class for subdividing pybind11 module across multiple translation units (i....
py::class_< PixelAreaBoundedField, std::shared_ptr< PixelAreaBoundedField >, BoundedField > PyClass
void wrapGenericMap(cpputils::python::WrapperCollection &wrappers)
std::string declareGenericMapRestrictions(std::string const &className, std::string const &keyName)