16#ifndef YASMIN__BLACKBOARD_PYWRAPPER_HPP_
17#define YASMIN__BLACKBOARD_PYWRAPPER_HPP_
19#include <pybind11/cast.h>
20#include <pybind11/pybind11.h>
21#include <pybind11/stl.h>
27#include <unordered_map>
33namespace py = pybind11;
82 using StringDict = std::unordered_map<std::string, std::string>;
84 using IntDict = std::unordered_map<std::string, std::int64_t>;
86 using FloatDict = std::unordered_map<std::string, double>;
88 using BoolDict = std::unordered_map<std::string, bool>;
100 if (PyBytes_Check(value.ptr()) != 0) {
101 if (PyBytes_AsStringAndSize(value.ptr(), &data, &
size) != 0) {
102 throw py::error_already_set();
104 }
else if (PyByteArray_Check(value.ptr()) != 0) {
105 data = PyByteArray_AsString(value.ptr());
106 size = PyByteArray_Size(value.ptr());
108 throw std::runtime_error(
"Expected bytes or bytearray object");
111 return std::vector<uint8_t>(
reinterpret_cast<uint8_t *
>(data),
112 reinterpret_cast<uint8_t *
>(data) +
size);
121 template <
typename ByteT>
123 return py::bytes(
reinterpret_cast<const char *
>(value.data()),
124 static_cast<py::ssize_t
>(value.size()));
133 return PyBytes_Check(value.ptr()) != 0 ||
134 PyByteArray_Check(value.ptr()) != 0;
146 return py::isinstance<py::int_>(value) && !py::isinstance<py::bool_>(value);
155 return py::isinstance<py::float_>(value);
173 return py::isinstance<py::list>(value) || py::isinstance<py::tuple>(value);
183 template <
typename Predicate>
185 for (
auto item : seq) {
199 template <
typename T>
201 std::vector<T> result;
202 result.reserve(
static_cast<std::size_t
>(py::len(seq)));
204 for (
auto item : seq) {
205 result.push_back(py::cast<T>(item));
217 for (
auto item : dict) {
218 if (!py::isinstance<py::str>(item.first)) {
232 template <
typename Predicate>
234 for (
auto item : dict) {
235 if (!pred(item.second)) {
248 template <
typename T>
249 static std::unordered_map<std::string, T>
251 std::unordered_map<std::string, T> result;
252 result.reserve(
static_cast<std::size_t
>(py::len(dict)));
254 for (
auto item : dict) {
255 result.emplace(py::cast<std::string>(item.first),
256 py::cast<T>(item.second));
303 void set(
const std::string &key, py::object value) {
304 if (py::isinstance<py::bool_>(value)) {
305 this->blackboard->set<
bool>(key, value.cast<
bool>());
310 this->blackboard->set<std::int64_t>(key, value.cast<std::int64_t>());
314 if (py::isinstance<py::float_>(value)) {
315 this->blackboard->set<
double>(key, value.cast<
double>());
320 this->blackboard->set<std::vector<uint8_t>>(key,
325 if (py::isinstance<py::str>(value)) {
326 this->blackboard->set<std::string>(key, value.cast<std::string>());
331 py::sequence seq = value.cast<py::sequence>();
335 if (py::len(seq) == 0) {
336 this->blackboard->set<py::object>(key, value);
342 return py::isinstance<py::bool_>(item);
366 return py::isinstance<py::str>(item);
373 this->blackboard->set<py::object>(key, value);
377 if (py::isinstance<py::dict>(value)) {
378 py::dict dict = value.cast<py::dict>();
383 this->blackboard->set<py::object>(key, value);
388 return py::isinstance<py::bool_>(item);
397 this->blackboard->set<
IntDict>(
412 return py::isinstance<py::str>(item);
419 this->blackboard->set<py::object>(key, value);
423 this->blackboard->set<py::object>(key, value);
434 py::object
get(
const std::string &key)
const {
435 const std::string type = this->blackboard->get_type(key);
439 this->blackboard->get<std::vector<uint8_t>>(key));
444 this->blackboard->get<std::vector<unsigned char>>(key));
449 this->blackboard->get<std::vector<char>>(key));
453 return py::cast(this->blackboard->get<
StringVector>(key));
457 return py::cast(this->blackboard->get<
IntVector>(key));
461 return py::cast(this->blackboard->get<std::vector<int>>(key));
465 return py::cast(this->blackboard->get<std::vector<long>>(key));
469 return py::cast(this->blackboard->get<std::vector<long long>>(key));
473 return py::cast(this->blackboard->get<
FloatVector>(key));
477 return py::cast(this->blackboard->get<std::vector<float>>(key));
481 return py::cast(this->blackboard->get<
BoolVector>(key));
485 return py::cast(this->blackboard->get<
StringDict>(key));
489 return py::cast(this->blackboard->get<
IntDict>(key));
494 this->blackboard->get<std::unordered_map<std::string, int>>(key));
499 this->blackboard->get<std::unordered_map<std::string, long>>(key));
504 this->blackboard->get<std::unordered_map<std::string, long long>>(
509 return py::cast(this->blackboard->get<
FloatDict>(key));
514 this->blackboard->get<std::unordered_map<std::string, float>>(key));
518 return py::cast(this->blackboard->get<
BoolDict>(key));
522 return py::cast(this->blackboard->get<std::string>(key));
526 return py::cast(this->blackboard->get<std::int64_t>(key));
530 return py::cast(this->blackboard->get<
int>(key));
534 return py::cast(this->blackboard->get<
long>(key));
538 return py::cast(this->blackboard->get<
float>(key));
542 return py::cast(this->blackboard->get<
double>(key));
546 return py::cast(this->blackboard->get<
bool>(key));
550 return this->blackboard->get<py::object>(key);
560 void remove(
const std::string &key) { this->blackboard->remove(key); }
568 return this->blackboard->contains(key);
575 int size()
const {
return this->blackboard->size(); }
581 std::vector<std::string>
keys()
const {
return this->blackboard->keys(); }
590 for (
const auto &key : this->blackboard->keys()) {
591 result.append(this->
get(key));
604 for (
const auto &key : this->blackboard->keys()) {
605 result.append(py::make_tuple(key, this->
get(key)));
615 std::string
to_string()
const {
return this->blackboard->to_string(); }
622 this->blackboard->set_remappings(remappings);
630 return this->blackboard->get_remappings();
static bool dict_values_match(const py::dict &dict, Predicate pred)
Check whether all values of a Python dict satisfy a predicate.
Definition blackboard_pywrapper.hpp:233
void set_remappings(const Remappings &remappings)
Set key remappings on the underlying blackboard.
Definition blackboard_pywrapper.hpp:621
Blackboard::SharedPtr blackboard
Shared pointer to the underlying native blackboard.
Definition blackboard_pywrapper.hpp:70
std::unordered_map< std::string, std::string > StringDict
Alias for a typed dictionary with string values.
Definition blackboard_pywrapper.hpp:82
py::list items() const
Get the key-value pairs visible in the current remapping scope.
Definition blackboard_pywrapper.hpp:601
static std::vector< uint8_t > py_buffer_to_vector(const py::handle &value)
Convert a Python bytes-like object into a byte vector.
Definition blackboard_pywrapper.hpp:96
static std::unordered_map< std::string, T > dict_to_unordered_map(const py::dict &dict)
Convert a Python dict with string keys into a typed unordered_map.
Definition blackboard_pywrapper.hpp:250
static bool dict_has_only_string_keys(const py::dict &dict)
Check whether all keys in a Python dict are strings.
Definition blackboard_pywrapper.hpp:216
BlackboardPyWrapper(Blackboard &&other)
Construct a wrapper by moving an existing native Blackboard.
Definition blackboard_pywrapper.hpp:285
static bool is_python_float_like(const py::handle &value)
Check whether a Python object is a floating point value.
Definition blackboard_pywrapper.hpp:154
std::unordered_map< std::string, double > FloatDict
Alias for a typed dictionary with floating point values.
Definition blackboard_pywrapper.hpp:86
std::vector< std::int64_t > IntVector
Alias for a typed vector of integers.
Definition blackboard_pywrapper.hpp:75
int size() const
Get the number of entries in the blackboard.
Definition blackboard_pywrapper.hpp:575
BlackboardPyWrapper()
Construct a wrapper with a newly created native Blackboard.
Definition blackboard_pywrapper.hpp:279
py::list values() const
Get the values visible in the current remapping scope.
Definition blackboard_pywrapper.hpp:587
std::unordered_map< std::string, bool > BoolDict
Alias for a typed dictionary with boolean values.
Definition blackboard_pywrapper.hpp:88
static bool is_python_bytes_like(const py::handle &value)
Check whether a Python object is bytes-like.
Definition blackboard_pywrapper.hpp:132
static bool is_python_number_like(const py::handle &value)
Check whether a Python object is a numeric value.
Definition blackboard_pywrapper.hpp:163
static bool is_python_sequence_like(const py::handle &value)
Check whether a Python object should be treated as a sequence.
Definition blackboard_pywrapper.hpp:172
static bool sequence_matches(const py::sequence &seq, Predicate pred)
Check whether all elements of a Python sequence satisfy a predicate.
Definition blackboard_pywrapper.hpp:184
std::vector< std::string > StringVector
Alias for a typed vector of strings.
Definition blackboard_pywrapper.hpp:73
static std::vector< T > sequence_to_vector(const py::sequence &seq)
Convert a Python sequence into a typed C++ vector.
Definition blackboard_pywrapper.hpp:200
py::object get(const std::string &key) const
Retrieve a Python object from the blackboard.
Definition blackboard_pywrapper.hpp:434
std::vector< double > FloatVector
Alias for a typed vector of floating point values.
Definition blackboard_pywrapper.hpp:77
static bool is_exact_cpp_type(const std::string &type)
Compare a stored type string against an exact C++ type.
Definition blackboard_pywrapper.hpp:271
std::vector< bool > BoolVector
Alias for a typed vector of booleans.
Definition blackboard_pywrapper.hpp:79
const Remappings & get_remappings() const
Get the current key remappings.
Definition blackboard_pywrapper.hpp:629
std::unordered_map< std::string, std::int64_t > IntDict
Alias for a typed dictionary with integer values.
Definition blackboard_pywrapper.hpp:84
static bool is_python_int_like(const py::handle &value)
Check whether a Python object is an integer but not a boolean.
Definition blackboard_pywrapper.hpp:145
void set(const std::string &key, py::object value)
Store a Python object in the blackboard.
Definition blackboard_pywrapper.hpp:303
std::string to_string() const
Get a string representation of the blackboard contents.
Definition blackboard_pywrapper.hpp:615
Blackboard::SharedPtr get_cpp_blackboard() const
Access the underlying native blackboard.
Definition blackboard_pywrapper.hpp:637
BlackboardPyWrapper(Blackboard::SharedPtr bb_ptr)
Construct a wrapper from an existing shared native Blackboard.
Definition blackboard_pywrapper.hpp:292
static py::bytes byte_vector_to_py_bytes(const std::vector< ByteT > &value)
Convert a C++ byte-like vector into Python bytes.
Definition blackboard_pywrapper.hpp:122
void remove(const std::string &key)
Remove a value from the blackboard.
Definition blackboard_pywrapper.hpp:560
bool contains(const std::string &key) const
Check whether a key exists in the blackboard.
Definition blackboard_pywrapper.hpp:567
std::vector< std::string > keys() const
Get the keys visible in the current remapping scope.
Definition blackboard_pywrapper.hpp:581
A thread-safe storage for key-value pairs of varying types.
Definition blackboard.hpp:67
std::shared_ptr< Blackboard > SharedPtr
Shared pointer type for Blackboard.
Definition blackboard.hpp:100
Definition blackboard.hpp:34
std::string demangle_type(const std::string &mangled_name)
Demangle a C++ type name to a human-readable format.
Definition blackboard.hpp:41
StringMap Remappings
Map of remappings (string to string).
Definition types.hpp:88