Skip to content

Commit 9ace39e

Browse files
committed
fixed unicode code and filename support for Python 3
1 parent d5f861a commit 9ace39e

13 files changed

+168
-116
lines changed

src/PythonQt.cpp

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
830830
QByteArray b;
831831
for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
832832
prev = p;
833-
b = (*i).toLatin1();
833+
b = QStringToPythonEncoding(*i);
834834
if (PyDict_Check(p)) {
835835
p = PyDict_GetItemString(p, b.data());
836836
} else {
@@ -850,7 +850,7 @@ PythonQtObjectPtr PythonQt::getMainModule() {
850850
PythonQtObjectPtr PythonQt::importModule(const QString& name)
851851
{
852852
PythonQtObjectPtr mod;
853-
mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
853+
mod.setNewRef(PyImport_ImportModule(QStringToPythonCharPointer(name)));
854854
return mod;
855855
}
856856

@@ -903,7 +903,7 @@ QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start
903903
dict = object;
904904
}
905905
if (dict) {
906-
p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
906+
p.setNewRef(PyRun_String(QStringToPythonCharPointer(script), start, dict, dict));
907907
}
908908
if (p) {
909909
result = PythonQtConv::PyObjToQVariant(p);
@@ -920,7 +920,7 @@ QVariant PythonQt::evalScript(const QString& script, PyObject* globals, PyObject
920920
PythonQtObjectPtr p;
921921
clearError();
922922
if (globals) {
923-
p.setNewRef(PyRun_String(script.toLatin1().data(), start, globals, locals ? locals : globals));
923+
p.setNewRef(PyRun_String(QStringToPythonCharPointer(script), start, globals, locals ? locals : globals));
924924
if (p) {
925925
result = PythonQtConv::PyObjToQVariant(p);
926926
} else {
@@ -968,7 +968,7 @@ PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QS
968968
scriptCode = "\n";
969969
}
970970
PythonQtObjectPtr pycode;
971-
pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
971+
pycode.setNewRef(Py_CompileString(QStringToPythonCharPointer(scriptCode), "", Py_file_input));
972972
PythonQtObjectPtr module = _p->createModule(name, pycode);
973973
return module;
974974
}
@@ -983,31 +983,31 @@ PythonQtObjectPtr PythonQt::createUniqueModule()
983983
void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
984984
{
985985
if (PyModule_Check(object)) {
986-
PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
986+
PyModule_AddObject(object, QStringToPythonCharPointer(name), _p->wrapQObject(qObject));
987987
} else if (PyDict_Check(object)) {
988-
PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
988+
PyDict_SetItemString(object, QStringToPythonCharPointer(name), _p->wrapQObject(qObject));
989989
} else {
990-
PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
990+
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), _p->wrapQObject(qObject));
991991
}
992992
}
993993

994994
void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
995995
{
996996
if (PyModule_Check(object)) {
997-
PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
997+
PyModule_AddObject(object, QStringToPythonCharPointer(name), PythonQtConv::QVariantToPyObject(v));
998998
} else if (PyDict_Check(object)) {
999-
PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
999+
PyDict_SetItemString(object, QStringToPythonCharPointer(name), PythonQtConv::QVariantToPyObject(v));
10001000
} else {
1001-
PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
1001+
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), PythonQtConv::QVariantToPyObject(v));
10021002
}
10031003
}
10041004

10051005
void PythonQt::removeVariable(PyObject* object, const QString& name)
10061006
{
10071007
if (PyDict_Check(object)) {
1008-
PyDict_DelItemString(object, name.toLatin1().data());
1008+
PyDict_DelItemString(object, QStringToPythonCharPointer(name));
10091009
} else {
1010-
PyObject_DelAttrString(object, name.toLatin1().data());
1010+
PyObject_DelAttrString(object, QStringToPythonCharPointer(name));
10111011
}
10121012
}
10131013

@@ -1033,7 +1033,7 @@ QStringList PythonQt::introspection(PyObject* module, const QString& objectname,
10331033
if (!object && type == CallOverloads) {
10341034
PyObject* dict = lookupObject(module, "__builtins__");
10351035
if (dict) {
1036-
object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
1036+
object = PyDict_GetItemString(dict, QStringToPythonCharPointer(objectname));
10371037
}
10381038
}
10391039
}
@@ -1089,7 +1089,14 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
10891089
keys = PyDict_Keys(object);
10901090
isDict = true;
10911091
} else {
1092+
#if defined(MEVISLAB) && !defined(PY3K)
1093+
int oldPy3kWarningFlag = Py_Py3kWarningFlag;
1094+
Py_Py3kWarningFlag = 0; // temporarily disable Python 3 warnings
10921095
keys = PyObject_Dir(object);
1096+
Py_Py3kWarningFlag = oldPy3kWarningFlag;
1097+
#else
1098+
keys = PyObject_Dir(object);
1099+
#endif
10931100
}
10941101
if (keys) {
10951102
int count = PyList_Size(keys);
@@ -1170,15 +1177,15 @@ PyObject* PythonQt::getObjectByType(const QString& typeName)
11701177
QString moduleName = tmp.join(".");
11711178

11721179
PyObject* object = NULL;
1173-
PyObject* moduleObject = PyDict_GetItemString(modules, moduleName.toLatin1().constData());
1180+
PyObject* moduleObject = PyDict_GetItemString(modules, QStringToPythonCharPointer(moduleName));
11741181
if (moduleObject) {
1175-
object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
1182+
object = PyObject_GetAttrString(moduleObject, QStringToPythonCharPointer(simpleTypeName));
11761183
}
11771184

11781185
if (!object) {
11791186
moduleObject = PyDict_GetItemString(modules, "__builtin__");
11801187
if (moduleObject) {
1181-
object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
1188+
object = PyObject_GetAttrString(moduleObject, QStringToPythonCharPointer(simpleTypeName));
11821189
}
11831190
}
11841191

@@ -1202,7 +1209,7 @@ QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
12021209
}
12031210
PyObject* typeObject = getObjectByType(typeName);
12041211
if (typeObject) {
1205-
object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData());
1212+
object = PyObject_GetAttrString(typeObject, QStringToPythonCharPointer(memberName));
12061213
}
12071214
}
12081215
if (object) {
@@ -1272,7 +1279,7 @@ PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList
12721279
it.next();
12731280
PyObject* arg = PythonQtConv::QVariantToPyObject(it.value());
12741281
if (arg) {
1275-
PyDict_SetItemString(pkwargs, it.key().toLatin1().constData(), arg);
1282+
PyDict_SetItemString(pkwargs, QStringToPythonCharPointer(it.key()), arg);
12761283
} else {
12771284
err = true;
12781285
break;
@@ -1434,7 +1441,7 @@ void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
14341441
void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
14351442
{
14361443
Q_FOREACH(QString name, names) {
1437-
_knownQObjectClassNames.insert(name.toLatin1(), true);
1444+
_knownQObjectClassNames.insert(name.toUtf8(), true);
14381445
}
14391446
}
14401447

@@ -1602,7 +1609,7 @@ void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
16021609
void PythonQt::stdOutRedirectCB(const QString& str)
16031610
{
16041611
if (!PythonQt::self()) {
1605-
std::cout << str.toLatin1().data() << std::endl;
1612+
std::cout << QStringToPythonConstCharPointer(str) << std::endl;
16061613
return;
16071614
}
16081615
Q_EMIT PythonQt::self()->pythonStdOut(str);
@@ -1611,7 +1618,7 @@ void PythonQt::stdOutRedirectCB(const QString& str)
16111618
void PythonQt::stdErrRedirectCB(const QString& str)
16121619
{
16131620
if (!PythonQt::self()) {
1614-
std::cerr << str.toLatin1().data() << std::endl;
1621+
std::cerr << QStringToPythonConstCharPointer(str) << std::endl;
16151622
return;
16161623
}
16171624
Q_EMIT PythonQt::self()->pythonStdErr(str);
@@ -1727,9 +1734,9 @@ QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& va
17271734
{
17281735
PythonQtObjectPtr methodObject;
17291736
if (PyDict_Check(variableObject)) {
1730-
methodObject = PyDict_GetItemString(variableObject, methodName.toLatin1().constData());
1737+
methodObject = PyDict_GetItemString(variableObject, QStringToPythonConstCharPointer(methodName));
17311738
} else {
1732-
methodObject.setNewRef(PyObject_GetAttrString(variableObject, methodName.toLatin1().constData()));
1739+
methodObject.setNewRef(PyObject_GetAttrString(variableObject, QStringToPythonConstCharPointer(methodName)));
17331740
}
17341741
if (methodObject.isNull()) {
17351742
return "";
@@ -1754,7 +1761,7 @@ QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& va
17541761
// if the type is a known class info, then create the full type name, i.e. include the
17551762
// module name. For example, the slot may return a QDate, then this looks up the
17561763
// name _PythonQt.QtCore.QDate.
1757-
PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(type.toLatin1().constData());
1764+
PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(QStringToPythonConstCharPointer(type));
17581765
if (typeInfo && typeInfo->pythonQtClassWrapper()) {
17591766
PyObject* s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__module__");
17601767
Q_ASSERT(PyString_Check(s));
@@ -1851,7 +1858,7 @@ PyObject* PythonQtPrivate::packageByName(const char* name)
18511858
void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
18521859
{
18531860
QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1854-
PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1861+
PyErr_SetString(PyExc_AttributeError, QStringToPythonCharPointer(error));
18551862
PythonQt::self()->handleError();
18561863
}
18571864

@@ -1861,7 +1868,7 @@ PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
18611868
Q_EMIT pythonHelpRequest(QByteArray(info->className()));
18621869
return Py_BuildValue("");
18631870
} else {
1864-
return PyString_FromString(info->help().toLatin1().data());
1871+
return PyString_FromString(QStringToPythonCharPointer(info->help()));
18651872
}
18661873
}
18671874

@@ -1911,7 +1918,7 @@ PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* p
19111918
PythonQtObjectPtr result;
19121919
PythonQt::self()->clearError();
19131920
if (pycode) {
1914-
result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1921+
result.setNewRef(PyImport_ExecCodeModule(QStringToPythonCharPointer(name), pycode));
19151922
} else {
19161923
PythonQt::self()->handleError();
19171924
}
@@ -2306,7 +2313,7 @@ PyObject* PythonQtPrivate::wrapMemoryAsBuffer( const void* data, Py_ssize_t size
23062313
PyObject* PythonQtPrivate::wrapMemoryAsBuffer( void* data, Py_ssize_t size )
23072314
{
23082315
#ifdef PY3K
2309-
return PyMemoryView_FromMemory((char*)data, size, PyBUF_READ | PyBUF_WRITE);
2316+
return PyMemoryView_FromMemory((char*)data, size, PyBUF_WRITE);
23102317
#else
23112318
return PyBuffer_FromReadWriteMemory((char*)data, size);
23122319
#endif

src/PythonQt.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,17 @@ typedef QObject* PythonQtQObjectCreatorFunctionCB();
143143
//! helper template to create a derived QObject class
144144
template<class T> QObject* PythonQtCreateObject() { return new T(); };
145145

146+
//! Helper define to convert from QString to Python C-API
147+
#ifdef PY3K
148+
#define QStringToPythonConstCharPointer(arg) ((arg).toUtf8().constData())
149+
#define QStringToPythonCharPointer(arg) ((arg).toUtf8().data())
150+
#define QStringToPythonEncoding(arg) ((arg).toUtf8())
151+
#else
152+
#define QStringToPythonConstCharPointer(arg) ((arg).toLatin1().constData())
153+
#define QStringToPythonCharPointer(arg) ((arg).toLatin1().data())
154+
#define QStringToPythonEncoding(arg) ((arg).toLatin1())
155+
#endif
156+
146157
//! The main interface to the Python Qt binding, realized as a singleton
147158
/*!
148159
Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.

src/PythonQtClassInfo.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,11 +1024,11 @@ PyObject* PythonQtClassInfo::getPythonTypeForProperty( const QString& name )
10241024
PythonQtClassInfo* PythonQtClassInfo::getClassInfoForProperty( const QString& name )
10251025
{
10261026
QByteArray typeName;
1027-
PythonQtMemberInfo info = member(name.toLatin1().constData());
1027+
PythonQtMemberInfo info = member(QStringToPythonConstCharPointer(name));
10281028
if (info._type == PythonQtMemberInfo::Property) {
10291029
typeName = info._property.typeName();
10301030
} else {
1031-
info = member(QString("py_get_" + name).toLatin1().constData());
1031+
info = member(QStringToPythonConstCharPointer(QString("py_get_" + name)));
10321032
if (info._type == PythonQtMemberInfo::Slot) {
10331033
typeName = info._slot->parameters().at(0).name;
10341034
}

src/PythonQtClassWrapper.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ static PyObject* PythonQtInstanceWrapper_binaryfunc(PyObject* self, PyObject* ot
143143
// different objects on the right. Otherwise we would need to generate __radd__ etc. methods.
144144
if (!PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
145145
QString error = "Unsupported operation " + opName + "(" + self->ob_type->tp_name + ", " + other->ob_type->tp_name + ")";
146-
PyErr_SetString(PyExc_ArithmeticError, error.toLatin1().data());
146+
PyErr_SetString(PyExc_ArithmeticError, QStringToPythonCharPointer(error));
147147
return NULL;
148148
}
149149
PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
@@ -384,7 +384,7 @@ static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args,
384384

385385
static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
386386
{
387-
return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
387+
return PyString_FromString((QByteArray("Class_") + type->classInfo()->className()).constData());
388388
}
389389

390390
static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
@@ -474,9 +474,9 @@ static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
474474
// do not expose internal slots
475475
continue;
476476
}
477-
PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().constData());
477+
PyObject* o = PyObject_GetAttrString(obj, QStringToPythonConstCharPointer(name));
478478
if (o) {
479-
PyDict_SetItemString(dict, name.toLatin1().constData(), o);
479+
PyDict_SetItemString(dict, QStringToPythonConstCharPointer(name), o);
480480
Py_DECREF(o);
481481
} else {
482482
// we should not get here anymore, but ignore this anyways.
@@ -559,7 +559,7 @@ static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
559559
}
560560

561561
QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
562-
PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
562+
PyErr_SetString(PyExc_AttributeError, QStringToPythonConstCharPointer(error));
563563
return NULL;
564564
}
565565

src/PythonQtConversion.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -587,13 +587,12 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i
587587
case QMetaType::QByteArray:
588588
{
589589
QByteArray bytes = PyObjGetBytes(obj, strict, ok);
590-
#ifdef PY3K
591590
if (!ok && !strict) {
592591
// since Qt uses QByteArray in many places for identifier strings,
593-
// we need to allow implicit conversion from unicode as well:
592+
// we need to allow implicit conversion from unicode as well.
593+
// We allow that for both Python 2.x and 3.x to be compatible.
594594
bytes = PyObjGetString(obj, strict, ok).toUtf8();
595595
}
596-
#endif
597596
if (ok) {
598597
PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
599598
ptr = (void*)((QVariant*)ptr)->constData();
@@ -1528,7 +1527,7 @@ QByteArray PythonQtConv::getCPPTypeName(PyObject* type)
15281527
result = "void";
15291528
} else {
15301529
bool dummy;
1531-
result = QMetaObject::normalizedType(PyObjGetString(type, true, dummy).toLatin1());
1530+
result = QMetaObject::normalizedType(PyObjGetString(type, true, dummy).toUtf8());
15321531
}
15331532
return result;
15341533
}

0 commit comments

Comments
 (0)