diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b689af..3a27eae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,11 +44,11 @@ endif() #----------------------------------------------------------------------------- # Generator -#if(PythonQt_Qt5) -# add_subdirectory(generator_50 EXCLUDE_FROM_ALL) -# add_custom_target(generator) -# add_dependencies(generator pythonqt_generator) -#endif() +if(PythonQt_Qt5) + add_subdirectory(generator_50 EXCLUDE_FROM_ALL) + add_custom_target(generator) + add_dependencies(generator pythonqt_generator) +endif() # TODO @@ -107,7 +107,6 @@ endif() option(PythonQt_Python3 "Use Python 3.x (3.3+)" OFF) if(PythonQt_Python3) set(PythonQt_PythonMin 3.3) - add_definitions(PYTHON3K) else(PythonQt_Python3) set(PythonQt_PythonMin 2.6) endif() diff --git a/generated_cpp_50/com_trolltech_qt_core_builtin/com_trolltech_qt_core_builtin0.h b/generated_cpp_50/com_trolltech_qt_core_builtin/com_trolltech_qt_core_builtin0.h index 0aff7b0..8bcd2ef 100644 --- a/generated_cpp_50/com_trolltech_qt_core_builtin/com_trolltech_qt_core_builtin0.h +++ b/generated_cpp_50/com_trolltech_qt_core_builtin/com_trolltech_qt_core_builtin0.h @@ -174,7 +174,11 @@ void delete_QByteArray(QByteArray* obj) { delete obj; } PyObject* data(QByteArray* b) { if (b->data()) { +#ifdef PY3K + return PyUnicode_FromStringAndSize(b->data(), b->size()); +#else return PyString_FromStringAndSize(b->data(), b->size()); +#endif } else { Py_INCREF(Py_None); return Py_None; diff --git a/generator_50/typesystem_core.xml b/generator_50/typesystem_core.xml index 52bde3d..5de2425 100644 --- a/generator_50/typesystem_core.xml +++ b/generator_50/typesystem_core.xml @@ -1426,7 +1426,7 @@ - + @@ -1439,7 +1439,7 @@ - + @@ -1447,7 +1447,7 @@ - + @@ -1505,14 +1505,6 @@ - - - - - QFile & %out% = *qscriptvalue_cast<QFile*>(%in%); - - - diff --git a/generator_50/typesystem_gui.xml b/generator_50/typesystem_gui.xml index e53e876..a6aef44 100644 --- a/generator_50/typesystem_gui.xml +++ b/generator_50/typesystem_gui.xml @@ -1200,14 +1200,6 @@ - -QImage* new_QImage( const uchar * data, int width, int height, QImage::Format format ) -{ - QImage* image = new QImage(width, height, format); - memcpy(image->bits(), data, image->byteCount()); - return image; -} - @@ -2101,23 +2093,31 @@ QImage* new_QImage( const uchar * data, int width, int height, QImage::Format fo - - QAction* addAction (QMenu* menu, const QString & text, PyObject* callable, const QKeySequence & shortcut = 0) { - QAction* a = menu->addAction(text); - a->setShortcut(shortcut); - PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); - return a; - } + + + - QAction* addAction (QMenu* menu, const QIcon& icon, const QString& text, PyObject* callable, const QKeySequence& shortcut = 0) - { - QAction* a = menu->addAction(text); - a->setIcon(icon); - a->setShortcut(shortcut); - PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); - return a; - } - + + + + + + QAction* addAction (QMenu* menu, const QString & text, PyObject* callable, const QKeySequence & shortcut = 0) { + QAction* a = menu->addAction(text); + a->setShortcut(shortcut); + PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); + return a; + } + + QAction* addAction (QMenu* menu, const QIcon& icon, const QString& text, PyObject* callable, const QKeySequence& shortcut = 0) + { + QAction* a = menu->addAction(text); + a->setIcon(icon); + a->setShortcut(shortcut); + PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); + return a; + } + @@ -2158,14 +2158,15 @@ QImage* new_QImage( const uchar * data, int width, int height, QImage::Format fo - - QAction* addAction (QMenuBar* menu, const QString & text, PyObject* callable) - { - QAction* a = menu->addAction(text); - PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); - return a; - } - + + + QAction* addAction (QMenuBar* menu, const QString & text, PyObject* callable) + { + QAction* a = menu->addAction(text); + PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); + return a; + } + @@ -4887,22 +4888,23 @@ QImage* new_QImage( const uchar * data, int width, int height, QImage::Format fo - - QAction* addAction (QToolBar* menu, const QString & text, PyObject* callable) - { - QAction* a = menu->addAction(text); - PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); - return a; - } - - QAction* addAction (QToolBar* menu, const QIcon& icon, const QString& text, PyObject* callable) - { - QAction* a = menu->addAction(text); - a->setIcon(icon); - PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); - return a; - } - + + + QAction* addAction (QToolBar* menu, const QString & text, PyObject* callable) + { + QAction* a = menu->addAction(text); + PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); + return a; + } + + QAction* addAction (QToolBar* menu, const QIcon& icon, const QString& text, PyObject* callable) + { + QAction* a = menu->addAction(text); + a->setIcon(icon); + PythonQt::self()->addSignalHandler(a, SIGNAL(triggered(bool)), callable); + return a; + } + @@ -5665,6 +5667,7 @@ QImage* new_QImage( const uchar * data, int width, int height, QImage::Format fo + diff --git a/generator_50/typesystem_opengl.xml b/generator_50/typesystem_opengl.xml index 11e102c..70c250b 100644 --- a/generator_50/typesystem_opengl.xml +++ b/generator_50/typesystem_opengl.xml @@ -9,11 +9,6 @@ - - - - - @@ -32,8 +27,6 @@ - - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7524182..97ee1f6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,9 +87,9 @@ qt_add_resources(GEN_QRC ${SOURCES_QRC}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -add_definitions(-DQT_NO_KEYWORDS) # recent python versions use them :( +#add_definitions(-DQT_NO_KEYWORDS) # recent python versions use them :( -add_library(PythonQt SHARED ${SOURCES} ${GEN_MOC} ${GEN_QRC}) +add_library(PythonQt SHARED ${SOURCES} ${GEN_MOC} ${GEN_QRC} ${HEADERS}) if(PythonQt_Qt5) qt_use_modules(PythonQt Core Gui Widgets) else() diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index d0ec843..15cb5ee 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -166,7 +166,11 @@ PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName) _p->_PythonQtObjectPtr_metaId = qRegisterMetaType("PythonQtObjectPtr"); if ((flags & PythonAlreadyInitialized) == 0) { +#ifdef PY3K + Py_SetProgramName(const_cast(L"PythonQt")); +#else Py_SetProgramName(const_cast("PythonQt")); +#endif if (flags & IgnoreSiteModule) { // this prevents the automatic importing of Python site files Py_NoSiteFlag = 1; @@ -496,7 +500,11 @@ PyObject* PythonQtPrivate::dummyTuple() { static PyObject* dummyTuple = NULL; if (dummyTuple==NULL) { dummyTuple = PyTuple_New(1); +#ifdef PY3K + PyTuple_SET_ITEM(dummyTuple, 0, PyUnicode_FromString("dummy")); +#else PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy")); +#endif } return dummyTuple; } @@ -526,7 +534,11 @@ PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObje PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) { PythonQtClassWrapper* result; +#ifdef PY3K + PyObject* className = PyUnicode_FromString(info->className()); +#else PyObject* className = PyString_FromString(info->className()); +#endif PyObject* baseClasses = PyTuple_New(1); PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type); @@ -561,10 +573,18 @@ PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) { PyObject* result; +#ifdef PY3K + PyObject* className = PyUnicode_FromString(enumName); +#else PyObject* className = PyString_FromString(enumName); +#endif PyObject* baseClasses = PyTuple_New(1); +#ifdef PY3K + PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyLong_Type); +#else PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type); +#endif PyObject* module = PyObject_GetAttrString(parentObject, "__module__"); PyObject* typeDict = PyDict_New(); @@ -703,11 +723,21 @@ QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) { globals = dict; } else { dict = PyObject_GetAttrString(object, "__dict__"); - globals = PyObject_GetAttrString(PyImport_ImportModule(PyString_AS_STRING(PyObject_GetAttrString(object, "__module__"))),"__dict__"); + globals = PyObject_GetAttrString(PyImport_ImportModule( +#ifdef PY3K + PyUnicode_AsUTF8( +#else + PyString_AS_STRING( +#endif + PyObject_GetAttrString(object, "__module__"))),"__dict__"); } PyObject* r = NULL; if (dict) { +#ifdef PY3K + r = PyEval_EvalCode(pycode, globals, dict); +#else r = PyEval_EvalCode((PyCodeObject*)pycode, globals , dict); +#endif } if (r) { result = PythonQtConv::PyObjToQVariant(r); @@ -894,7 +924,11 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type) } else { PyObject* doc = PyObject_GetAttrString(object, "__doc__"); if (doc) { +#ifdef PY3K + results << PyUnicode_AsUTF8(doc); +#else results << PyString_AsString(doc); +#endif Py_DECREF(doc); } } @@ -922,7 +956,11 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type) value = PyObject_GetAttr(object, key); } if (!value) continue; +#ifdef PY3K + keystr = PyUnicode_AsUTF8(key); +#else keystr = PyString_AsString(key); +#endif static const QString underscoreStr("__tmp"); if (!keystr.startsWith(underscoreStr)) { switch (type) { @@ -930,18 +968,25 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type) results << keystr; break; case Class: +#ifdef PY3K + if(PyType_Check(value)) { +#else if (value->ob_type == &PyClass_Type || value->ob_type == &PyType_Type) { +#endif results << keystr; } break; case Variable: - if (value->ob_type != &PyClass_Type - && value->ob_type != &PyCFunction_Type - && value->ob_type != &PyFunction_Type - && value->ob_type != &PyMethod_Type - && value->ob_type != &PyModule_Type - && value->ob_type != &PyType_Type - && value->ob_type != &PythonQtSlotFunction_Type + if ( +#ifndef PY3K + value->ob_type != &PyClass_Type && +#endif + value->ob_type != &PyCFunction_Type && + value->ob_type != &PyFunction_Type && + value->ob_type != &PyMethod_Type && + value->ob_type != &PyModule_Type && + value->ob_type != &PyType_Type && + value->ob_type != &PythonQtSlotFunction_Type ) { results << keystr; } @@ -1282,8 +1327,12 @@ int custom_system_exit_exception_handler() // return exitcode; PyErr_Fetch(&exception, &value, &tb); +#ifdef PY3K + std::cout << std::endl; +#else if (Py_FlushLine()) PyErr_Clear(); +#endif fflush(stdout); if (value == NULL || value == Py_None) goto done; @@ -1299,8 +1348,13 @@ int custom_system_exit_exception_handler() /* If we failed to dig out the 'code' attribute, just let the else clause below print the error. */ } +#ifdef PY3K + if (PyLong_Check(value)) + exitcode = (int)PyLong_AsLong(value); +#else if (PyInt_Check(value)) exitcode = (int)PyInt_AsLong(value); +#endif else { PyObject *sys_stderr = PySys_GetObject(const_cast("stderr")); if (sys_stderr != NULL && sys_stderr != Py_None) { @@ -1437,13 +1491,32 @@ static PyMethodDef PythonQtMethods[] = { {NULL, NULL, 0, NULL} }; +#ifdef PY3K +static PyModuleDef PythonQtModule = { + PyModuleDef_HEAD_INIT, + "", + NULL, + -1, + PythonQtMethods, + NULL, + NULL, + NULL, + NULL +}; +#endif + void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName) { QByteArray name = "PythonQt"; if (!pythonQtModuleName.isEmpty()) { name = pythonQtModuleName; } +#ifdef PY3K + PythonQtModule.m_name = name.constData(); + _p->_pythonQtModule = PyModule_Create(&PythonQtModule); +#else _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods); +#endif _p->_pythonQtModuleName = name; if (redirectStdOut) { @@ -1469,7 +1542,11 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ PyObject *module_names = PyTuple_New(old_size+1); for(Py_ssize_t i = 0; i < old_size; i++) PyTuple_SetItem(module_names, i, PyTuple_GetItem(old_module_names, i)); +#ifdef PY3K + PyTuple_SetItem(module_names, old_size, PyUnicode_FromString(name.constData())); +#else PyTuple_SetItem(module_names, old_size, PyString_FromString(name.constData())); +#endif PyModule_AddObject(sys.object(),"builtin_module_names",module_names); Py_DecRef(old_module_names); } @@ -1512,7 +1589,11 @@ QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& va QString type; +#ifdef PY3K + if (PyType_Check(methodObject)) { +#else if (methodObject->ob_type == &PyClass_Type || methodObject->ob_type == &PyType_Type) { +#endif // the methodObject is not a method, but the name of a type/class. This means // a constructor is called. Return the context. type = context; @@ -1525,8 +1606,13 @@ QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& va } else { PyObject* classNameObject = PyObject_GetAttrString(variableObject, "__name__"); if (classNameObject) { +#ifdef PY3K + Q_ASSERT(PyUnicode_Check(classNameObject)); + className = PyUnicode_AsUTF8(classNameObject); +#else Q_ASSERT(PyString_Check(classNameObject)); className = PyString_AsString(classNameObject); +#endif Py_DECREF(classNameObject); } } @@ -1559,11 +1645,20 @@ QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& va PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(type.toLatin1().constData()); if (typeInfo && typeInfo->pythonQtClassWrapper()) { PyObject* s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__module__"); +#ifdef PY3K + Q_ASSERT(PyUnicode_Check(s)); + type = QString(PyUnicode_AsUTF8(s)); +#else Q_ASSERT(PyString_Check(s)); type = QString(PyString_AsString(s)) + "." + type; +#endif Py_DECREF(s); s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__name__"); +#ifdef PY3K + Q_ASSERT(PyUnicode_Check(s)); +#else Q_ASSERT(PyString_Check(s)); +#endif Py_DECREF(s); } } @@ -1668,7 +1763,11 @@ PyObject* PythonQt::helpCalled(PythonQtClassInfo* info) Q_EMIT pythonHelpRequest(QByteArray(info->className())); return Py_BuildValue(""); } else { +#ifdef PY3K + return PyUnicode_FromString(info->help().toLatin1().data()); +#else return PyString_FromString(info->help().toLatin1().data()); +#endif } } @@ -1743,8 +1842,11 @@ bool PythonQtPrivate::isMethodDescriptor(PyObject* object) const if (PyObject_HasAttrString(object, "__get__") && !PyObject_HasAttrString(object, "__set__") && !PyMethod_Check(object) && - !PyFunction_Check(object) && - !PyClass_Check(object)) { + !PyFunction_Check(object) +#ifndef PY3K + && !PyClass_Check(object) +#endif + ) { return true; } return false; @@ -1760,7 +1862,11 @@ QString PythonQtPrivate::getSignature(PyObject* object) bool decrefMethod = false; +#ifdef PY3K + if (PyType_Check(object)) { +#else if (object->ob_type == &PyClass_Type || object->ob_type == &PyType_Type) { +#endif method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__"); decrefMethod = true; } else if (object->ob_type == &PyFunction_Type) { @@ -1775,14 +1881,23 @@ QString PythonQtPrivate::getSignature(PyObject* object) QString docstr; PyObject* doc = PyObject_GetAttrString(object, "__doc__"); if (doc) { +#ifdef PY3K + docstr = PyUnicode_AsUTF8(doc); +#else docstr = PyString_AsString(doc); +#endif Py_DECREF(doc); } PyObject* s = PyObject_GetAttrString(object, "__name__"); if (s) { +#ifdef PY3K + Q_ASSERT(PyUnicode_Check(s)); + signature = PyUnicode_AsUTF8(s); +#else Q_ASSERT(PyString_Check(s)); signature = PyString_AsString(s); +#endif if (docstr.startsWith(signature + "(")) { signature = docstr; } else { @@ -1800,15 +1915,25 @@ QString PythonQtPrivate::getSignature(PyObject* object) QString funcName; PyObject* s = PyObject_GetAttrString((PyObject*)func, "__name__"); if (s) { +#ifdef PY3K + Q_ASSERT(PyUnicode_Check(s)); + funcName = PyUnicode_AsUTF8(s); +#else Q_ASSERT(PyString_Check(s)); funcName = PyString_AsString(s); +#endif Py_DECREF(s); } if (method && funcName == "__init__") { PyObject* s = PyObject_GetAttrString(object, "__name__"); if (s) { +#ifdef PY3K + Q_ASSERT(PyUnicode_Check(s)); + funcName = PyUnicode_AsUTF8(s); +#else Q_ASSERT(PyString_Check(s)); funcName = PyString_AsString(s); +#endif Py_DECREF(s); } } @@ -1826,19 +1951,34 @@ QString PythonQtPrivate::getSignature(PyObject* object) Q_ASSERT(PyTuple_Check(code->co_varnames)); for (int i=0; ico_varnames, i); +#ifdef PY3K + Q_ASSERT(PyUnicode_Check(name)); + arguments << PyUnicode_AsUTF8(name); +#else Q_ASSERT(PyString_Check(name)); arguments << PyString_AsString(name); +#endif } if (code->co_flags & CO_VARARGS) { PyObject* s = PyTuple_GetItem(code->co_varnames, nargs); +#ifdef PY3K + Q_ASSERT(PyUnicode_Check(s)); + varargs = PyUnicode_AsUTF8(s); +#else Q_ASSERT(PyString_Check(s)); varargs = PyString_AsString(s); +#endif nargs += 1; } if (code->co_flags & CO_VARKEYWORDS) { PyObject* s = PyTuple_GetItem(code->co_varnames, nargs); +#ifdef PY3K + Q_ASSERT(PyUnicode_Check(s)); + varkeywords = PyUnicode_AsUTF8(s); +#else Q_ASSERT(PyString_Check(s)); varkeywords = PyString_AsString(s); +#endif } } @@ -1848,8 +1988,13 @@ QString PythonQtPrivate::getSignature(PyObject* object) for (Py_ssize_t i=0; i_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul; } if (typeSlots & PythonQt::Type_Divide) { +#ifndef PY3K wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div; +#endif wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div; } if (typeSlots & PythonQt::Type_And) { @@ -188,7 +190,9 @@ static void initializeSlots(PythonQtClassWrapper* wrap) wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul; } if (typeSlots & PythonQt::Type_InplaceDivide) { +#ifndef PY3K wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv; +#endif wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv; } if (typeSlots & PythonQt::Type_InplaceAnd) { @@ -213,7 +217,11 @@ static void initializeSlots(PythonQtClassWrapper* wrap) wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert; } if (typeSlots & PythonQt::Type_NonZero) { +#ifdef PY3K + wrap->_base.as_number.nb_bool = (inquiry)PythonQtInstanceWrapper_nonzero; +#else wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero; +#endif } } } @@ -252,10 +260,10 @@ static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, // ... // class MyWidget(MyWidgetBase): // ... - while( superType && superType->ob_type != &PythonQtClassWrapper_Type ) + while( superType && Py_TYPE(superType) != &PythonQtClassWrapper_Type ) superType = superType->tp_base; - if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) { + if (!superType || (Py_TYPE(superType) != &PythonQtClassWrapper_Type)) { PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name); return -1; } @@ -269,7 +277,11 @@ static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type) { +#ifdef PY3K + return PyUnicode_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data()); +#else return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data()); +#endif } static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type) @@ -325,7 +337,11 @@ static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name) const char *attributeName; PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj; +#ifdef PY3K + if ((attributeName = PyUnicode_AsUTF8(name)) == NULL) { +#else if ((attributeName = PyString_AsString(name)) == NULL) { +#endif return NULL; } if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) { @@ -352,7 +368,11 @@ static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name) } } if (wrapper->classInfo()->constructors()) { +#ifdef PY3K + PyObject* initName = PyUnicode_FromString("__init__"); +#else PyObject* initName = PyString_FromString("__init__"); +#endif PyObject* func = PyType_Type.tp_getattro(obj, initName); Py_DECREF(initName); PyDict_SetItemString(dict, "__init__", func); @@ -369,6 +389,9 @@ static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name) } // look in Python to support derived Python classes +#ifdef PY3K + return PyObject_GenericGetAttr(obj, name); +#else PyObject* superAttr = PyType_Type.tp_getattro(obj, name); if (superAttr) { return superAttr; @@ -403,6 +426,7 @@ static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name) QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'"; PyErr_SetString(PyExc_AttributeError, error.toLatin1().data()); return NULL; +#endif } static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value) @@ -435,8 +459,7 @@ static PyObject * PythonQtClassWrapper_repr(PyObject * obj) */ PyTypeObject PythonQtClassWrapper_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "PythonQt.PythonQtClassWrapper", /*tp_name*/ sizeof(PythonQtClassWrapper), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/src/PythonQtConversion.cpp b/src/PythonQtConversion.cpp index bb01083..6adbb59 100644 --- a/src/PythonQtConversion.cpp +++ b/src/PythonQtConversion.cpp @@ -45,6 +45,10 @@ #include #include +#if PY_MAJOR_VERSION >= 3 +#define PY3K +#endif + PythonQtValueStorage PythonQtConv::global_valueStorage; PythonQtValueStorage PythonQtConv::global_ptrStorage; PythonQtValueStorageWithCleanup PythonQtConv::global_variantStorage; @@ -78,7 +82,11 @@ PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::Paramet // a char ptr will probably be a null terminated string, so we support that: char* charPtr = *((char**)data); if (charPtr) { +#ifdef PY3K + return PyUnicode_FromString(charPtr); +#else return PyString_FromString(charPtr); +#endif } else { Py_INCREF(Py_None); return Py_None; @@ -129,27 +137,27 @@ PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* dat Py_INCREF(Py_None); return Py_None; case QMetaType::Char: - return PyInt_FromLong(*((char*)data)); + return PyLong_FromLong(*((char*)data)); case QMetaType::UChar: - return PyInt_FromLong(*((unsigned char*)data)); + return PyLong_FromLong(*((unsigned char*)data)); case QMetaType::Short: - return PyInt_FromLong(*((short*)data)); + return PyLong_FromLong(*((short*)data)); case QMetaType::UShort: - return PyInt_FromLong(*((unsigned short*)data)); + return PyLong_FromLong(*((unsigned short*)data)); case QMetaType::Long: - return PyInt_FromLong(*((long*)data)); + return PyLong_FromLong(*((long*)data)); case QMetaType::ULong: // does not fit into simple int of python return PyLong_FromUnsignedLong(*((unsigned long*)data)); case QMetaType::Bool: return PythonQtConv::GetPyBool(*((bool*)data)); case QMetaType::Int: - return PyInt_FromLong(*((int*)data)); + return PyLong_FromLong(*((int*)data)); case QMetaType::UInt: // does not fit into simple int of python return PyLong_FromUnsignedLong(*((unsigned int*)data)); case QMetaType::QChar: - return PyInt_FromLong(*((short*)data)); + return PyLong_FromLong(*((short*)data)); case QMetaType::Float: return PyFloat_FromDouble(*((float*)data)); case QMetaType::Double: @@ -293,7 +301,7 @@ void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, vo if (typeId == cursorId) { static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL); if ((PyObject*)obj->ob_type == qtCursorShapeEnum) { - Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj); + Qt::CursorShape val = (Qt::CursorShape)PyLong_AsLong(obj); if (!ptr) { PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr); ptr = (void*)((QVariant*)ptr)->constData(); @@ -305,7 +313,7 @@ void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, vo // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default) static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper(); if ((PyObject*)obj->ob_type == qtGlobalColorEnum) { - Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj); + Qt::GlobalColor val = (Qt::GlobalColor)PyLong_AsLong(obj); if (!ptr) { PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr); ptr = (void*)((QVariant*)ptr)->constData(); @@ -324,7 +332,7 @@ void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, vo // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default) static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper(); if ((PyObject*)obj->ob_type == qtGlobalColorEnum) { - Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj); + Qt::GlobalColor val = (Qt::GlobalColor)PyLong_AsLong(obj); if (!ptr) { PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr); ptr = (void*)((QVariant*)ptr)->constData(); @@ -342,7 +350,7 @@ void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, vo } else if (typeId == colorId) { // colors can be created from Qt::GlobalColor (and from colors, but that's the default) if ((PyObject*)obj->ob_type == qtGlobalColorEnum) { - Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj); + Qt::GlobalColor val = (Qt::GlobalColor)PyLong_AsLong(obj); if (!ptr) { PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr); ptr = (void*)((QVariant*)ptr)->constData(); @@ -393,10 +401,18 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i // a pointer if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar) { +#ifdef PY3K + if (PyUnicode_Check(obj)) { + QByteArray bytes(PyUnicode_AsUTF8(obj)); + void* ptr2 = NULL; + PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(bytes), ptr2); + PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr); +#else if (obj->ob_type == &PyString_Type) { // take direct reference to string data const char* data = PyString_AS_STRING(obj); PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)data, ptr); +#endif } else { // convert to string QString str = PyObjGetString(obj, strict, ok); @@ -601,7 +617,7 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i ok = false; if ((PyObject*)obj->ob_type == info.enumWrapper) { // we have a exact enum type match: - val = PyInt_AS_LONG(obj); + val = PyLong_AsLong(obj); ok = true; } else if (!strict) { // we try to get any integer, when not being strict. If we are strict, integers are not wanted because @@ -681,8 +697,10 @@ QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok ok = false; // if we are strict, we do not want to convert a string to a stringlist // (strings in python are detected to be sequences) - if (strict && - (val->ob_type == &PyString_Type || + if (strict && ( +#ifndef PY3K + val->ob_type == &PyString_Type || +#endif PyUnicode_Check(val))) { ok = false; return v; @@ -703,7 +721,13 @@ QString PythonQtConv::PyObjGetRepresentation(PyObject* val) QString r; PyObject* str = PyObject_Repr(val); if (str) { +#ifdef PY3K + Py_UCS4 *x = PyUnicode_AsUCS4Copy(str); + r = QString::fromUcs4(x, PyUnicode_GetLength(str)); + PyMem_Free(x); +#else r = QString(PyString_AS_STRING(str)); +#endif Py_DECREF(str); } return r; @@ -712,19 +736,34 @@ QString PythonQtConv::PyObjGetRepresentation(PyObject* val) QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) { QString r; ok = true; - if (val->ob_type == &PyString_Type) { +#ifndef PY3K + if (Py_TYPE(val) == &PyString_Type) { r = QString(PyString_AS_STRING(val)); - } else if (PyUnicode_Check(val)) { + } else +#endif + if (PyUnicode_Check(val)) { +#ifdef PY3K + Py_UCS4 *x = PyUnicode_AsUCS4Copy(val); + r = QString::fromUcs4(x, PyUnicode_GetLength(val)); + PyMem_Free(x); +#else PyObject *ptmp = PyUnicode_AsUTF8String(val); if(ptmp) { r = QString::fromUtf8(PyString_AS_STRING(ptmp)); Py_DECREF(ptmp); } +#endif } else if (!strict) { // EXTRA: could also use _Unicode, but why should we? PyObject* str = PyObject_Str(val); if (str) { +#ifdef PY3K + Py_UCS4 *x = PyUnicode_AsUCS4Copy(str); + r = QString::fromUcs4(x, PyUnicode_GetLength(str)); + PyMem_Free(x); +#else r = QString(PyString_AS_STRING(str)); +#endif Py_DECREF(str); } else { ok = false; @@ -739,9 +778,14 @@ QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) // TODO: support buffer objects in general QByteArray r; ok = true; - if (val->ob_type == &PyString_Type) { +#ifdef PY3K + if (PyBytes_Check(val)) { + r = QByteArray(PyBytes_AS_STRING(val), PyBytes_GET_SIZE(val)); +#else + if (Py_TYPE(val) == &PyString_Type) { long size = PyString_GET_SIZE(val); r = QByteArray(PyString_AS_STRING(val), size); +#endif } else { ok = false; } @@ -769,17 +813,25 @@ bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) { int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) { int d = 0; ok = true; +#ifndef PY3K if (val->ob_type == &PyInt_Type) { d = PyInt_AS_LONG(val); + } else +#endif + if (Py_TYPE(val) == &PyLong_Type) { + // handle error on overflow! + d = PyLong_AsLong(val); } else if (!strict) { +#ifndef PY3K if (PyObject_TypeCheck(val, &PyInt_Type)) { // support for derived int classes, e.g. for our enums d = PyInt_AS_LONG(val); - } else if (val->ob_type == &PyFloat_Type) { - d = floor(PyFloat_AS_DOUBLE(val)); - } else if (val->ob_type == &PyLong_Type) { - // handle error on overflow! + } else +#endif + if (PyObject_TypeCheck(val, &PyLong_Type)) { d = PyLong_AsLong(val); + } else if (Py_TYPE(val) == &PyFloat_Type) { + d = floor(PyFloat_AS_DOUBLE(val)); } else if (val == Py_False) { d = 0; } else if (val == Py_True) { @@ -787,7 +839,7 @@ int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) { } else { PyErr_Clear(); // PyInt_AsLong will try conversion to an int if the object is not an int: - d = PyInt_AsLong(val); + d = PyLong_AsLong(val); if (PyErr_Occurred()) { ok = false; PyErr_Clear(); @@ -802,15 +854,23 @@ int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) { qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) { qint64 d = 0; ok = true; +#ifndef PY3K if (val->ob_type == &PyInt_Type) { d = PyInt_AS_LONG(val); - } else if (val->ob_type == &PyLong_Type) { + } else +#endif + if (Py_TYPE(val) == &PyLong_Type) { d = PyLong_AsLongLong(val); } else if (!strict) { +#ifndef PY3K if (PyObject_TypeCheck(val, &PyInt_Type)) { // support for derived int classes, e.g. for our enums d = PyInt_AS_LONG(val); - } else if (val->ob_type == &PyFloat_Type) { + } else +#endif + if (PyObject_TypeCheck(val, &PyLong_Type)) { + d = PyLong_AsLong(val); + } else if (Py_TYPE(val) == &PyFloat_Type) { d = floor(PyFloat_AS_DOUBLE(val)); } else if (val == Py_False) { d = 0; @@ -834,15 +894,23 @@ qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) { quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) { quint64 d = 0; ok = true; - if (PyObject_TypeCheck(val, &PyInt_Type)) { +#ifndef PY3K + if (Py_TYPE(val) == &PyInt_Type) { d = PyInt_AS_LONG(val); - } else if (val->ob_type == &PyLong_Type) { + } else +#endif + if (Py_TYPE(val) == &PyLong_Type) { d = PyLong_AsLongLong(val); } else if (!strict) { +#ifndef PY3K if (PyObject_TypeCheck(val, &PyInt_Type)) { // support for derived int classes, e.g. for our enums d = PyInt_AS_LONG(val); - } else if (val->ob_type == &PyFloat_Type) { + } else +#endif + if (PyObject_TypeCheck(val, &PyLong_Type)) { + d = PyLong_AsLong(val); + } else if (Py_TYPE(val) == &PyFloat_Type) { d = floor(PyFloat_AS_DOUBLE(val)); } else if (val == Py_False) { d = 0; @@ -869,9 +937,12 @@ double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) { if (val->ob_type == &PyFloat_Type) { d = PyFloat_AS_DOUBLE(val); } else if (!strict) { +#ifndef PY3K if (PyObject_TypeCheck(val, &PyInt_Type)) { d = PyInt_AS_LONG(val); - } else if (val->ob_type == &PyLong_Type) { + } else +#endif + if (PyLong_Check(val)) { d = PyLong_AsLong(val); } else if (val == Py_False) { d = 0; @@ -899,15 +970,23 @@ QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type) if (type==-1) { // no special type requested +#ifdef PY3K + if (PyBytes_Check(val)) { + type = QVariant::ByteArray; + } else if (PyUnicode_Check(val)) { +#else if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) { +#endif type = QVariant::String; } else if (val == Py_False || val == Py_True) { type = QVariant::Bool; +#ifndef PY3K } else if (PyObject_TypeCheck(val, &PyInt_Type)) { type = QVariant::Int; - } else if (val->ob_type==&PyLong_Type) { +#endif + } else if (PyLong_Check(val)) { type = QVariant::LongLong; - } else if (val->ob_type==&PyFloat_Type) { + } else if (PyFloat_Check(val)) { type = QVariant::Double; } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) { PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val; @@ -928,9 +1007,9 @@ QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type) v = qVariantFromValue(myObject); } return v; - } else if (val->ob_type==&PyDict_Type) { + } else if (PyDict_Check(val)) { type = QVariant::Map; - } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) { + } else if (PyList_Check(val) || PyTuple_Check(val) || PySequence_Check(val)) { type = QVariant::List; } else if (val == Py_None) { // none is invalid @@ -1100,7 +1179,11 @@ QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type) PyObject* PythonQtConv::QStringToPyObject(const QString& str) { if (str.isNull()) { +#ifdef PY3K + return PyUnicode_New(0, 0); +#else return PyString_FromString(""); +#endif } else { return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL); } diff --git a/src/PythonQtImporter.cpp b/src/PythonQtImporter.cpp index 2fc2459..61d69f2 100644 --- a/src/PythonQtImporter.cpp +++ b/src/PythonQtImporter.cpp @@ -51,6 +51,10 @@ #include #include +#if PY_MAJOR_VERSION >= 3 +#define PY3K +#endif + #define IS_SOURCE 0x0 #define IS_BYTECODE 0x1 #define IS_PACKAGE 0x2 @@ -159,7 +163,7 @@ PythonQtImporter_dealloc(PythonQtImporter *self) // free the stored path if (self->_path) delete self->_path; // free ourself - self->ob_type->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free((PyObject *)self); } @@ -230,7 +234,11 @@ PythonQtImporter_load_module(PyObject *obj, PyObject *args) QString subname = info.moduleName; int err; +#ifdef PY3K + fullpath = PyUnicode_FromFormat("%s%c%s", +#else fullpath = PyString_FromFormat("%s%c%s", +#endif self->_path->toLatin1().constData(), SEP, subname.toLatin1().constData()); @@ -400,8 +408,7 @@ Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or i #define DEFERRED_ADDRESS(ADDR) 0 PyTypeObject PythonQtImporter_Type = { - PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type)) - 0, + PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) "PythonQtImport.PythonQtImporter", sizeof(PythonQtImporter), 0, /* tp_itemsize */ @@ -766,6 +773,20 @@ PyObject* PythonQtImport::getCodeFromPyc(const QString& file) PyDoc_STRVAR(mlabimport_doc, "Imports python files into PythonQt, completely replaces internal python import"); +#ifdef PY3K +static struct PyModuleDef PythonQtImport_def = { + PyModuleDef_HEAD_INIT, + "PythonQtImport", /* m_name */ + mlabimport_doc, /* m_doc */ + -1, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif + void PythonQtImport::init() { static bool first = true; @@ -794,8 +815,12 @@ void PythonQtImport::init() mlab_searchorder[4] = tmp; } +#ifdef PY3K + mod = PyModule_Create(&PythonQtImport_def); +#else mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc, NULL, PYTHON_API_VERSION); +#endif PythonQtImportError = PyErr_NewException(const_cast("PythonQtImport.PythonQtImportError"), PyExc_ImportError, NULL); diff --git a/src/PythonQtInstanceWrapper.cpp b/src/PythonQtInstanceWrapper.cpp index 3ca7bd0..45983f1 100644 --- a/src/PythonQtInstanceWrapper.cpp +++ b/src/PythonQtInstanceWrapper.cpp @@ -48,10 +48,14 @@ #include "PythonQtConversion.h" #include "PythonQtClassWrapper.h" +#if PY_MAJOR_VERSION >= 3 +#define PY3K +#endif + PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo() { // take the class info from our type object - return ((PythonQtClassWrapper*)ob_type)->_classInfo; + return ((PythonQtClassWrapper*)Py_TYPE(this))->_classInfo; } static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) { @@ -112,7 +116,7 @@ static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self) { PythonQtInstanceWrapper_deleteObject(self); self->_obj.~QPointer(); - self->ob_type->tp_free((PyObject*)self); + Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/) @@ -286,7 +290,11 @@ static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wr static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj) { - return PyString_FromString(obj->ob_type->tp_name); +#ifdef PY3K + return PyUnicode_FromString(Py_TYPE(obj)->tp_name); +#else + return PyString_FromString(Py_TYPE(obj)->tp_name); +#endif } PyObject *PythonQtInstanceWrapper_inherits(PythonQtInstanceWrapper* obj, PyObject *args) @@ -333,7 +341,11 @@ static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name) const char *attributeName; PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj; +#ifdef PY3K + if ((attributeName = PyUnicode_AsUTF8(name)) == NULL) { +#else if ((attributeName = PyString_AsString(name)) == NULL) { +#endif return NULL; } @@ -455,7 +467,11 @@ static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name) } // look for the internal methods (className(), help()) +#ifdef PY3K + PyObject* internalMethod = PyObject_GenericGetAttr(obj, name); +#else PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName); +#endif if (internalMethod) { return internalMethod; } @@ -483,7 +499,11 @@ static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec const char *attributeName; PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj; +#ifdef PY3K + if ((attributeName = PyUnicode_AsUTF8(name)) == NULL) +#else if ((attributeName = PyString_AsString(name)) == NULL) +#endif return -1; PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName); @@ -619,9 +639,17 @@ static PyObject * PythonQtInstanceWrapper_str(PyObject * obj) if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) { QByteArray* b = (QByteArray*) wrapper->_wrappedPtr; if (b->data()) { +#ifdef PY3K + return PyUnicode_FromStringAndSize(b->data(), b->size()); +#else return PyString_FromStringAndSize(b->data(), b->size()); +#endif } else { +#ifdef PY3K + return PyUnicode_New(0, 0); +#else return PyString_FromString(""); +#endif } } @@ -629,16 +657,32 @@ static PyObject * PythonQtInstanceWrapper_str(PyObject * obj) QObject *qobj = wrapper->_obj; QString str = getStringFromObject(wrapper); if (!str.isEmpty()) { +#ifdef PY3K + return PyUnicode_FromFormat("%s", str.toLatin1().constData()); +#else return PyString_FromFormat("%s", str.toLatin1().constData()); +#endif } if (wrapper->_wrappedPtr) { if (wrapper->_obj) { - return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj); +#ifdef PY3K + return PyUnicode_FromFormat("%s (C++ Object %p wrapped by %s %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj); +#else + return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj); +#endif } else { +#ifdef PY3K + return PyUnicode_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr); +#else return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr); +#endif } } else { +#ifdef PY3K + return PyUnicode_FromFormat("%s (QObject %p)", typeName, qobj); +#else return PyString_FromFormat("%s (QObject %p)", typeName, qobj); +#endif } } @@ -651,19 +695,39 @@ static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj) QString str = getStringFromObject(wrapper); if (!str.isEmpty()) { if (str.startsWith(typeName)) { +#ifdef PY3K + return PyUnicode_FromFormat("%s", str.toLatin1().constData()); +#else return PyString_FromFormat("%s", str.toLatin1().constData()); +#endif } else { +#ifdef PY3K + return PyUnicode_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj); +#else return PyString_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj); +#endif } } if (wrapper->_wrappedPtr) { if (wrapper->_obj) { +#ifdef PY3K + return PyUnicode_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj); +#else return PyString_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj); +#endif } else { +#ifdef PY3K + return PyUnicode_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr); +#else return PyString_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr); +#endif } } else { +#ifdef PY3K + return PyUnicode_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj); +#else return PyString_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj); +#endif } } @@ -691,30 +755,38 @@ static PyNumberMethods PythonQtInstanceWrapper_as_number = { 0, /* nb_add */ 0, /* nb_subtract */ 0, /* nb_multiply */ +#ifndef PY3K 0, /* nb_divide */ +#endif 0, /* nb_remainder */ 0, /* nb_divmod */ 0, /* nb_power */ 0, /* nb_negative */ 0, /* nb_positive */ 0, /* nb_absolute */ - PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */ + PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero / nb_bool in Py3K */ 0, /* nb_invert */ 0, /* nb_lshift */ 0, /* nb_rshift */ 0, /* nb_and */ 0, /* nb_xor */ 0, /* nb_or */ +#ifndef PY3K 0, /* nb_coerce */ +#endif 0, /* nb_int */ - 0, /* nb_long */ + 0, /* nb_long / nb_reserved in Py3K */ 0, /* nb_float */ +#ifndef PY3K 0, /* nb_oct */ 0, /* nb_hex */ +#endif 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ +#ifndef PY3K 0, /* nb_inplace_divide */ +#endif 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ @@ -726,11 +798,13 @@ static PyNumberMethods PythonQtInstanceWrapper_as_number = { 0, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ +#ifdef PY3K + 0, /* nb_index in Py3K */ +#endif }; PyTypeObject PythonQtInstanceWrapper_Type = { - PyObject_HEAD_INIT(&PythonQtClassWrapper_Type) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(&PythonQtClassWrapper_Type, 0) "PythonQt.PythonQtInstanceWrapper", /*tp_name*/ sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -749,7 +823,7 @@ PyTypeObject PythonQtInstanceWrapper_Type = { PythonQtInstanceWrapper_getattro, /*tp_getattro*/ PythonQtInstanceWrapper_setattro, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE /*| Py_TPFLAGS_CHECKTYPES FIXME Py_TPFLAGS_CHECKTYPES removal */, /*tp_flags*/ "PythonQtInstanceWrapper object", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ diff --git a/src/PythonQtPythonInclude.h b/src/PythonQtPythonInclude.h index e443324..bab5890 100644 --- a/src/PythonQtPythonInclude.h +++ b/src/PythonQtPythonInclude.h @@ -38,6 +38,12 @@ #undef _POSIX_THREADS #undef _XOPEN_SOURCE +// Undefine Qt keywords that conflict with Python headers +#ifdef slots +#undef slots +#define PYTHONQT_RESTORE_KEYWORDS +#endif + // If PYTHONQT_USE_RELEASE_PYTHON_FALLBACK is enabled, try to link // release Python DLL if it is available by undefining _DEBUG while // including Python.h @@ -53,4 +59,14 @@ #include #endif +// get Qt keywords back +#ifdef PYTHONQT_RESTORE_KEYWORDS +#define slots Q_SLOTS +#undef PYTHONQT_RESTORE_KEYWORDS +#endif + +#if PY_MAJOR_VERSION >= 3 +#define PY3K +#endif + #endif diff --git a/src/PythonQtSignal.cpp b/src/PythonQtSignal.cpp index d77b839..4cc39ec 100644 --- a/src/PythonQtSignal.cpp +++ b/src/PythonQtSignal.cpp @@ -110,10 +110,18 @@ static PyObject * meth_get__name__(PythonQtSignalFunctionObject *m, void * /*closure*/) { #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) ) +#ifdef PY3K + return PyUnicode_FromString(m->m_ml->metaMethod()->methodSignature()); +#else return PyString_FromString(m->m_ml->metaMethod()->methodSignature()); +#endif +#else +#ifdef PY3K + return PyUnicode_FromString(m->m_ml->metaMethod()->signature()); #else return PyString_FromString(m->m_ml->metaMethod()->signature()); #endif +#endif } static int @@ -137,11 +145,13 @@ static PyObject * meth_get__self__(PythonQtSignalFunctionObject *m, void * /*closure*/) { PyObject *self; +#ifndef PY3K if (PyEval_GetRestricted()) { PyErr_SetString(PyExc_RuntimeError, "method.__self__ not accessible in restricted mode"); return NULL; } +#endif self = m->m_self; if (self == NULL) self = Py_None; @@ -266,11 +276,19 @@ meth_repr(PythonQtSignalFunctionObject *f) { if (f->m_self->ob_type == &PythonQtClassWrapper_Type) { PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self; +#ifdef PY3K + return PyUnicode_FromFormat("", +#else return PyString_FromFormat("", +#endif f->m_ml->slotName().data(), self->classInfo()->className()); } else { +#ifdef PY3K + return PyUnicode_FromFormat("", +#else return PyString_FromFormat("", +#endif f->m_ml->slotName().data(), f->m_self->ob_type->tp_name, f->m_self); @@ -314,10 +332,32 @@ meth_hash(PythonQtSignalFunctionObject *a) return x; } +// for python 3.x +static PyObject* +meth_richcompare(PythonQtSignalFunctionObject *a, PythonQtSignalFunctionObject *b, int op) +{ + int x = meth_compare(a, b); + bool r; + if (op == Py_LT) + r = x < 0; + else if (op == Py_LE) + r = x < 1; + else if (op == Py_EQ) + r = x == 0; + else if (op == Py_NE) + r = x != 0; + else if (op == Py_GE) + r = x > -1; + else if (op == Py_GT) + r = x > 0; + if (r) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} PyTypeObject PythonQtSignalFunction_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, + PyVarObject_HEAD_INIT(&PyType_Type, 0) "builtin_qt_signal", sizeof(PythonQtSignalFunctionObject), 0, @@ -325,7 +365,11 @@ PyTypeObject PythonQtSignalFunction_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ +#ifdef PY3K + 0, +#else (cmpfunc)meth_compare, /* tp_compare */ +#endif (reprfunc)meth_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -341,7 +385,7 @@ PyTypeObject PythonQtSignalFunction_Type = { 0, /* tp_doc */ (traverseproc)meth_traverse, /* tp_traverse */ 0, /* tp_clear */ - 0, /* tp_richcompare */ + (richcmpfunc)meth_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ diff --git a/src/PythonQtSignalReceiver.cpp b/src/PythonQtSignalReceiver.cpp index 004e15a..789930c 100644 --- a/src/PythonQtSignalReceiver.cpp +++ b/src/PythonQtSignalReceiver.cpp @@ -138,7 +138,11 @@ PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInf bool PythonQtSignalTarget::isSame( int signalId, PyObject* callable ) const { +#ifdef PY3K + return PyObject_RichCompareBool(callable, _callable, Py_EQ) && signalId == _signalId; +#else return PyObject_Compare(callable, _callable) == 0 && signalId==_signalId; +#endif } //------------------------------------------------------------------------------ diff --git a/src/PythonQtSlot.cpp b/src/PythonQtSlot.cpp index ad67685..fc3d82f 100644 --- a/src/PythonQtSlot.cpp +++ b/src/PythonQtSlot.cpp @@ -52,6 +52,10 @@ #include +#if PY_MAJOR_VERSION >= 3 +#define PY3K +#endif + #define PYTHONQT_MAX_ARGS 32 @@ -192,7 +196,11 @@ bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObj hadException = true; QByteArray what("std::exception: "); what += e.what(); +#ifdef PY3K + PyErr_SetString(PyExc_RuntimeError, what.constData()); +#else PyErr_SetString(PyExc_StandardError, what.constData()); +#endif } } @@ -419,10 +427,18 @@ static PyObject * meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/) { #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) ) +#ifdef PY3K + return PyUnicode_FromString(m->m_ml->metaMethod()->methodSignature()); +#else return PyString_FromString(m->m_ml->metaMethod()->methodSignature()); +#endif +#else +#ifdef PY3K + return PyUnicode_FromString(m->m_ml->metaMethod()->signature()); #else return PyString_FromString(m->m_ml->metaMethod()->signature()); #endif +#endif } static int @@ -446,11 +462,13 @@ static PyObject * meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/) { PyObject *self; +#ifndef PY3K if (PyEval_GetRestricted()) { PyErr_SetString(PyExc_RuntimeError, "method.__self__ not accessible in restricted mode"); return NULL; } +#endif self = m->m_self; if (self == NULL) self = Py_None; @@ -505,7 +523,11 @@ PyObject *PythonQtMemberFunction_parameterTypes(PythonQtSlotInfo* theInfo) QList types = info->metaMethod()->parameterTypes(); PyObject* tuple = PyTuple_New(types.count()); for (int i = 0; inextInfo(); PyTuple_SET_ITEM(result, j, tuple); @@ -527,7 +549,11 @@ PyObject *PythonQtMemberFunction_parameterNames(PythonQtSlotInfo* theInfo) QList names = info->metaMethod()->parameterNames(); PyObject* tuple = PyTuple_New(names.count()); for (int i = 0; inextInfo(); PyTuple_SET_ITEM(result, j, tuple); @@ -547,7 +573,11 @@ PyObject *PythonQtMemberFunction_typeName(PythonQtSlotInfo* theInfo) PyObject* result = PyTuple_New(count); for (int j = 0;jmetaMethod()->typeName(); +#ifdef PY3K + PyTuple_SET_ITEM(result, j, PyUnicode_FromString(name.constData())); +#else PyTuple_SET_ITEM(result, j, PyString_FromString(name.constData())); +#endif info = info->nextInfo(); } return result; @@ -571,11 +601,19 @@ meth_repr(PythonQtSlotFunctionObject *f) { if (f->m_self->ob_type == &PythonQtClassWrapper_Type) { PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self; +#ifdef PY3K + return PyUnicode_FromFormat("", +#else return PyString_FromFormat("", +#endif f->m_ml->slotName().data(), self->classInfo()->className()); } else { +#ifdef PY3K + return PyUnicode_FromFormat("", +#endif f->m_ml->slotName().data(), f->m_self->ob_type->tp_name, f->m_self); @@ -619,10 +657,33 @@ meth_hash(PythonQtSlotFunctionObject *a) return x; } +// for python 3.x +static PyObject* +meth_richcompare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b, int op) +{ + int x = meth_compare(a, b); + bool r; + if (op == Py_LT) + r = x < 0; + else if (op == Py_LE) + r = x < 1; + else if (op == Py_EQ) + r = x == 0; + else if (op == Py_NE) + r = x != 0; + else if (op == Py_GE) + r = x > -1; + else if (op == Py_GT) + r = x > 0; + if (r) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + PyTypeObject PythonQtSlotFunction_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, + PyVarObject_HEAD_INIT(&PyType_Type, 0) "builtin_qt_slot", sizeof(PythonQtSlotFunctionObject), 0, @@ -630,7 +691,11 @@ PyTypeObject PythonQtSlotFunction_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ +#ifdef PY3K + 0, +#else (cmpfunc)meth_compare, /* tp_compare */ +#endif (reprfunc)meth_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -645,7 +710,7 @@ PyTypeObject PythonQtSlotFunction_Type = { 0, /* tp_doc */ (traverseproc)meth_traverse, /* tp_traverse */ 0, /* tp_clear */ - 0, /* tp_richcompare */ + (richcmpfunc)meth_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ diff --git a/src/PythonQtStdDecorators.cpp b/src/PythonQtStdDecorators.cpp index edf9800..a25a8a3 100644 --- a/src/PythonQtStdDecorators.cpp +++ b/src/PythonQtStdDecorators.cpp @@ -181,8 +181,13 @@ QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject(); } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) { meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject(); +#ifdef PY3K + } else if (PyUnicode_Check(type)) { + typeName = PyUnicode_AsUTF8(type); +#else } else if (PyString_Check(type)) { typeName = PyString_AsString(type); +#endif } if (!typeName && !meta) @@ -200,8 +205,13 @@ QList PythonQtStdDecorators::findChildren(QObject* parent, PyObject* t meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject(); } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) { meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject(); +#ifdef PY3K + } else if (PyUnicode_Check(type)) { + typeName = PyUnicode_AsUTF8(type); +#else } else if (PyString_Check(type)) { typeName = PyString_AsString(type); +#endif } QList list; @@ -223,8 +233,13 @@ QList PythonQtStdDecorators::findChildren(QObject* parent, PyObject* t meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject(); } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) { meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject(); +#ifdef PY3K + } else if (PyUnicode_Check(type)) { + typeName = PyUnicode_AsUTF8(type); +#else } else if (PyString_Check(type)) { typeName = PyString_AsString(type); +#endif } QList list; @@ -324,4 +339,4 @@ int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, c const QMetaObject* PythonQtStdDecorators::metaObject( QObject* obj ) { return obj->metaObject(); -} \ No newline at end of file +} diff --git a/src/PythonQtStdIn.cpp b/src/PythonQtStdIn.cpp index 07d844d..bd8f652 100644 --- a/src/PythonQtStdIn.cpp +++ b/src/PythonQtStdIn.cpp @@ -76,8 +76,7 @@ static PyMemberDef PythonQtStdInRedirect_members[] = { }; PyTypeObject PythonQtStdInRedirectType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "PythonQtStdInRedirect", /*tp_name*/ sizeof(PythonQtStdInRedirect), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/src/PythonQtStdOut.cpp b/src/PythonQtStdOut.cpp index 4604541..60b5f4e 100644 --- a/src/PythonQtStdOut.cpp +++ b/src/PythonQtStdOut.cpp @@ -60,6 +60,11 @@ static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args) if (PyTuple_GET_SIZE(args)>=1) { PyObject* obj = PyTuple_GET_ITEM(args,0); if (PyUnicode_Check(obj)) { +#ifdef PY3K + Py_UCS4 *x = PyUnicode_AsUCS4Copy(obj); + output = QString::fromUcs4(x, PyUnicode_GetLength(obj)); + PyMem_Free(x); +#else PyObject *tmp = PyUnicode_AsUTF8String(obj); if(tmp) { output = QString::fromUtf8(PyString_AS_STRING(tmp)); @@ -67,6 +72,7 @@ static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args) } else { return NULL; } +#endif } else { char *string; if (!PyArg_ParseTuple(args, "s", &string)) { @@ -117,8 +123,7 @@ static PyMemberDef PythonQtStdOutRedirect_members[] = { }; PyTypeObject PythonQtStdOutRedirectType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT(NULL, 0) "PythonQtStdOutRedirect", /*tp_name*/ sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/ 0, /*tp_itemsize*/