253struct type_caster< QDateTime >
255 PYBIND11_TYPE_CASTER(QDateTime, _(
"datetime.datetime"));
257 static pybind11::object& get_datetime_type()
259 static pybind11::object datetime_type = []() -> pybind11::object {
261 return pybind11::module::import(
"datetime").attr(
"datetime");
263 return pybind11::none();
266 return datetime_type;
268 static pybind11::object& get_pandas_timestamp_type()
270 static pybind11::object pd_Timestamp = []() -> pybind11::object {
272 return pybind11::module::import(
"pandas").attr(
"Timestamp");
274 return pybind11::none();
279 static pybind11::object& get_numpy_timestamp_type()
281 static pybind11::object np_datetime64 = []() -> pybind11::object {
283 return pybind11::module::import(
"numpy").attr(
"datetime64");
285 return pybind11::none();
288 return np_datetime64;
290 bool load(pybind11::handle src,
bool convert)
295 static pybind11::object& datetime_type = get_datetime_type();
296 if (!datetime_type.is_none() && pybind11::isinstance(src, datetime_type)) {
299 pybind11::object timestamp = src.attr(
"timestamp");
300 double ts = timestamp().cast<
double >();
301 qint64 msecs_since_epoch =
static_cast< qint64
>(ts * 1000);
304 pybind11::object tzinfo = src.attr(
"tzinfo");
305 bool has_tzinfo = !tzinfo.is_none();
309 pybind11::object timestamp = src.attr(
"timestamp");
310 double ts = timestamp().cast<
double >();
311 qint64 msecs_since_epoch =
static_cast< qint64
>(ts * 1000);
312 value = QDateTime::fromMSecsSinceEpoch(msecs_since_epoch, Qt::UTC);
315 int year = src.attr(
"year").cast<
int >();
316 int month = src.attr(
"month").cast<
int >();
317 int day = src.attr(
"day").cast<
int >();
318 int hour = src.attr(
"hour").cast<
int >();
319 int minute = src.attr(
"minute").cast<
int >();
320 int second = src.attr(
"second").cast<
int >();
321 int microsecond = src.attr(
"microsecond").cast<
int >();
322 int msec = microsecond / 1000;
324 QDate date(year, month, day);
325 QTime time(hour, minute, second, msec);
327 if (date.isValid() && time.isValid()) {
329 value = QDateTime(date, time);
338 static pybind11::object& np_timestamp = get_numpy_timestamp_type();
339 if (!np_timestamp.is_none() && pybind11::isinstance(src, np_timestamp)) {
342 int64_t ns = src.attr(
"astype")(
"datetime64[ns]").attr(
"view")(
"int64").cast< int64_t >();
343 value = QDateTime::fromMSecsSinceEpoch(ns / 1000000, Qt::UTC);
350 static pybind11::object& pd_timestamp = get_pandas_timestamp_type();
351 if (!pd_timestamp.is_none() && pybind11::isinstance(src, pd_timestamp)) {
355 pybind11::object tz = src.attr(
"tz");
356 bool has_tz = !tz.is_none();
360 double ts = src.attr(
"timestamp")().cast< double >();
361 value = QDateTime::fromMSecsSinceEpoch(
static_cast< qint64
>(ts * 1000), Qt::UTC);
365 pybind11::object py_dt = src.attr(
"to_pydatetime")();
366 return load(py_dt, convert);
377 static pybind11::handle
378 cast(
const QDateTime& src, pybind11::return_value_policy , pybind11::handle )
380 if (!src.isValid()) {
384 qint64 ms = src.toMSecsSinceEpoch();
385 double ts = ms / 1000.0;
387 object datetime_type = module_::import(
"datetime").attr(
"datetime");
388 return datetime_type.attr(
"fromtimestamp")(ts).release();
665struct type_caster< QVariant >
667 PYBIND11_TYPE_CASTER(QVariant, _(
"Any"));
670 static bool is_none_or_empty(handle src)
672 return src.is_none() || (PyObject_Size(src.ptr()) == 0 && PyErr_Occurred() ==
nullptr);
676 static bool is_numpy_array(handle src)
679 static pybind11::object numpy_module = []() -> pybind11::object {
681 return pybind11::module::import(
"numpy");
683 return pybind11::none();
687 if (!numpy_module.is_none()) {
688 static pybind11::object ndarray_type = numpy_module.attr(
"ndarray");
689 static pybind11::object generic_type = numpy_module.attr(
"generic");
690 return pybind11::isinstance(src, ndarray_type) || pybind11::isinstance(src, generic_type);
699 bool handle_numpy_object(handle src)
702 pybind11::object np_obj = reinterpret_borrow< object >(src);
703 pybind11::dtype dt = np_obj.attr(
"dtype");
704 char dtype_char = dt.char_();
707 pybind11::tuple shape = np_obj.attr(
"shape");
708 std::size_t ndim = pybind11::len(shape);
713 pybind11::object scalar = np_obj.attr(
"item")();
715 switch (dtype_char) {
717 value = scalar.cast<
bool >();
720 value = QChar(
static_cast< char >(scalar.cast<
int >()));
724 value = scalar.cast<
int >();
727 value = scalar.cast<
long long >();
730 value = QChar(
static_cast< unsigned char >(scalar.cast<
int >()));
734 value = scalar.cast<
unsigned int >();
737 value = scalar.cast<
unsigned long long >();
741 value = scalar.cast<
float >();
744 value = scalar.cast<
double >();
749 value = QString::fromStdString(pybind11::str(scalar));
754 pybind11::object item = np_obj.attr(
"item")();
758 if (PyUnicode_Check(item.ptr())) {
760 const char* data = PyUnicode_AsUTF8AndSize(item.ptr(), &size);
762 str_val = QString::fromUtf8(data, size);
765 str_val = QString::fromStdString(pybind11::str(item));
773 pybind11::object item = np_obj.attr(
"item")();
776 if (PyBytes_Check(item.ptr())) {
779 if (PyBytes_AsStringAndSize(item.ptr(), &data, &size) != -1) {
780 byte_val = QByteArray(data, size);
783 byte_val = QByteArray(pybind11::str(item).cast< std::string >().c_str());
792 pybind11::object item = np_obj.attr(
"item")();
796 static pybind11::object datetime_type = []() -> pybind11::object {
798 return pybind11::module::import(
"datetime").attr(
"datetime");
800 return pybind11::none();
804 if (!datetime_type.is_none() && pybind11::isinstance(item, datetime_type)) {
805 QDateTime dt_val = item.cast< QDateTime >();
815 pybind11::object timestamp = item.attr(
"astype")(
"datetime64[ms]");
816 int64_t ms = pybind11::cast< int64_t >(timestamp.attr(
"view")(
"int64"));
817 value = QDateTime::fromMSecsSinceEpoch(ms);
821 QString str_val = QString::fromStdString(pybind11::str(item));
829 QString str_val = QString::fromStdString(pybind11::str(np_obj.attr(
"item")()));
836 QByteArray byte_val = QByteArray(pybind11::str(np_obj.attr(
"item")()).cast< std::string >().c_str());
843 pybind11::object item = np_obj.attr(
"item")();
845 if (caster.load(item,
true)) {
846 value = caster.value;
853 value = QString::fromStdString(pybind11::str(np_obj.attr(
"item")()));
861 for (std::size_t i = 0; i < ndim; ++i) {
862 total_size *= shape[ i ].cast<
int >();
865 pybind11::list py_list = np_obj.attr(
"tolist")();
868 QVariantList qt_list;
869 qt_list.reserve(total_size);
871 for (
auto item : py_list) {
873 if (caster.load(item,
true)) {
874 qt_list.append(caster.value);
892 bool load(handle src,
bool convert)
904 if (is_numpy_array(src)) {
905 return handle_numpy_object(src);
910 if (PyLong_Check(src.ptr())) {
913 int int_val = src.cast<
int >();
914 value = QVariant(int_val);
919 qlonglong ll_val = src.cast< qlonglong >();
920 value = QVariant(ll_val);
925 qulonglong ull_val = src.cast< qulonglong >();
926 value = QVariant(ull_val);
936 if (PyFloat_Check(src.ptr())) {
938 double double_val = src.cast<
double >();
939 value = QVariant(double_val);
943 float float_val = src.cast<
float >();
944 value = QVariant(float_val);
953 if (PyBool_Check(src.ptr())) {
954 bool bool_val = src.cast<
bool >();
955 value = QVariant(bool_val);
960 if (PyUnicode_Check(src.ptr())) {
962 QString str_val = src.cast< QString >();
963 value = QVariant(str_val);
971 if (PyBytes_Check(src.ptr()) || PyByteArray_Check(src.ptr())) {
973 QByteArray byte_val = src.cast< QByteArray >();
974 value = QVariant(byte_val);
982 if (PyList_Check(src.ptr()) || PyTuple_Check(src.ptr())) {
985 QVariantList list_val = src.cast< QVariantList >();
986 value = QVariant(list_val);
994 if (PyDict_Check(src.ptr())) {
997 QVariantMap map_val = src.cast< QVariantMap >();
998 value = QVariant(map_val);
1003 QVariantHash hash_val = src.cast< QVariantHash >();
1004 value = QVariant(hash_val);
1013 if (PySet_Check(src.ptr())) {
1015 QVariantList list_val;
1016 auto set_obj = reinterpret_borrow< set >(src);
1017 for (
auto item : set_obj) {
1019 if (caster.load(item, convert)) {
1020 list_val.append(caster.value);
1025 value = QVariant(list_val);
1035 static pybind11::object datetime_type = []() {
1036 return pybind11::module::import(
"datetime").attr(
"datetime");
1039 if (pybind11::isinstance(src, datetime_type)) {
1040 QDateTime dt_val = src.cast< QDateTime >();
1041 value = QVariant(dt_val);
1049 static pybind11::object date_type = []() {
return pybind11::module::import(
"datetime").attr(
"date"); }();
1051 if (pybind11::isinstance(src, date_type)) {
1052 QDate date_val = src.cast< QDate >();
1053 value = QVariant(date_val);
1061 static pybind11::object time_type = []() {
return pybind11::module::import(
"datetime").attr(
"time"); }();
1063 if (pybind11::isinstance(src, time_type)) {
1064 QTime time_val = src.cast< QTime >();
1065 value = QVariant(time_val);
1075 QString str_val = src.cast< QString >();
1076 value = QVariant(str_val);
1094 static handle cast(
const QVariant& src, return_value_policy policy, handle parent)
1096 if (!src.isValid() || src.isNull()) {
1102 int type_id = src.userType();
1106 case QMetaType::UnknownType:
1110 case QMetaType::Int:
1111 return pybind11::cast(src.toInt()).release();
1112 case QMetaType::UInt:
1113 return pybind11::cast(src.toUInt()).release();
1114 case QMetaType::LongLong:
1115 return pybind11::cast(src.toLongLong()).release();
1116 case QMetaType::ULongLong:
1117 return pybind11::cast(src.toULongLong()).release();
1118 case QMetaType::Double:
1119 return pybind11::cast(src.toDouble()).release();
1120 case QMetaType::Float:
1121 return pybind11::cast(src.toFloat()).release();
1122 case QMetaType::Bool:
1123 return pybind11::cast(src.toBool()).release();
1126 case QMetaType::QString:
1127 return pybind11::cast(src.toString()).release();
1128 case QMetaType::QByteArray:
1129 return pybind11::cast(src.toByteArray()).release();
1130 case QMetaType::QChar:
1131 return pybind11::cast(src.toChar()).release();
1134 case QMetaType::QDate:
1135 return pybind11::cast(src.toDate()).release();
1136 case QMetaType::QTime:
1137 return pybind11::cast(src.toTime()).release();
1138 case QMetaType::QDateTime:
1139 return pybind11::cast(src.toDateTime()).release();
1141 case QMetaType::QVariantList: {
1142 QVariantList list = src.toList();
1143 pybind11::list py_list;
1144 for (
const QVariant& item : list) {
1145 py_list.append(cast(item, policy, parent));
1147 return py_list.release();
1150 case QMetaType::QVariantMap: {
1151 QVariantMap map = src.toMap();
1152 pybind11::dict py_dict;
1153 for (
auto it = map.begin(); it != map.end(); ++it) {
1154 py_dict[ pybind11::cast(it.key()) ] = cast(it.value(), policy, parent);
1156 return py_dict.release();
1159 case QMetaType::QVariantHash: {
1160 QVariantHash hash = src.toHash();
1161 pybind11::dict py_dict;
1162 for (
auto it = hash.begin(); it != hash.end(); ++it) {
1163 py_dict[ pybind11::cast(it.key()) ] = cast(it.value(), policy, parent);
1165 return py_dict.release();
1171 const char* type_name = src.typeName();
1173 QString type_str = QString::fromUtf8(type_name);
1176 if (type_str ==
"QList<QString>") {
1177 return pybind11::cast(src.value< QList< QString > >()).release();
1180 else if (type_str ==
"QList<int>") {
1181 return pybind11::cast(src.value< QList< int > >()).release();
1184 else if (type_str ==
"QList<double>") {
1185 return pybind11::cast(src.value< QList< double > >()).release();
1188 else if (type_str ==
"QVector<QString>") {
1189 return pybind11::cast(src.value< QVector< QString > >()).release();
1192 else if (type_str.startsWith(
"QList<") || type_str.startsWith(
"QVector<")) {
1194 QVariantList list = src.toList();
1195 pybind11::list py_list;
1196 for (
const QVariant& item : list) {
1197 py_list.append(cast(item, policy, parent));
1199 return py_list.release();
1202 else if (type_str.startsWith(
"QMap<") || type_str.startsWith(
"QHash<")) {
1204 QVariantMap map = src.toMap();
1205 pybind11::dict py_dict;
1206 for (
auto it = map.begin(); it != map.end(); ++it) {
1207 py_dict[ pybind11::cast(it.key()) ] = cast(it.value(), policy, parent);
1209 return py_dict.release();
1212 else if (type_str.startsWith(
"QSet<")) {
1214 QVariantList list = src.toList();
1215 pybind11::set py_set;
1216 for (
const QVariant& item : list) {
1217 py_set.add(cast(item, policy, parent));
1219 return py_set.release();
1224 if (src.canConvert< QString >()) {
1225 return pybind11::cast(src.toString()).release();
1229 return pybind11::cast(src.toString()).release();