45#if defined(__GNUC__) && !defined(__clang__)
46#pragma GCC diagnostic push
47#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
67 bool checkPythonObject(
const boost::python::object& pyObject,
const std::string&);
68 template<
typename Key,
typename Value>
69 bool checkPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&);
71 template<
typename Value>
72 bool checkPythonObject(
const boost::python::object& pyObject,
const std::vector<Value>&);
74 template<
typename Value>
75 bool checkPythonObject(
const boost::python::object& pyObject,
const std::set<Value>&);
77 template<
typename... Types>
78 bool checkPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&);
80 template<
typename... Types>
81 bool checkPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&);
83 template<
typename Type>
84 bool checkPythonObject(
const boost::python::object& pyObject,
const std::optional<Type>&);
87 template<
typename Scalar>
91 std::shared_ptr<T>
convertPythonObject(
const boost::python::object& pyObject,
const std::shared_ptr<T>&);
93 template<
typename Key,
typename Value>
94 std::map<Key, Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&);
96 template<
typename Value>
97 std::vector<Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::vector<Value>&);
99 template<
typename Value>
100 std::set<Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::set<Value>&);
102 template<
typename... Types>
103 std::tuple<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&);
105 template<
typename... Types>
106 boost::variant<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&);
108 template<
typename Type>
109 std::optional<Type>
convertPythonObject(
const boost::python::object& pyObject,
const std::optional<Type>&);
111 template<
typename Scalar>
113 template<
typename Value>
116 template<
typename Value>
118 template<
typename Key,
typename Value>
120 template<
typename... Types>
122 template<
typename... Types>
125 template<
typename Type>
128 template<
typename T>
struct Type;
130 template<typename T> struct
Type<std::set<T>>;
131 template<typename A, typename B> struct
Type<std::map<A, B> >;
132 template<typename... Types> struct
Type<std::tuple<Types...> >;
133 template<typename... Types> struct
Type<boost::variant<Types...> >;
134 template<> struct
Type<int>;
135 template<> struct
Type<bool>;
136 template<> struct
Type<float>;
137 template<> struct
Type<double>;
138 template<> struct
Type<std::string>;
140 template< typename T, typename... Types> struct
VariadicType;
156 template<
typename T>
struct Type {
static std::string
name() {
return "???";} };
160 template<
typename T>
struct Type<
std::set<T>> {
static std::string
name() {
return std::string(
"set(") +
Type<T>::name() +
")"; }};
165 template<>
struct Type<unsigned int> {
static std::string
name() {
return "unsigned int"; } };
167 template<>
struct Type<unsigned long int> {
static std::string
name() {
return "unsigned long int"; } };
169 template<>
struct Type<int> {
static std::string
name() {
return "int"; } };
171 template<>
struct Type<bool> {
static std::string
name() {
return "bool"; } };
173 template<>
struct Type<float> {
static std::string
name() {
return "float"; } };
175 template<>
struct Type<double> {
static std::string
name() {
return "float"; } };
189 template<>
struct Type<
std::shared_ptr<Path>> {
191 static std::string
name() {
return std::string(
"Path"); }
196 template <
size_t >
struct SizeT { };
205 return PyBool_Check(pyObject.ptr());
211 return PyLong_CheckExact(pyObject.ptr());
216 return PyLong_CheckExact(pyObject.ptr());
222 return PyLong_CheckExact(pyObject.ptr());
228 return PyFloat_CheckExact(pyObject.ptr());
234 return PyFloat_CheckExact(pyObject.ptr());
240 return PyUnicode_Check(pyObject.ptr());
244 template<
typename Key,
typename Value>
247 if (not PyDict_Check(pyObject.ptr()))
return false;
248 const boost::python::dict& pyDict =
static_cast<const boost::python::dict&
>(pyObject);
249 boost::python::list keys = pyDict.keys();
250 boost::python::list values = pyDict.values();
251 for (
int i = 0; i < boost::python::len(keys); ++i) {
265 template<
class Functor>
268 boost::python::object iterator(boost::python::handle<>(PyObject_GetIter(pyObject.ptr())));
269 PyObject* item{
nullptr};
271 while ((item = PyIter_Next(iterator.ptr()))) {
272 boost::python::object obj{boost::python::handle<>(item)};
273 if (not function(obj))
return false;
279 template<
typename Value>
282 if (not PyList_Check(pyObject.ptr()))
return false;
288 template<
typename Value>
291 if (not PyAnySet_Check(pyObject.ptr()))
return false;
298 template<
typename... Types, std::size_t ... Is>
299 bool CheckTuple(
const std::tuple<Types...>& tuple,
const boost::python::tuple& pyTuple,
300 std::index_sequence<Is...>)
306 template<
typename... Types>
307 bool checkPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>& tuple)
309 if (not PyTuple_Check(pyObject.ptr()))
return false;
310 const boost::python::tuple& pyTuple =
static_cast<const boost::python::tuple&
>(pyObject);
311 return CheckTuple(tuple, pyTuple, std::index_sequence_for<Types ...>());
315 template<
typename VariantType>
317 const boost::python::object&,
324 template<
typename... Types,
size_t N>
326 const boost::python::object& pyObject,
329 using Scalar =
typename std::tuple_element < N - 1, std::tuple<Types...> >::type;
333 return CheckVariant(variant, pyObject, SizeT < N - 1 > ());
337 template<
typename... Types>
338 bool checkPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...> variant)
346 template<
typename Type>
362 template<
typename Scalar>
365 return boost::python::object(value);
374 template<
typename Value>
377 boost::python::list outputList;
378 for (
const auto& value :
vector) {
388 template<
typename Value>
391 boost::python::object result(boost::python::handle<>(PySet_New(
nullptr)));
392 for (
const auto& value : set) {
404 template<
typename Key,
typename Value>
407 boost::python::dict outputDict;
408 for (
auto pair : map) {
422 template <
typename TupleType >
423 inline void GetTuple(
const TupleType& tuple, boost::python::list& pyList)
425 GetTuple(tuple, pyList,
SizeT<std::tuple_size<TupleType>::value>());
429 template <
typename TupleType >
434 template <
typename TupleType,
size_t N >
437 GetTuple(tuple, pyList, SizeT < N - 1 > ());
448 template<
typename... Types>
451 boost::python::list outputList;
453 boost::python::tuple outputTuple(outputList);
476 template<
typename... Types>
489 template<
typename Type>
495 return boost::python::object();
510 template<
typename Scalar>
515 boost::python::extract<Scalar> valueProxy(pyObject);
516 if (valueProxy.check()) {
517 tmpValue =
static_cast<Scalar
>(valueProxy);
519 throw std::runtime_error(std::string(
"Could not convert value: Expected type '") +
Type<Scalar>::name() +
"' instead of '" +
520 pyObject.ptr()->ob_type->tp_name +
"'.");
533 template <
typename T>
534 __attribute__((noinline))
538 std::shared_ptr<T> tmpValue;
539 boost::python::extract<std::shared_ptr<T>> valueProxy(pyObject);
540 if (valueProxy.check()) {
541 tmpValue = valueProxy();
543 throw std::runtime_error(
544 std::string(
"Could not convert value: Expected type '") +
Type<std::shared_ptr<T>>::name() +
"' instead of '" +
545 pyObject.ptr()->ob_type->tp_name +
"'."
559 template<
typename Value>
563 std::vector<Value> tmpVector;
564 if (PyList_Check(pyObject.ptr()) or PyGen_Check(pyObject.ptr())) {
576 template<
typename Value>
579 std::set<Value> result;
580 if (PyAnySet_Check(pyObject.ptr())) {
598 template<
typename Key,
typename Value>
599 std::map<Key, Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&)
601 std::map<Key, Value> tmpMap;
602 const boost::python::dict& pyDict =
static_cast<const boost::python::dict&
>(pyObject);
603 boost::python::list keys = pyDict.keys();
605 for (
int i = 0; i < boost::python::len(keys); ++i) {
608 tmpMap.insert(std::pair<Key, Value>(key, value));
622 template <
typename TupleType >
623 inline void SetTuple(TupleType& tuple,
const boost::python::tuple& pyTuple)
625 static const unsigned N = std::tuple_size<TupleType>::value;
626 if ((
unsigned)boost::python::len(pyTuple) != N) {
627 throw std::runtime_error(std::string(
"Given python tuple has length ") +
628 std::to_string(boost::python::len(pyTuple)) +
629 ", expected " + std::to_string(N));
635 template <
typename TupleType >
640 template <
typename TupleType,
size_t N >
643 SetTuple(tuple, pyTuple, SizeT < N - 1 > ());
644 std::get < N - 1 > (tuple) =
convertPythonObject(pyTuple[N - 1], std::get < N - 1 > (tuple));
654 template<
typename... Types>
655 std::tuple<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&)
657 std::tuple<Types...> tmpTuple;
658 const boost::python::tuple& pyTuple =
static_cast<const boost::python::tuple&
>(pyObject);
671 template <
typename... Types>
674 throw std::runtime_error(std::string(
"Could not set module parameter: Expected type '") +
675 Type<boost::variant<Types...> >::name() +
"' instead of '" +
676 pyObject.ptr()->ob_type->tp_name +
"'.");
680 template <
typename... Types,
size_t N >
681 inline void SetVariant(boost::variant<Types...>& variant,
const boost::python::object& pyObject,
SizeT<N>)
683 using Scalar =
typename std::tuple_element < N - 1, std::tuple<Types...> >::type;
689 }
catch (
const std::runtime_error& e) {
693 SetVariant(variant, pyObject, SizeT < N - 1 > ());
703 template<
typename... Types>
704 boost::variant<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&)
706 boost::variant<Types...> tmpVariant;
717 template<
typename Type>
718 std::optional<Type>
convertPythonObject(
const boost::python::object& pyObject,
const std::optional<Type>&)
720 std::optional<Type> tmpOptional = std::nullopt;
721 if (!pyObject.is_none()) {
726#if defined(__GNUC__) && !defined(__clang__)
727#pragma GCC diagnostic pop