Skip to content

Commit 1db8980

Browse files
committed
Lots of fixed. Draft
1 parent e53690b commit 1db8980

File tree

6 files changed

+124
-101
lines changed

6 files changed

+124
-101
lines changed

src/PythonQt.cpp

Lines changed: 104 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,16 @@ PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
435435
PythonQt::~PythonQt() {
436436
delete _p;
437437
_p = nullptr;
438+
439+
Py_DECREF(&PythonQtSlotFunction_Type);
440+
Py_DECREF(&PythonQtSignalFunction_Type);
441+
Py_DECREF(&PythonQtSlotDecorator_Type);
442+
Py_DECREF(&PythonQtProperty_Type);
443+
Py_DECREF(&PythonQtBoolResult_Type);
444+
Py_DECREF(&PythonQtClassWrapper_Type);
445+
Py_DECREF(&PythonQtInstanceWrapper_Type);
446+
Py_DECREF(&PythonQtStdOutRedirectType);
447+
Py_DECREF(&PythonQtStdInRedirectType);
438448
}
439449

440450
PythonQtPrivate::~PythonQtPrivate() {
@@ -446,7 +456,7 @@ PythonQtPrivate::~PythonQtPrivate() {
446456
}
447457

448458
PythonQtMethodInfo::cleanupCachedMethodInfos();
449-
PythonQtArgumentFrame::cleanupFreeList();
459+
PythonQtArgumentFrame::cleanupFreeList();
450460
}
451461

452462
void PythonQtPrivate::setTaskDoneCallback(const PythonQtObjectPtr & callable)
@@ -509,7 +519,9 @@ void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void *
509519

510520
// Backup original 'sys.stdin' if not yet done
511521
if( !PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") ) {
512-
PyObject_SetAttrString(sys.object(), "pythonqt_original_stdin", PyObject_GetAttrString(sys.object(), "stdin"));
522+
PyObject *_stdin = PyObject_GetAttrString(sys.object(), "stdin");
523+
PyObject_SetAttrString(sys.object(), "pythonqt_original_stdin", _stdin);
524+
Py_XDECREF(_stdin);
513525
}
514526

515527
in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, nullptr, nullptr);
@@ -526,15 +538,16 @@ void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void *
526538
void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
527539
{
528540
PythonQtObjectPtr sys;
541+
PythonQtObjectPtr _stdin;
529542
sys.setNewRef(PyImport_ImportModule("sys"));
530543

531544
if (enabled) {
532-
if( !PyObject_HasAttrString(sys.object(), "pythonqt_stdin") ) {
533-
PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_stdin"));
545+
if( PyObject_HasAttrString(sys.object(), "pythonqt_stdin") ) {
546+
_stdin.setNewRef(PyObject_GetAttrString(sys.object(), "pythonqt_stdin"));
534547
}
535548
} else {
536-
if( !PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") ) {
537-
PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_original_stdin"));
549+
if( PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") ) {
550+
_stdin.setNewRef(PyObject_GetAttrString(sys.object(), "pythonqt_original_stdin"));
538551
}
539552
}
540553
}
@@ -627,19 +640,20 @@ void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const
627640
PythonQtClassInfo* outerClassInfo = lookupClassInfoAndCreateIfNotPresent(outerClass);
628641
outerClassInfo->addNestedClass(info);
629642
} else {
630-
if (PyModule_AddObject(pack, info->className(), pyobj) == 0) {
631-
// since PyModule_AddObject steals the reference, we need a incref once more...
632-
Py_INCREF(pyobj);
643+
Py_INCREF(pyobj);
644+
if (PyModule_AddObject(pack, info->className(), pyobj)) {
645+
Py_DECREF(pyobj);
633646
}
634647
}
635648
if (!module && package && strncmp(package, "Qt", 2) == 0) {
649+
Py_INCREF(pyobj);
636650
// put all qt objects into Qt as well
637-
if (PyModule_AddObject(packageByName("Qt"), info->className(), pyobj) == 0) {
638-
// since PyModule_AddObject steals the reference, we need a incref once more...
639-
Py_INCREF(pyobj);
651+
if (PyModule_AddObject(packageByName("Qt"), info->className(), pyobj)) {
652+
Py_DECREF(pyobj);
640653
}
641654
}
642655
info->setPythonQtClassWrapper(pyobj);
656+
Py_DECREF(pyobj);
643657
}
644658

645659
PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
@@ -1001,17 +1015,21 @@ QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
10011015
QVariant result;
10021016
clearError();
10031017
if (pycode) {
1004-
PyObject* dict = nullptr;
1005-
PyObject* globals = nullptr;
1018+
PythonQtObjectPtr dict;
1019+
PythonQtObjectPtr globals;
10061020
if (PyModule_Check(object)) {
10071021
dict = PyModule_GetDict(object);
10081022
globals = dict;
10091023
} else if (PyDict_Check(object)) {
10101024
dict = object;
10111025
globals = dict;
10121026
} else {
1013-
dict = PyObject_GetAttrString(object, "__dict__");
1014-
globals = PyObject_GetAttrString(PyImport_ImportModule(PyString_AS_STRING(PyObject_GetAttrString(object, "__module__"))),"__dict__");
1027+
PyObject *moduleName = PyObject_GetAttrString(object, "__module__");
1028+
PyObject *module = PyImport_ImportModule(PyString_AS_STRING(moduleName));
1029+
dict.setNewRef(PyObject_GetAttrString(object, "__dict__"));
1030+
globals.setNewRef(PyObject_GetAttrString(module, "__dict__"));
1031+
Py_XDECREF(moduleName);
1032+
Py_XDECREF(module);
10151033
}
10161034
PyObject* r = nullptr;
10171035
if (dict) {
@@ -1156,30 +1174,30 @@ PythonQtObjectPtr PythonQt::createUniqueModule()
11561174

11571175
void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
11581176
{
1159-
if (PyModule_Check(object)) {
1160-
auto pyobj = _p->wrapQObject(qObject);
1161-
if (PyModule_AddObject(object, QStringToPythonCharPointer(name), pyobj) < 0) {
1162-
Py_DECREF(pyobj);
1177+
PyObject *wrappedObject = _p->wrapQObject(qObject);
1178+
if (PyModule_Check(object)) {
1179+
Py_XINCREF(wrappedObject);
1180+
PyModule_AddObject(object, QStringToPythonCharPointer(name), wrappedObject);
1181+
} else if (PyDict_Check(object)) {
1182+
PyDict_SetItemString(object, QStringToPythonCharPointer(name), wrappedObject);
1183+
} else {
1184+
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), wrappedObject);
11631185
}
1164-
} else if (PyDict_Check(object)) {
1165-
PyDict_SetItemString(object, QStringToPythonCharPointer(name), _p->wrapQObject(qObject));
1166-
} else {
1167-
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), _p->wrapQObject(qObject));
1168-
}
1186+
Py_XDECREF(wrappedObject);
11691187
}
11701188

11711189
void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
11721190
{
1173-
if (PyModule_Check(object)) {
1174-
auto pyobj = PythonQtConv::QVariantToPyObject(v);
1175-
if (PyModule_AddObject(object, QStringToPythonCharPointer(name), pyobj) < 0) {
1176-
Py_DECREF(pyobj);
1177-
}
1178-
} else if (PyDict_Check(object)) {
1179-
PyDict_SetItemString(object, QStringToPythonCharPointer(name), PythonQtConv::QVariantToPyObject(v));
1180-
} else {
1181-
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), PythonQtConv::QVariantToPyObject(v));
1182-
}
1191+
PyObject *value = PythonQtConv::QVariantToPyObject(v);
1192+
if (PyModule_Check(object)) {
1193+
Py_XINCREF(value);
1194+
PyModule_AddObject(object, QStringToPythonCharPointer(name), value);
1195+
} else if (PyDict_Check(object)) {
1196+
PyDict_SetItemString(object, QStringToPythonCharPointer(name), value);
1197+
} else {
1198+
PyObject_SetAttrString(object, QStringToPythonCharPointer(name), value);
1199+
}
1200+
Py_XDECREF(value);
11831201
}
11841202

11851203
void PythonQt::removeVariable(PyObject* object, const QString& name)
@@ -1221,7 +1239,7 @@ QStringList PythonQt::introspection(PyObject* module, const QString& objectname,
12211239
} else {
12221240
object = lookupObject(module, objectname);
12231241
if (!object && type == CallOverloads) {
1224-
PyObject* dict = lookupObject(module, "__builtins__");
1242+
PythonQtObjectPtr dict = lookupObject(module, "__builtins__");
12251243
if (dict) {
12261244
object = PyDict_GetItemString(dict, QStringToPythonCharPointer(objectname));
12271245
}
@@ -1273,38 +1291,36 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
12731291
}
12741292
}
12751293
} else {
1276-
PyObject* keys = nullptr;
1277-
bool isDict = false;
1278-
if (PyDict_Check(object)) {
1279-
keys = PyDict_Keys(object);
1280-
isDict = true;
1281-
} else {
1282-
#if defined(MEVISLAB) && !defined(PY3K)
1283-
int oldPy3kWarningFlag = Py_Py3kWarningFlag;
1284-
Py_Py3kWarningFlag = 0; // temporarily disable Python 3 warnings
1285-
keys = PyObject_Dir(object);
1286-
Py_Py3kWarningFlag = oldPy3kWarningFlag;
1287-
#else
1288-
keys = PyObject_Dir(object);
1289-
#endif
1294+
PythonQtObjectPtr keys;
1295+
bool isDict = false;
1296+
if (PyDict_Check(object)) {
1297+
keys.setNewRef(PyDict_Keys(object));
1298+
isDict = true;
1299+
} else {
1300+
#if defined(MEVISLAB) && !defined(PY3K)
1301+
int oldPy3kWarningFlag = Py_Py3kWarningFlag;
1302+
Py_Py3kWarningFlag = 0; // temporarily disable Python 3 warnings
1303+
keys.setNewRef(PyObject_Dir(object));
1304+
Py_Py3kWarningFlag = oldPy3kWarningFlag;
1305+
#else
1306+
keys.setNewRef(PyObject_Dir(object));
1307+
#endif
12901308
}
12911309
if (keys) {
12921310
int count = PyList_Size(keys);
1293-
PyObject* key;
1294-
PyObject* value;
1295-
QString keystr;
12961311
for (int i = 0;i<count;i++) {
1297-
key = PyList_GetItem(keys,i);
1298-
if (isDict) {
1299-
value = PyDict_GetItem(object, key);
1300-
Py_INCREF(value);
1301-
} else {
1302-
value = PyObject_GetAttr(object, key);
1303-
}
1304-
if (!value) continue;
1305-
keystr = PyString_AsString(key);
1306-
static const QString underscoreStr("__tmp");
1307-
if (!keystr.startsWith(underscoreStr)) {
1312+
PythonQtObjectPtr key = PyList_GetItem(keys,i);
1313+
PythonQtObjectPtr value;
1314+
if (isDict) {
1315+
value.setNewRef(PyDict_GetItem(object, key));
1316+
Py_INCREF(value);
1317+
} else {
1318+
value = PyObject_GetAttr(object, key);
1319+
}
1320+
if (!value) continue;
1321+
QString keystr = PyString_AsString(key);
1322+
static const QString underscoreStr("__tmp");
1323+
if (!keystr.startsWith(underscoreStr)) {
13081324
switch (type) {
13091325
case Anything:
13101326
results << keystr;
@@ -1347,9 +1363,7 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
13471363
std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
13481364
}
13491365
}
1350-
Py_DECREF(value);
13511366
}
1352-
Py_DECREF(keys);
13531367
}
13541368
}
13551369
PyErr_Clear();
@@ -1402,6 +1416,7 @@ QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
14021416
PyObject* typeObject = getObjectByType(typeName);
14031417
if (typeObject) {
14041418
object = PyObject_GetAttrString(typeObject, QStringToPythonCharPointer(memberName));
1419+
Py_DECREF(typeObject);
14051420
}
14061421
}
14071422
if (object) {
@@ -1473,6 +1488,7 @@ PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList
14731488
PyObject* arg = PythonQtConv::QVariantToPyObject(it.value());
14741489
if (arg) {
14751490
PyDict_SetItemString(pkwargs, QStringToPythonCharPointer(it.key()), arg);
1491+
Py_DECREF(arg);
14761492
} else {
14771493
err = true;
14781494
break;
@@ -1549,6 +1565,7 @@ PythonQtPrivate::PythonQtPrivate()
15491565
_systemExitExceptionHandlerEnabled = false;
15501566
_debugAPI = new PythonQtDebugAPI(this);
15511567
_configAPI = new PythonQtConfigAPI(this);
1568+
_qtSlotsName.setNewRef(PyString_FromString("_qtSlots"));
15521569
}
15531570

15541571
void PythonQtPrivate::setupSharedLibrarySuffixes()
@@ -1879,7 +1896,7 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ
18791896
}
18801897
#ifdef PY3K
18811898
PythonQtModuleDef.m_name = name.constData();
1882-
_p->_pythonQtModule = PyModule_Create(&PythonQtModuleDef);
1899+
_p->_pythonQtModule.setNewRef(PyModule_Create(&PythonQtModuleDef));
18831900
#else
18841901
_p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
18851902
#endif
@@ -1919,7 +1936,11 @@ void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQ
19191936
Py_XDECREF(old_module_names);
19201937

19211938
#ifdef PY3K
1922-
PyDict_SetItem(PyObject_GetAttrString(sys.object(), "modules"), PyUnicode_FromString(name.constData()), _p->_pythonQtModule.object());
1939+
PyObject *modules = PyObject_GetAttrString(sys.object(), "modules");
1940+
PyObject *nameObj = PyUnicode_FromString(name.constData());
1941+
PyDict_SetItem(modules, nameObj, _p->_pythonQtModule.object());
1942+
Py_XDECREF(modules);
1943+
Py_XDECREF(nameObj);
19231944
#endif
19241945
}
19251946

@@ -1939,8 +1960,9 @@ QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString&
19391960

19401961
QString PythonQt::getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName)
19411962
{
1942-
PythonQtObjectPtr typeObject = getObjectByType(typeName);
1943-
if (typeObject.isNull()) {
1963+
PythonQtObjectPtr typeObject;
1964+
typeObject.setNewRef(getObjectByType(typeName));
1965+
if (typeObject.isNull()) {
19441966
return "";
19451967
}
19461968
return getReturnTypeOfWrappedMethodHelper(typeObject, methodName, typeName + "." + methodName);
@@ -2237,8 +2259,7 @@ const QMetaObject* PythonQtPrivate::buildDynamicMetaObject(PythonQtClassWrapper*
22372259
PyObject* dict = ((PyTypeObject*)type)->tp_dict;
22382260
Py_ssize_t pos = 0;
22392261
PyObject* value = nullptr;
2240-
PyObject* key = nullptr;
2241-
static PyObject* qtSlots = PyString_FromString("_qtSlots");
2262+
PyObject* key = nullptr;
22422263

22432264
bool needsMetaObject = false;
22442265
// Iterate over all members and check if they affect the QMetaObject:
@@ -2288,12 +2309,13 @@ const QMetaObject* PythonQtPrivate::buildDynamicMetaObject(PythonQtClassWrapper*
22882309
}
22892310
}
22902311
}
2291-
if (PyFunction_Check(value) && PyObject_HasAttr(value, qtSlots)) {
2312+
if (PyFunction_Check(value) && PyObject_HasAttr(value, _qtSlotsName)) {
22922313
// A function which has a "_qtSlots" signature list, add the slots to the meta object
2293-
PyObject* signatures = PyObject_GetAttr(value, qtSlots);
2314+
PythonQtObjectPtr signatures;
2315+
signatures.setNewRef(PyObject_GetAttr(value, _qtSlotsName));
22942316
Py_ssize_t count = PyList_Size(signatures);
22952317
for (Py_ssize_t i = 0; i < count; i++) {
2296-
PyObject* signature = PyList_GET_ITEM(signatures, i);
2318+
PyObject* signature = PyList_GET_ITEM(signatures.object(), i);
22972319
QByteArray sig = PyString_AsString(signature);
22982320
// Split the return type and the rest of the signature,
22992321
// no spaces should be in the rest of the signature...
@@ -2339,9 +2361,11 @@ int PythonQtPrivate::handleMetaCall(QObject* object, PythonQtInstanceWrapper* wr
23392361
}
23402362
PythonQtProperty* prop = nullptr;
23412363
// Get directly from the Python class, since we don't want to get the value of the property
2342-
PyObject* maybeProp = PyBaseObject_Type.tp_getattro((PyObject*)wrapper, PyString_FromString(metaProp.name()));
2364+
PythonQtObjectPtr name, maybeProp;
2365+
name.setNewRef(PyString_FromString(metaProp.name()));
2366+
maybeProp.setNewRef(PyBaseObject_Type.tp_getattro((PyObject*)wrapper, name));
23432367
if (maybeProp && PythonQtProperty_Check(maybeProp)) {
2344-
prop = (PythonQtProperty*)maybeProp;
2368+
prop = (PythonQtProperty*)maybeProp.object();
23452369
} else {
23462370
return id - methodCount;
23472371
}
@@ -2396,17 +2420,15 @@ QString PythonQtPrivate::getSignature(PyObject* object)
23962420
PyMethodObject* method = nullptr;
23972421
PyFunctionObject* func = nullptr;
23982422

2399-
bool decrefMethod = false;
2400-
24012423
if (PythonQtUtils::isPythonClassType(object)) {
24022424
method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__");
2403-
decrefMethod = true;
24042425
} else if (object->ob_type == &PyFunction_Type) {
24052426
func = (PyFunctionObject*)object;
24062427
} else if (object->ob_type == &PyMethod_Type) {
24072428
method = (PyMethodObject*)object;
2429+
Py_XINCREF(method);
24082430
}
2409-
if (method) {
2431+
if (method) {
24102432
if (PyFunction_Check(method->im_func)) {
24112433
func = (PyFunctionObject*)method->im_func;
24122434
} else if (isMethodDescriptor((PyObject*)method)) {
@@ -2514,9 +2536,7 @@ QString PythonQtPrivate::getSignature(PyObject* object)
25142536
signature = funcName + "(" + signature + ")";
25152537
}
25162538

2517-
if (method && decrefMethod) {
2518-
Py_DECREF(method);
2519-
}
2539+
Py_XDECREF(method);
25202540
}
25212541

25222542
return signature;

src/PythonQt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
884884

885885
bool _hadError;
886886
bool _systemExitExceptionHandlerEnabled;
887+
PythonQtObjectPtr _qtSlotsName;
887888

888889
friend class PythonQt;
889890
};

0 commit comments

Comments
 (0)