11#include <boost/python/object.hpp>
12#include <boost/python/list.hpp>
13#include <boost/python/tuple.hpp>
14#include <boost/python/dict.hpp>
15#include <boost/python/extract.hpp>
16#include <boost/variant.hpp>
40 namespace PyObjConvUtils {
59 bool checkPythonObject(
const boost::python::object& pyObject,
const std::string&);
60 template<
typename Key,
typename Value>
61 bool checkPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&);
63 template<
typename Value>
64 bool checkPythonObject(
const boost::python::object& pyObject,
const std::vector<Value>&);
66 template<
typename Value>
67 bool checkPythonObject(
const boost::python::object& pyObject,
const std::set<Value>&);
69 template<
typename... Types>
70 bool checkPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&);
72 template<
typename... Types>
73 bool checkPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&);
75 template<
typename Type>
76 bool checkPythonObject(
const boost::python::object& pyObject,
const std::optional<Type>&);
79 template<
typename Scalar>
82 template<
typename Key,
typename Value>
83 std::map<Key, Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&);
85 template<
typename Value>
86 std::vector<Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::vector<Value>&);
88 template<
typename Value>
89 std::set<Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::set<Value>&);
91 template<
typename... Types>
92 std::tuple<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&);
94 template<
typename... Types>
95 boost::variant<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&);
97 template<
typename Type>
98 std::optional<Type>
convertPythonObject(
const boost::python::object& pyObject,
const std::optional<Type>&);
100 template<
typename Scalar>
102 template<
typename Value>
105 template<
typename Value>
107 template<
typename Key,
typename Value>
109 template<
typename... Types>
111 template<
typename... Types>
114 template<
typename Type>
117 template<
typename T>
struct Type;
118 template<
typename T>
struct Type<
std::vector<T> >;
119 template<typename T> struct
Type<std::set<T>>;
120 template<typename A, typename B> struct
Type<std::map<A, B> >;
121 template<typename... Types> struct
Type<std::tuple<Types...> >;
122 template<typename... Types> struct
Type<boost::variant<Types...> >;
123 template<> struct
Type<int>;
124 template<> struct
Type<bool>;
125 template<> struct
Type<float>;
126 template<> struct
Type<double>;
127 template<> struct
Type<std::string>;
129 template< typename T, typename... Types> struct
VariadicType;
145 template<
typename T>
struct Type {
static std::string
name() {
return "???";} };
147 template<
typename T>
struct Type<
std::vector<T> > {
static std::string
name() {
return std::string(
"list(") +
Type<T>::name() +
")"; } };
149 template<
typename T>
struct Type<
std::set<T>> {
static std::string
name() {
return std::string(
"set(") +
Type<T>::name() +
")"; }};
154 template<>
struct Type<unsigned int> {
static std::string
name() {
return "unsigned int"; } };
156 template<>
struct Type<unsigned long int> {
static std::string
name() {
return "unsigned long int"; } };
158 template<>
struct Type<int> {
static std::string
name() {
return "int"; } };
160 template<>
struct Type<bool> {
static std::string
name() {
return "bool"; } };
162 template<>
struct Type<float> {
static std::string
name() {
return "float"; } };
164 template<>
struct Type<double> {
static std::string
name() {
return "float"; } };
166 template<>
struct Type<
std::string> {
static std::string
name() {
return "str"; } };
178 template<>
struct Type<
std::shared_ptr<Path>> {
180 static std::string
name() {
return std::string(
"Path"); }
185 template <
size_t >
struct SizeT { };
194 return PyBool_Check(pyObject.ptr());
200 return PyLong_CheckExact(pyObject.ptr());
205 return PyLong_CheckExact(pyObject.ptr());
211 return PyLong_CheckExact(pyObject.ptr());
217 return PyFloat_CheckExact(pyObject.ptr());
223 return PyFloat_CheckExact(pyObject.ptr());
229 return PyUnicode_Check(pyObject.ptr());
233 template<
typename Key,
typename Value>
236 if (not PyDict_Check(pyObject.ptr()))
return false;
237 const boost::python::dict& pyDict =
static_cast<const boost::python::dict&
>(pyObject);
238 boost::python::list keys = pyDict.keys();
239 boost::python::list values = pyDict.values();
240 for (
int i = 0; i < boost::python::len(keys); ++i) {
254 template<
class Functor>
257 boost::python::object iterator(boost::python::handle<>(PyObject_GetIter(pyObject.ptr())));
258 PyObject* item{
nullptr};
260 while ((item = PyIter_Next(iterator.ptr()))) {
261 boost::python::object obj{boost::python::handle<>(item)};
262 if (not function(obj))
return false;
268 template<
typename Value>
271 if (not PyList_Check(pyObject.ptr()))
return false;
277 template<
typename Value>
280 if (not PyAnySet_Check(pyObject.ptr()))
return false;
287 template<
typename... Types, std::size_t ... Is>
288 bool CheckTuple(
const std::tuple<Types...>& tuple,
const boost::python::tuple& pyTuple,
289 std::index_sequence<Is...>)
295 template<
typename... Types>
296 bool checkPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>& tuple)
298 if (not PyTuple_Check(pyObject.ptr()))
return false;
299 const boost::python::tuple& pyTuple =
static_cast<const boost::python::tuple&
>(pyObject);
300 return CheckTuple(tuple, pyTuple, std::index_sequence_for<Types ...>());
304 template<
typename VariantType>
306 const boost::python::object&,
313 template<
typename... Types,
size_t N>
315 const boost::python::object& pyObject,
318 using Scalar =
typename std::tuple_element < N - 1, std::tuple<Types...> >::type;
322 return CheckVariant(variant, pyObject, SizeT < N - 1 > ());
326 template<
typename... Types>
327 bool checkPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...> variant)
335 template<
typename Type>
351 template<
typename Scalar>
354 return boost::python::object(value);
363 template<
typename Value>
366 boost::python::list outputList;
367 for (
const auto& value : vector) {
377 template<
typename Value>
380 boost::python::object result(boost::python::handle<>(PySet_New(
nullptr)));
381 for (
const auto& value : set) {
393 template<
typename Key,
typename Value>
396 boost::python::dict outputDict;
397 for (
auto pair : map) {
411 template <
typename TupleType >
412 inline void GetTuple(
const TupleType& tuple, boost::python::list& pyList)
414 GetTuple(tuple, pyList,
SizeT<std::tuple_size<TupleType>::value>());
418 template <
typename TupleType >
423 template <
typename TupleType,
size_t N >
426 GetTuple(tuple, pyList, SizeT < N - 1 > ());
437 template<
typename... Types>
440 boost::python::list outputList;
442 boost::python::tuple outputTuple(outputList);
465 template<
typename... Types>
478 template<
typename Type>
484 return boost::python::object();
499 template<
typename Scalar>
504 boost::python::extract<Scalar> valueProxy(pyObject);
505 if (valueProxy.check()) {
506 tmpValue =
static_cast<Scalar
>(valueProxy);
508 throw std::runtime_error(std::string(
"Could not convert value: Expected type '") +
Type<Scalar>::name() +
"' instead of '" +
509 pyObject.ptr()->ob_type->tp_name +
"'.");
522 template<
typename Value>
526 std::vector<Value> tmpVector;
527 if (PyList_Check(pyObject.ptr()) or PyGen_Check(pyObject.ptr())) {
539 template<
typename Value>
542 std::set<Value> result;
543 if (PyAnySet_Check(pyObject.ptr())) {
561 template<
typename Key,
typename Value>
562 std::map<Key, Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&)
564 std::map<Key, Value> tmpMap;
565 const boost::python::dict& pyDict =
static_cast<const boost::python::dict&
>(pyObject);
566 boost::python::list keys = pyDict.keys();
568 for (
int i = 0; i < boost::python::len(keys); ++i) {
571 tmpMap.insert(std::pair<Key, Value>(key, value));
585 template <
typename TupleType >
586 inline void SetTuple(TupleType& tuple,
const boost::python::tuple& pyTuple)
588 static const unsigned N = std::tuple_size<TupleType>::value;
589 if ((
unsigned)boost::python::len(pyTuple) != N) {
590 throw std::runtime_error(std::string(
"Given python tuple has length ") +
591 std::to_string(boost::python::len(pyTuple)) +
592 ", expected " + std::to_string(N));
598 template <
typename TupleType >
603 template <
typename TupleType,
size_t N >
606 SetTuple(tuple, pyTuple, SizeT < N - 1 > ());
607 std::get < N - 1 > (tuple) =
convertPythonObject(pyTuple[N - 1], std::get < N - 1 > (tuple));
617 template<
typename... Types>
618 std::tuple<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&)
620 std::tuple<Types...> tmpTuple;
621 const boost::python::tuple& pyTuple =
static_cast<const boost::python::tuple&
>(pyObject);
634 template <
typename... Types>
637 throw std::runtime_error(std::string(
"Could not set module parameter: Expected type '") +
638 Type<boost::variant<Types...> >::name() +
"' instead of '" +
639 pyObject.ptr()->ob_type->tp_name +
"'.");
643 template <
typename... Types,
size_t N >
644 inline void SetVariant(boost::variant<Types...>& variant,
const boost::python::object& pyObject,
SizeT<N>)
646 using Scalar =
typename std::tuple_element < N - 1, std::tuple<Types...> >::type;
652 }
catch (std::runtime_error& e) {
656 SetVariant(variant, pyObject, SizeT < N - 1 > ());
666 template<
typename... Types>
667 boost::variant<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&)
669 boost::variant<Types...> tmpVariant;
680 template<
typename Type>
681 std::optional<Type>
convertPythonObject(
const boost::python::object& pyObject,
const std::optional<Type>&)
683 std::optional<Type> tmpOptional = std::nullopt;
684 if (!pyObject.is_none()) {
Helper function object to unpack a value from a variant to a python object.
boost::python::object operator()(const T &value) const
actually convert a value.
boost::python::object convertToPythonObject(const Scalar &value)
------------— From C++ TO Python Converter ---------------------—
bool CheckVariant(const VariantType &, const boost::python::object &, SizeT< 0 >)
Recursion sentinal for the case that all former type checks failed for the variant.
bool iteratePythonObject(const boost::python::object &pyObject, Functor function)
Helper function to loop over a python object that implements the iterator concept and call a functor ...
Scalar convertPythonObject(const boost::python::object &pyObject, Scalar)
Convert from Python to given type.
void SetTuple(TupleType &tuple, const boost::python::tuple &pyTuple)
TMP (Template Meta Programming ) The given python tuple is written into the given c++ tuple.
bool CheckTuple(const std::tuple< Types... > &tuple, const boost::python::tuple &pyTuple, std::index_sequence< Is... >)
Check if all tuple elements match.
bool checkPythonObject(const boost::python::object &pyObject, bool)
check if the python object can be converted to the given type.
void GetTuple(const TupleType &tuple, boost::python::list &pyList)
TMP (Template Meta Programming ) The given python list is filled, and later converted into a python t...
void SetVariant(boost::variant< Types... > &, const boost::python::object &pyObject, SizeT< 0 >)
TMP (Template Meta Programming ) The given python object is written into the given c++ boost variant.
Abstract base class for different kinds of events.
Helper construct for TMP that provides an index at compile time to recurse through type lists.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name
static std::string name()
type name
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
Converts a template argument into a string for corresponding Python type.
static std::string name()
type name.
static std::string name()
type name.
Recursively convert multiple types to type names (used for tuples).
static std::string name()
type name.