aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2/libpyside
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside2/libpyside')
-rw-r--r--sources/pyside2/libpyside/CMakeLists.txt2
-rw-r--r--sources/pyside2/libpyside/dynamicqmetaobject.cpp10
-rw-r--r--sources/pyside2/libpyside/dynamicqmetaobject_p.h2
-rw-r--r--sources/pyside2/libpyside/globalreceiverv2.cpp2
-rw-r--r--sources/pyside2/libpyside/pyside.cpp52
-rw-r--r--sources/pyside2/libpyside/pyside.h1
-rw-r--r--sources/pyside2/libpyside/pysideclassinfo.cpp6
-rw-r--r--sources/pyside2/libpyside/pysideclassinfo_p.h2
-rw-r--r--sources/pyside2/libpyside/pysidemetafunction.cpp9
-rw-r--r--sources/pyside2/libpyside/pysideproperty.cpp47
-rw-r--r--sources/pyside2/libpyside/pysideqflags.cpp14
-rw-r--r--sources/pyside2/libpyside/pysidesignal.cpp38
-rw-r--r--sources/pyside2/libpyside/pysideslot.cpp9
-rw-r--r--sources/pyside2/libpyside/pysidestaticstrings.cpp59
-rw-r--r--sources/pyside2/libpyside/pysidestaticstrings.h56
-rw-r--r--sources/pyside2/libpyside/pysideweakref.cpp9
-rw-r--r--sources/pyside2/libpyside/signalmanager.cpp40
-rw-r--r--sources/pyside2/libpyside/signalmanager.h1
18 files changed, 290 insertions, 69 deletions
diff --git a/sources/pyside2/libpyside/CMakeLists.txt b/sources/pyside2/libpyside/CMakeLists.txt
index 7b8adfc84..7493a453a 100644
--- a/sources/pyside2/libpyside/CMakeLists.txt
+++ b/sources/pyside2/libpyside/CMakeLists.txt
@@ -53,6 +53,7 @@ set(libpyside_SRC
pysideqflags.cpp
pysideweakref.cpp
pyside.cpp
+ pysidestaticstrings.cpp
${DESTROYLISTENER_MOC}
)
@@ -130,6 +131,7 @@ set(libpyside_HEADERS
pysidemacros.h
signalmanager.h
pyside.h
+ pysidestaticstrings.h
pysidemetafunction.h
pysidesignal.h
pysideproperty.h
diff --git a/sources/pyside2/libpyside/dynamicqmetaobject.cpp b/sources/pyside2/libpyside/dynamicqmetaobject.cpp
index 857d242a2..dae9e2059 100644
--- a/sources/pyside2/libpyside/dynamicqmetaobject.cpp
+++ b/sources/pyside2/libpyside/dynamicqmetaobject.cpp
@@ -140,7 +140,8 @@ MetaObjectBuilder::MetaObjectBuilder(PyTypeObject *type, const QMetaObject *meta
MetaObjectBuilder::~MetaObjectBuilder()
{
- qDeleteAll(m_d->m_cachedMetaObjects);
+ for (auto *metaObject : m_d->m_cachedMetaObjects)
+ free(const_cast<QMetaObject*>(metaObject));
delete m_d->m_builder;
delete m_d;
}
@@ -413,6 +414,10 @@ const QMetaObject *MetaObjectBuilderPrivate::update()
if (!m_builder)
return m_baseObject;
if (m_cachedMetaObjects.empty() || m_dirty) {
+ // PYSIDE-803: The dirty branch needs to be protected by the GIL.
+ // This was moved from SignalManager::retrieveMetaObject to here,
+ // which is only the update in "return builder->update()".
+ Shiboken::GilState gil;
m_cachedMetaObjects.push_back(m_builder->toMetaObject());
checkMethodOrder(m_cachedMetaObjects.back());
m_dirty = false;
@@ -464,7 +469,8 @@ void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type)
if (Signal::checkType(value)) {
// Register signals.
auto data = reinterpret_cast<PySideSignal *>(value);
- data->data->signalName = Shiboken::String::toCString(key);
+ if (data->data->signalName.isEmpty())
+ data->data->signalName = Shiboken::String::toCString(key);
for (const auto &s : data->data->signatures) {
const auto sig = data->data->signalName + '(' + s.signature + ')';
if (m_baseObject->indexOfSignal(sig) == -1) {
diff --git a/sources/pyside2/libpyside/dynamicqmetaobject_p.h b/sources/pyside2/libpyside/dynamicqmetaobject_p.h
index 534be5825..9199630b7 100644
--- a/sources/pyside2/libpyside/dynamicqmetaobject_p.h
+++ b/sources/pyside2/libpyside/dynamicqmetaobject_p.h
@@ -45,8 +45,6 @@
#include <QtCore/QByteArray>
#include <QtCore/QMetaMethod>
-#define GLOBAL_RECEIVER_CLASS_NAME "__GlobalReceiver__"
-
struct PySideProperty;
namespace PySide
{
diff --git a/sources/pyside2/libpyside/globalreceiverv2.cpp b/sources/pyside2/libpyside/globalreceiverv2.cpp
index 84ec92687..0377f7697 100644
--- a/sources/pyside2/libpyside/globalreceiverv2.cpp
+++ b/sources/pyside2/libpyside/globalreceiverv2.cpp
@@ -187,7 +187,7 @@ DynamicSlotDataV2::~DynamicSlotDataV2()
GlobalReceiverV2::GlobalReceiverV2(PyObject *callback, SharedMap map) :
QObject(nullptr),
- m_metaObject(GLOBAL_RECEIVER_CLASS_NAME, &QObject::staticMetaObject),
+ m_metaObject("__GlobalReceiver__", &QObject::staticMetaObject),
m_sharedMap(std::move(map))
{
m_data = new DynamicSlotDataV2(callback, this);
diff --git a/sources/pyside2/libpyside/pyside.cpp b/sources/pyside2/libpyside/pyside.cpp
index 9ee20f461..e2b8708ce 100644
--- a/sources/pyside2/libpyside/pyside.cpp
+++ b/sources/pyside2/libpyside/pyside.cpp
@@ -45,6 +45,7 @@
#include "pysideproperty.h"
#include "pysidesignal.h"
#include "pysidesignal_p.h"
+#include "pysidestaticstrings.h"
#include "pysideslot_p.h"
#include "pysidemetafunction_p.h"
#include "pysidemetafunction.h"
@@ -57,6 +58,7 @@
#include <gilstate.h>
#include <sbkconverter.h>
#include <sbkstring.h>
+#include <sbkstaticstrings.h>
#include <qapp_macro.h>
#include <QtCore/QByteArray>
@@ -92,6 +94,7 @@ void init(PyObject *module)
MetaFunction::init(module);
// Init signal manager, so it will register some meta types used by QVariant.
SignalManager::instance();
+ initQApp();
}
static bool _setProperty(PyObject *qObj, PyObject *name, PyObject *value, bool *accept)
@@ -147,7 +150,8 @@ bool fillQtProperties(PyObject *qObj, const QMetaObject *metaObj, PyObject *kwds
return false;
}
if (!accept) {
- PyErr_Format(PyExc_AttributeError, "'%S' is not a Qt property or a signal", key);
+ PyErr_Format(PyExc_AttributeError, "'%s' is not a Qt property or a signal",
+ propName.constData());
return false;
}
}
@@ -211,7 +215,7 @@ void destroyQCoreApplication()
delete app;
Py_END_ALLOW_THREADS
// PYSIDE-571: make sure to create a singleton deleted qApp.
- MakeSingletonQAppWrapper(NULL);
+ Py_DECREF(MakeQAppWrapper(nullptr));
}
std::size_t getSizeOfQObject(SbkObjectType *type)
@@ -233,7 +237,8 @@ void initDynamicMetaObject(SbkObjectType *type, const QMetaObject *base, std::si
if (!converter)
return;
Shiboken::AutoDecRef pyMetaObject(Shiboken::Conversions::pointerToPython(converter, metaObjectPtr));
- PyObject_SetAttrString(reinterpret_cast<PyObject *>(type), "staticMetaObject", pyMetaObject);
+ PyObject_SetAttr(reinterpret_cast<PyObject *>(type),
+ PySide::PyName::qtStaticMetaObject(), pyMetaObject);
}
TypeUserData *retrieveTypeUserData(SbkObjectType *sbkTypeObj)
@@ -295,6 +300,23 @@ void initQObjectSubType(SbkObjectType *type, PyObject *args, PyObject * /* kwds
initDynamicMetaObject(type, userData->mo.update(), userData->cppObjSize);
}
+void initQApp()
+{
+ /*
+ * qApp will not be initialized when embedding is active.
+ * That means that qApp exists already when PySide is initialized.
+ * We could solve that by creating a qApp variable, but in embedded
+ * mode, we also have the effect that the first assignment to qApp
+ * is persistent! Therefore, we can never be sure to have created
+ * qApp late enough to get the right type for the instance.
+ *
+ * I would appreciate very much if someone could explain or even fix
+ * this issue. It exists only when a pre-existing application exists.
+ */
+ if (!qApp)
+ Py_DECREF(MakeQAppWrapper(nullptr));
+}
+
PyObject *getMetaDataFromQObject(QObject *cppSelf, PyObject *self, PyObject *name)
{
PyObject *attr = PyObject_GenericGetAttr(self, name);
@@ -306,7 +328,6 @@ PyObject *getMetaDataFromQObject(QObject *cppSelf, PyObject *self, PyObject *nam
Py_DECREF(attr);
if (!value)
return 0;
- Py_INCREF(value);
attr = value;
}
@@ -397,6 +418,24 @@ static void invalidatePtr(any_t *object)
static const char invalidatePropertyName[] = "_PySideInvalidatePtr";
+// PYSIDE-1214, when creating new wrappers for classes inheriting QObject but
+// not exposed to Python, try to find the best-matching (most-derived) Qt
+// class by walking up the meta objects.
+static const char *typeName(QObject *cppSelf)
+{
+ const char *typeName = typeid(*cppSelf).name();
+ if (!Shiboken::Conversions::getConverter(typeName)) {
+ for (auto metaObject = cppSelf->metaObject(); metaObject; metaObject = metaObject->superClass()) {
+ const char *name = metaObject->className();
+ if (Shiboken::Conversions::getConverter(name)) {
+ typeName = name;
+ break;
+ }
+ }
+ }
+ return typeName;
+}
+
PyObject *getWrapperForQObject(QObject *cppSelf, SbkObjectType *sbk_type)
{
PyObject *pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppSelf));
@@ -419,8 +458,7 @@ PyObject *getWrapperForQObject(QObject *cppSelf, SbkObjectType *sbk_type)
}
}
- const char *typeName = typeid(*cppSelf).name();
- pyOut = Shiboken::Object::newObject(sbk_type, cppSelf, false, false, typeName);
+ pyOut = Shiboken::Object::newObject(sbk_type, cppSelf, false, false, typeName(cppSelf));
return pyOut;
}
@@ -539,7 +577,7 @@ bool registerInternalQtConf()
// Querying __file__ should be done only for modules that have finished their initialization.
// Thus querying for the top-level PySide2 package works for us whenever any Qt-wrapped module
// is loaded.
- PyObject *pysideInitFilePath = PyObject_GetAttrString(pysideModule, "__file__");
+ PyObject *pysideInitFilePath = PyObject_GetAttr(pysideModule, Shiboken::PyMagicName::file());
Py_DECREF(pysideModule);
if (!pysideInitFilePath)
return false;
diff --git a/sources/pyside2/libpyside/pyside.h b/sources/pyside2/libpyside/pyside.h
index 1529d79c9..ae400e1fe 100644
--- a/sources/pyside2/libpyside/pyside.h
+++ b/sources/pyside2/libpyside/pyside.h
@@ -103,6 +103,7 @@ PYSIDE_DEPRECATED(PYSIDE_API void initDynamicMetaObject(SbkObjectType *type, con
PYSIDE_API void initDynamicMetaObject(SbkObjectType *type, const QMetaObject *base,
std::size_t cppObjSize);
PYSIDE_API void initQObjectSubType(SbkObjectType *type, PyObject *args, PyObject *kwds);
+PYSIDE_API void initQApp();
/// Return the size in bytes of a type that inherits QObject.
PYSIDE_API std::size_t getSizeOfQObject(SbkObjectType *type);
diff --git a/sources/pyside2/libpyside/pysideclassinfo.cpp b/sources/pyside2/libpyside/pysideclassinfo.cpp
index fe5ca8765..375a31b57 100644
--- a/sources/pyside2/libpyside/pysideclassinfo.cpp
+++ b/sources/pyside2/libpyside/pysideclassinfo.cpp
@@ -60,11 +60,11 @@ static PyType_Slot PySideClassInfoType_slots[] = {
{Py_tp_init, (void *)classInfoTpInit},
{Py_tp_new, (void *)classInfoTpNew},
{Py_tp_free, (void *)classInfoFree},
- {Py_tp_dealloc, (void *)object_dealloc},
+ {Py_tp_dealloc, (void *)Sbk_object_dealloc},
{0, 0}
};
static PyType_Spec PySideClassInfoType_spec = {
- "PySide2.QtCore.ClassInfo",
+ "2:PySide2.QtCore.ClassInfo",
sizeof(PySideClassInfo),
0,
Py_TPFLAGS_DEFAULT,
@@ -75,7 +75,7 @@ static PyType_Spec PySideClassInfoType_spec = {
PyTypeObject *PySideClassInfoTypeF(void)
{
static PyTypeObject *type =
- reinterpret_cast<PyTypeObject *>(PyType_FromSpec(&PySideClassInfoType_spec));
+ reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideClassInfoType_spec));
return type;
}
diff --git a/sources/pyside2/libpyside/pysideclassinfo_p.h b/sources/pyside2/libpyside/pysideclassinfo_p.h
index c0038a71a..021aa58e9 100644
--- a/sources/pyside2/libpyside/pysideclassinfo_p.h
+++ b/sources/pyside2/libpyside/pysideclassinfo_p.h
@@ -44,8 +44,6 @@
#include <QMetaObject>
#include "pysideclassinfo.h"
-#define __INFO_ATTR_NAME__ "__classInfo__" // not used! ???
-
struct PySideClassInfo;
extern "C"
diff --git a/sources/pyside2/libpyside/pysidemetafunction.cpp b/sources/pyside2/libpyside/pysidemetafunction.cpp
index e0e0c439b..f4b95385a 100644
--- a/sources/pyside2/libpyside/pysidemetafunction.cpp
+++ b/sources/pyside2/libpyside/pysidemetafunction.cpp
@@ -62,11 +62,11 @@ static PyType_Slot PySideMetaFunctionType_slots[] = {
{Py_tp_call, (void *)functionCall},
{Py_tp_new, (void *)PyType_GenericNew},
{Py_tp_free, (void *)functionFree},
- {Py_tp_dealloc, (void *)object_dealloc},
+ {Py_tp_dealloc, (void *)Sbk_object_dealloc},
{0, 0}
};
static PyType_Spec PySideMetaFunctionType_spec = {
- "PySide2.QtCore.MetaFunction",
+ "2:PySide2.QtCore.MetaFunction",
sizeof(PySideMetaFunction),
0,
Py_TPFLAGS_DEFAULT,
@@ -76,9 +76,8 @@ static PyType_Spec PySideMetaFunctionType_spec = {
PyTypeObject *PySideMetaFunctionTypeF(void)
{
- static PyTypeObject *type = nullptr;
- if (!type)
- type = (PyTypeObject *)PyType_FromSpec(&PySideMetaFunctionType_spec);
+ static PyTypeObject *type = reinterpret_cast<PyTypeObject *>(
+ SbkType_FromSpec(&PySideMetaFunctionType_spec));
return type;
}
diff --git a/sources/pyside2/libpyside/pysideproperty.cpp b/sources/pyside2/libpyside/pysideproperty.cpp
index d9d15eb3b..77dc6f3fc 100644
--- a/sources/pyside2/libpyside/pysideproperty.cpp
+++ b/sources/pyside2/libpyside/pysideproperty.cpp
@@ -61,6 +61,9 @@ static PyObject *qPropertyGetter(PyObject *, PyObject *);
static int qpropertyTraverse(PyObject *self, visitproc visit, void *arg);
static int qpropertyClear(PyObject *self);
+// Attributes
+static PyObject *qPropertyDocGet(PyObject *, void *);
+
static PyMethodDef PySidePropertyMethods[] = {
{"setter", (PyCFunction)qPropertySetter, METH_O, 0},
{"write", (PyCFunction)qPropertySetter, METH_O, 0},
@@ -69,6 +72,11 @@ static PyMethodDef PySidePropertyMethods[] = {
{0, 0, 0, 0}
};
+static PyGetSetDef PySidePropertyType_getset[] = {
+ {"__doc__", qPropertyDocGet, nullptr, nullptr, nullptr},
+ {nullptr, nullptr, nullptr, nullptr, nullptr}
+};
+
static PyType_Slot PySidePropertyType_slots[] = {
{Py_tp_dealloc, (void *)qpropertyDeAlloc},
{Py_tp_call, (void *)qPropertyCall},
@@ -77,11 +85,12 @@ static PyType_Slot PySidePropertyType_slots[] = {
{Py_tp_methods, (void *)PySidePropertyMethods},
{Py_tp_init, (void *)qpropertyTpInit},
{Py_tp_new, (void *)qpropertyTpNew},
+ {Py_tp_getset, PySidePropertyType_getset},
{0, 0}
};
-// Dotted modulename is crucial for PyType_FromSpec to work. Is this name right?
+// Dotted modulename is crucial for SbkType_FromSpec to work. Is this name right?
static PyType_Spec PySidePropertyType_spec = {
- "PySide2.QtCore.Property",
+ "2:PySide2.QtCore.Property",
sizeof(PySideProperty),
0,
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE,
@@ -91,9 +100,8 @@ static PyType_Spec PySidePropertyType_spec = {
PyTypeObject *PySidePropertyTypeF(void)
{
- static PyTypeObject *type = nullptr;
- if (!type)
- type = (PyTypeObject *)PyType_FromSpec(&PySidePropertyType_spec);
+ static PyTypeObject *type = reinterpret_cast<PyTypeObject *>(
+ SbkType_FromSpec(&PySidePropertyType_spec));
return type;
}
@@ -177,12 +185,10 @@ int qpropertyTpInit(PyObject *self, PyObject *args, PyObject *kwds)
return -1;
}
- if (doc) {
+ if (doc)
pData->doc = doc;
- free(doc);
- } else {
+ else
pData->doc.clear();
- }
pData->typeName = PySide::Signal::getTypeName(type);
@@ -210,6 +216,11 @@ int qpropertyTpInit(PyObject *self, PyObject *args, PyObject *kwds)
void qpropertyDeAlloc(PyObject *self)
{
qpropertyClear(self);
+ if (PepRuntime_38_flag) {
+ // PYSIDE-939: Handling references correctly.
+ // This was not needed before Python 3.8 (Python issue 35810)
+ Py_DECREF(Py_TYPE(self));
+ }
Py_TYPE(self)->tp_free(self);
}
@@ -262,6 +273,24 @@ PyObject *qPropertyGetter(PyObject *self, PyObject *callback)
return nullptr;
}
+static PyObject *qPropertyDocGet(PyObject *self, void *)
+{
+ auto data = reinterpret_cast<PySideProperty *>(self);
+ PySidePropertyPrivate *pData = data->d;
+
+ QByteArray doc(pData->doc);
+ if (!doc.isEmpty()) {
+#if PY_MAJOR_VERSION >= 3
+ return PyUnicode_FromString(doc);
+#else
+ return PyString_FromString(doc);
+#endif
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
static int qpropertyTraverse(PyObject *self, visitproc visit, void *arg)
{
PySidePropertyPrivate *data = reinterpret_cast<PySideProperty *>(self)->d;
diff --git a/sources/pyside2/libpyside/pysideqflags.cpp b/sources/pyside2/libpyside/pysideqflags.cpp
index fd0ed005f..d7e6b4f4c 100644
--- a/sources/pyside2/libpyside/pysideqflags.cpp
+++ b/sources/pyside2/libpyside/pysideqflags.cpp
@@ -86,6 +86,11 @@ extern "C" {
return PyLong_AsLong(number);
}
+ static PyObject *qflag_int(PyObject *self)
+ {
+ return PyLong_FromLong(reinterpret_cast<PySideQFlagsObject*>(self)->ob_value);
+ }
+
PyObject *PySideQFlagsRichCompare(PyObject *self, PyObject *other, int op)
{
int result = 0;
@@ -146,13 +151,14 @@ namespace QFlags
{Py_nb_and, 0},
{Py_nb_xor, 0},
{Py_nb_or, 0},
- {Py_nb_int, 0},
+ {Py_nb_int, reinterpret_cast<void*>(qflag_int)},
+ {Py_nb_index, reinterpret_cast<void*>(qflag_int)},
#ifndef IS_PY3K
{Py_nb_long, 0},
#endif
{Py_tp_new, (void *)PySideQFlagsNew},
{Py_tp_richcompare, (void *)PySideQFlagsRichCompare},
- {Py_tp_dealloc, (void *)object_dealloc},
+ {Py_tp_dealloc, (void *)Sbk_object_dealloc},
{0, 0}
};
static PyType_Spec SbkNewQFlagsType_spec = {
@@ -168,7 +174,7 @@ namespace QFlags
char qualname[200];
// PYSIDE-747: Here we insert now the full class name.
strcpy(qualname, name);
- // Careful: PyType_FromSpec does not allocate the string.
+ // Careful: SbkType_FromSpec does not allocate the string.
PyType_Spec *newspec = new PyType_Spec;
newspec->name = strdup(qualname);
newspec->basicsize = SbkNewQFlagsType_spec.basicsize;
@@ -180,7 +186,7 @@ namespace QFlags
SbkNewQFlagsType_slots[idx].pfunc = numberMethods[idx].pfunc;
}
newspec->slots = SbkNewQFlagsType_spec.slots;
- PyTypeObject *type = (PyTypeObject *)PyType_FromSpec(newspec);
+ PyTypeObject *type = (PyTypeObject *)SbkType_FromSpec(newspec);
Py_TYPE(type) = &PyType_Type;
PySideQFlagsType *flagsType = reinterpret_cast<PySideQFlagsType *>(type);
diff --git a/sources/pyside2/libpyside/pysidesignal.cpp b/sources/pyside2/libpyside/pysidesignal.cpp
index a09c17a24..0fa33254c 100644
--- a/sources/pyside2/libpyside/pysidesignal.cpp
+++ b/sources/pyside2/libpyside/pysidesignal.cpp
@@ -40,6 +40,7 @@
#include <sbkpython.h>
#include "pysidesignal.h"
#include "pysidesignal_p.h"
+#include "pysidestaticstrings.h"
#include "signalmanager.h"
#include <shiboken.h>
@@ -53,6 +54,7 @@
#include <utility>
#define QT_SIGNAL_SENTINEL '2'
+#define PyEnumMeta_Check(x) (strcmp(Py_TYPE(arg)->tp_name, "EnumMeta") == 0)
namespace PySide {
namespace Signal {
@@ -109,13 +111,13 @@ static PyType_Slot PySideMetaSignalType_slots[] = {
{Py_tp_methods, (void *)MetaSignal_methods},
{Py_tp_base, (void *)&PyType_Type},
{Py_tp_free, (void *)PyObject_GC_Del},
- {Py_tp_dealloc, (void *)object_dealloc},
+ {Py_tp_dealloc, (void *)Sbk_object_dealloc},
{0, 0}
};
static PyType_Spec PySideMetaSignalType_spec = {
- "PySide2.QtCore.MetaSignal",
+ "2:PySide2.QtCore.MetaSignal",
0,
- // sizeof(PyHeapTypeObject) is filled in by PyType_FromSpecWithBases
+ // sizeof(PyHeapTypeObject) is filled in by SbkType_FromSpecWithBases
// which calls PyType_Ready which calls inherit_special.
0,
Py_TPFLAGS_DEFAULT,
@@ -128,7 +130,7 @@ PyTypeObject *PySideMetaSignalTypeF(void)
static PyTypeObject *type = nullptr;
if (!type) {
PyObject *bases = Py_BuildValue("(O)", &PyType_Type);
- type = (PyTypeObject *)PyType_FromSpecWithBases(&PySideMetaSignalType_spec, bases);
+ type = (PyTypeObject *)SbkType_FromSpecWithBases(&PySideMetaSignalType_spec, bases);
Py_XDECREF(bases);
}
return type;
@@ -141,11 +143,11 @@ static PyType_Slot PySideSignalType_slots[] = {
{Py_tp_init, (void *)signalTpInit},
{Py_tp_new, (void *)PyType_GenericNew},
{Py_tp_free, (void *)signalFree},
- {Py_tp_dealloc, (void *)object_dealloc},
+ {Py_tp_dealloc, (void *)Sbk_object_dealloc},
{0, 0}
};
static PyType_Spec PySideSignalType_spec = {
- "PySide2.QtCore.Signal",
+ "2:PySide2.QtCore.Signal",
sizeof(PySideSignal),
0,
Py_TPFLAGS_DEFAULT,
@@ -157,7 +159,7 @@ PyTypeObject *PySideSignalTypeF(void)
{
static PyTypeObject *type = nullptr;
if (!type) {
- type = (PyTypeObject *)PyType_FromSpec(&PySideSignalType_spec);
+ type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideSignalType_spec));
PyTypeObject *hold = Py_TYPE(type);
Py_TYPE(type) = PySideMetaSignalTypeF();
Py_INCREF(Py_TYPE(type));
@@ -180,11 +182,11 @@ static PyType_Slot PySideSignalInstanceType_slots[] = {
{Py_tp_methods, (void *)SignalInstance_methods},
{Py_tp_new, (void *)PyType_GenericNew},
{Py_tp_free, (void *)signalInstanceFree},
- {Py_tp_dealloc, (void *)object_dealloc},
+ {Py_tp_dealloc, (void *)Sbk_object_dealloc},
{0, 0}
};
static PyType_Spec PySideSignalInstanceType_spec = {
- "PySide2.QtCore.SignalInstance",
+ "2:PySide2.QtCore.SignalInstance",
sizeof(PySideSignalInstance),
0,
Py_TPFLAGS_DEFAULT,
@@ -195,7 +197,7 @@ static PyType_Spec PySideSignalInstanceType_spec = {
PyTypeObject *PySideSignalInstanceTypeF(void)
{
static PyTypeObject *type =
- (PyTypeObject *)PyType_FromSpec(&PySideSignalInstanceType_spec);
+ reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideSignalInstanceType_spec));
return type;
}
@@ -240,7 +242,7 @@ int signalTpInit(PyObject *self, PyObject *args, PyObject *kwds)
for (Py_ssize_t i = 0, i_max = PyTuple_Size(args); i < i_max; i++) {
PyObject *arg = PyTuple_GET_ITEM(args, i);
- if (PySequence_Check(arg) && !Shiboken::String::check(arg)) {
+ if (PySequence_Check(arg) && !Shiboken::String::check(arg) && !PyEnumMeta_Check(arg)) {
tupledArgs = true;
const auto sig = PySide::Signal::parseSignature(arg);
PySide::Signal::appendSignature(
@@ -412,7 +414,8 @@ PyObject *signalInstanceConnect(PyObject *self, PyObject *args, PyObject *kwds)
if (match) {
Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
- Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->d->source, "connect"));
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttr(source->d->source,
+ PySide::PyName::qtConnect()));
if (pyMethod.isNull()) { // PYSIDE-79: check if pyMethod exists.
PyErr_SetString(PyExc_RuntimeError, "method 'connect' vanished!");
return 0;
@@ -465,7 +468,8 @@ PyObject *signalInstanceEmit(PyObject *self, PyObject *args)
for (Py_ssize_t i = 0, max = PyTuple_Size(args); i < max; i++)
PyList_Append(pyArgs, PyTuple_GetItem(args, i));
- Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->d->source, "emit"));
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttr(source->d->source,
+ PySide::PyName::qtEmit()));
Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
return PyObject_CallObject(pyMethod, tupleArgs);
@@ -530,7 +534,8 @@ PyObject *signalInstanceDisconnect(PyObject *self, PyObject *args)
if (match) {
Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
- Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->d->source, "disconnect"));
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttr(source->d->source,
+ PySide::PyName::qtDisconnect()));
PyObject *result = PyObject_CallObject(pyMethod, tupleArgs);
if (!result || result == Py_True)
return result;
@@ -615,7 +620,7 @@ void init(PyObject *module)
{
if (SbkSpecial_Type_Ready(module, PySideMetaSignalTypeF(), MetaSignal_SignatureStrings) < 0)
return;
- Py_INCREF(PySideSignalTypeF());
+ Py_INCREF(PySideMetaSignalTypeF());
PyModule_AddObject(module, "MetaSignal", reinterpret_cast<PyObject *>(PySideMetaSignalTypeF()));
if (SbkSpecial_Type_Ready(module, PySideSignalTypeF(), Signal_SignatureStrings) < 0)
@@ -756,7 +761,8 @@ void instanceInitialize(PySideSignalInstance *self, PyObject *name, PySideSignal
bool connect(PyObject *source, const char *signal, PyObject *callback)
{
- Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source, "connect"));
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttr(source,
+ PySide::PyName::qtConnect()));
if (pyMethod.isNull())
return false;
diff --git a/sources/pyside2/libpyside/pysideslot.cpp b/sources/pyside2/libpyside/pysideslot.cpp
index 204253aa2..e60115450 100644
--- a/sources/pyside2/libpyside/pysideslot.cpp
+++ b/sources/pyside2/libpyside/pysideslot.cpp
@@ -71,11 +71,11 @@ static PyType_Slot PySideSlotType_slots[] = {
{Py_tp_call, (void *)slotCall},
{Py_tp_init, (void *)slotTpInit},
{Py_tp_new, (void *)PyType_GenericNew},
- {Py_tp_dealloc, (void *)object_dealloc},
+ {Py_tp_dealloc, (void *)Sbk_object_dealloc},
{0, 0}
};
static PyType_Spec PySideSlotType_spec = {
- "PySide2.QtCore.Slot",
+ "2:PySide2.QtCore.Slot",
sizeof(PySideSlot),
0,
Py_TPFLAGS_DEFAULT,
@@ -85,9 +85,8 @@ static PyType_Spec PySideSlotType_spec = {
static PyTypeObject *PySideSlotTypeF(void)
{
- static PyTypeObject *type = nullptr;
- if (!type)
- type = (PyTypeObject *)PyType_FromSpec(&PySideSlotType_spec);
+ static PyTypeObject *type = reinterpret_cast<PyTypeObject *>(
+ SbkType_FromSpec(&PySideSlotType_spec));
return type;
}
diff --git a/sources/pyside2/libpyside/pysidestaticstrings.cpp b/sources/pyside2/libpyside/pysidestaticstrings.cpp
new file mode 100644
index 000000000..82e233621
--- /dev/null
+++ b/sources/pyside2/libpyside/pysidestaticstrings.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pysidestaticstrings.h"
+#include <sbkstring.h>
+
+#define STATIC_STRING_IMPL(funcName, value) \
+PyObject *funcName() \
+{ \
+ static PyObject *const s = Shiboken::String::createStaticString(value); \
+ return s; \
+}
+
+namespace PySide
+{
+namespace PyName
+{
+STATIC_STRING_IMPL(qtStaticMetaObject, "staticMetaObject")
+STATIC_STRING_IMPL(qtConnect, "connect")
+STATIC_STRING_IMPL(qtDisconnect, "disconnect")
+STATIC_STRING_IMPL(qtEmit, "emit")
+} // namespace PyName
+} // namespace PySide
diff --git a/sources/pyside2/libpyside/pysidestaticstrings.h b/sources/pyside2/libpyside/pysidestaticstrings.h
new file mode 100644
index 000000000..1d5700c51
--- /dev/null
+++ b/sources/pyside2/libpyside/pysidestaticstrings.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYSIDESTRINGS_H
+#define PYSIDESTRINGS_H
+
+#include <sbkpython.h>
+
+namespace PySide
+{
+namespace PyName
+{
+PyObject *qtStaticMetaObject();
+PyObject *qtConnect();
+PyObject *qtDisconnect();
+PyObject *qtEmit();
+} // namespace PyName
+} // namespace PySide
+
+#endif // PYSIDESTRINGS_H
diff --git a/sources/pyside2/libpyside/pysideweakref.cpp b/sources/pyside2/libpyside/pysideweakref.cpp
index 2b27f9545..cd90634bd 100644
--- a/sources/pyside2/libpyside/pysideweakref.cpp
+++ b/sources/pyside2/libpyside/pysideweakref.cpp
@@ -53,11 +53,11 @@ static PyObject *CallableObject_call(PyObject *callable_object, PyObject *args,
static PyType_Slot PySideCallableObjectType_slots[] = {
{Py_tp_call, (void *)CallableObject_call},
- {Py_tp_dealloc, (void *)object_dealloc},
+ {Py_tp_dealloc, (void *)Sbk_object_dealloc},
{0, 0}
};
static PyType_Spec PySideCallableObjectType_spec = {
- const_cast<char *>("PySide.Callable"),
+ "1:PySide.Callable",
sizeof(PySideCallableObject),
0,
Py_TPFLAGS_DEFAULT,
@@ -68,7 +68,7 @@ static PyType_Spec PySideCallableObjectType_spec = {
static PyTypeObject *PySideCallableObjectTypeF()
{
static PyTypeObject *type =
- (PyTypeObject *)PyType_FromSpec(&PySideCallableObjectType_spec);
+ reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideCallableObjectType_spec));
return type;
}
@@ -94,7 +94,8 @@ PyObject *create(PyObject *obj, PySideWeakRefFunction func, void *userData)
PyType_Ready(PySideCallableObjectTypeF());
}
- PySideCallableObject *callable = PyObject_New(PySideCallableObject, PySideCallableObjectTypeF());
+ PyTypeObject *type = PySideCallableObjectTypeF();
+ PySideCallableObject *callable = PyObject_New(PySideCallableObject, type);
if (!callable || PyErr_Occurred())
return 0;
diff --git a/sources/pyside2/libpyside/signalmanager.cpp b/sources/pyside2/libpyside/signalmanager.cpp
index 0895cc682..8e8cc9f02 100644
--- a/sources/pyside2/libpyside/signalmanager.cpp
+++ b/sources/pyside2/libpyside/signalmanager.cpp
@@ -53,6 +53,7 @@
#include <gilstate.h>
#include <sbkconverter.h>
#include <sbkstring.h>
+#include <sbkstaticstrings.h>
#include <QtCore/QDebug>
#include <QtCore/QHash>
@@ -77,8 +78,6 @@
#define PYSIDE_SIGNAL '2'
#include "globalreceiverv2.h"
-#define PYTHON_TYPE "PyObject"
-
namespace {
static PyObject *metaObjectAttr = 0;
@@ -115,18 +114,24 @@ namespace PySide {
PyObjectWrapper::PyObjectWrapper()
:m_me(Py_None)
{
+ // PYSIDE-813: When PYSIDE-164 was solved by adding some thread allowance,
+ // this code was no longer protected. It was hard to find this connection.
+ // See the website https://bugreports.qt.io/browse/PYSIDE-813 for details.
+ Shiboken::GilState gil;
Py_XINCREF(m_me);
}
PyObjectWrapper::PyObjectWrapper(PyObject *me)
: m_me(me)
{
+ Shiboken::GilState gil;
Py_XINCREF(m_me);
}
PyObjectWrapper::PyObjectWrapper(const PyObjectWrapper &other)
: m_me(other.m_me)
{
+ Shiboken::GilState gil;
Py_XINCREF(m_me);
}
@@ -143,6 +148,7 @@ PyObjectWrapper::~PyObjectWrapper()
void PyObjectWrapper::reset(PyObject *o)
{
+ Shiboken::GilState gil;
Py_XINCREF(o);
Py_XDECREF(m_me);
m_me = o;
@@ -171,7 +177,7 @@ QDataStream &operator<<(QDataStream &out, const PyObjectWrapper &myObj)
Shiboken::GilState gil;
if (!reduce_func) {
Shiboken::AutoDecRef pickleModule(PyImport_ImportModule("pickle"));
- reduce_func = PyObject_GetAttrString(pickleModule, "dumps");
+ reduce_func = PyObject_GetAttr(pickleModule, Shiboken::PyName::dumps());
}
Shiboken::AutoDecRef repr(PyObject_CallFunctionObjArgs(reduce_func, (PyObject *)myObj, NULL));
if (repr.object()) {
@@ -202,7 +208,7 @@ QDataStream &operator>>(QDataStream &in, PyObjectWrapper &myObj)
Shiboken::GilState gil;
if (!eval_func) {
Shiboken::AutoDecRef pickleModule(PyImport_ImportModule("pickle"));
- eval_func = PyObject_GetAttrString(pickleModule, "loads");
+ eval_func = PyObject_GetAttr(pickleModule, Shiboken::PyName::loads());
}
QByteArray repr;
@@ -268,15 +274,15 @@ SignalManager::SignalManager() : m_d(new SignalManagerPrivate)
using namespace Shiboken;
// Register PyObject type to use in queued signal and slot connections
- qRegisterMetaType<PyObjectWrapper>(PYTHON_TYPE);
- qRegisterMetaTypeStreamOperators<PyObjectWrapper>(PYTHON_TYPE);
+ qRegisterMetaType<PyObjectWrapper>("PyObject");
+ qRegisterMetaTypeStreamOperators<PyObjectWrapper>("PyObject");
qRegisterMetaTypeStreamOperators<PyObjectWrapper>("PyObjectWrapper");
qRegisterMetaTypeStreamOperators<PyObjectWrapper>("PySide::PyObjectWrapper");
SbkConverter *converter = Shiboken::Conversions::createConverter(&PyBaseObject_Type, nullptr);
Shiboken::Conversions::setCppPointerToPythonFunction(converter, PyObject_PTR_CppToPython_PyObject);
Shiboken::Conversions::setPythonToCppPointerFunctions(converter, PyObject_PythonToCpp_PyObject_PTR, is_PyObject_PythonToCpp_PyObject_PTR_Convertible);
- Shiboken::Conversions::registerConverterName(converter, PYTHON_TYPE);
+ Shiboken::Conversions::registerConverterName(converter, "PyObject");
Shiboken::Conversions::registerConverterName(converter, "object");
Shiboken::Conversions::registerConverterName(converter, "PyObjectWrapper");
Shiboken::Conversions::registerConverterName(converter, "PySide::PyObjectWrapper");
@@ -551,10 +557,19 @@ bool SignalManager::registerMetaMethod(QObject *source, const char *signature, Q
static MetaObjectBuilder *metaBuilderFromDict(PyObject *dict)
{
+ // PYSIDE-803: The dict in this function is the ob_dict of an SbkObject.
+ // The "metaObjectAttr" entry is only handled in this file. There is no
+ // way in this function to involve the interpreter. Therefore, we need
+ // no GIL.
+ // Note that "SignalManager::registerMetaMethodGetIndex" has write actions
+ // that might involve the interpreter, but in that context the GIL is held.
if (!dict || !PyDict_Contains(dict, metaObjectAttr))
return nullptr;
- PyObject *pyBuilder = PyDict_GetItem(dict, metaObjectAttr);
+ // PYSIDE-813: The above assumption is not true in debug mode:
+ // PyDict_GetItem would touch PyThreadState_GET and the global error state.
+ // PyDict_GetItemWithError instead can work without GIL.
+ PyObject *pyBuilder = PyDict_GetItemWithError(dict, metaObjectAttr);
#ifdef IS_PY3K
return reinterpret_cast<MetaObjectBuilder *>(PyCapsule_GetPointer(pyBuilder, nullptr));
#else
@@ -606,7 +621,14 @@ int SignalManager::registerMetaMethodGetIndex(QObject *source, const char *signa
const QMetaObject *SignalManager::retrieveMetaObject(PyObject *self)
{
- Shiboken::GilState gil;
+ // PYSIDE-803: Avoid the GIL in SignalManager::retrieveMetaObject
+ // This function had the GIL. We do not use the GIL unless we have to.
+ // metaBuilderFromDict accesses a Python dict, but in that context there
+ // is no way to reach the interpreter, see "metaBuilderFromDict".
+ //
+ // The update function is MetaObjectBuilderPrivate::update in
+ // dynamicmetaobject.c . That function now uses the GIL when the
+ // m_dirty flag is set.
Q_ASSERT(self);
MetaObjectBuilder *builder = metaBuilderFromDict(reinterpret_cast<SbkObject *>(self)->ob_dict);
diff --git a/sources/pyside2/libpyside/signalmanager.h b/sources/pyside2/libpyside/signalmanager.h
index 229ddb91d..fe077bd1a 100644
--- a/sources/pyside2/libpyside/signalmanager.h
+++ b/sources/pyside2/libpyside/signalmanager.h
@@ -43,6 +43,7 @@
#include "pysidemacros.h"
#include <sbkpython.h>
+#include <shibokenmacros.h>
#include <QtCore/QMetaMethod>