aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2023-03-08 14:45:32 +0100
committerChristian Tismer <tismer@stackless.com>2023-03-09 17:42:02 +0100
commitd074f98ded062760ca6c237b17221cbba05f5d73 (patch)
treecba7a689a4459725aa17865205c796998a15f5ca /sources/pyside6
parent3e0343a214075efe2660ec36359ea09e8435b562 (diff)
SignalInstance: Fix more very old errors due to unlucky exposure
SignalInstance unfortunately can be created directly without a calling Signal. This is an old design error that cannot easily be reverted because that is now the API. Fixed by printing "(no signature)": * print(SignalInstance()) # prints "(no signature)" Fixed by producing a runtime error: * SignalInstance().connect(lambda: None) * SignalInstance().disconnect() * SignalInstance().emit() Thanks to <bers bers> who reported them all. Task-number: PYSIDE-79 Change-Id: I92598d963b9796453fbd17c1526a674fa007e5e8 Pick-to: 6.4 Reviewed-by: Adrian Herrmann <adrian.herrmann@qt.io> Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io>
Diffstat (limited to 'sources/pyside6')
-rw-r--r--sources/pyside6/libpyside/pysidesignal.cpp15
-rw-r--r--sources/pyside6/tests/pysidetest/signalinstance_equality_test.py13
2 files changed, 25 insertions, 3 deletions
diff --git a/sources/pyside6/libpyside/pysidesignal.cpp b/sources/pyside6/libpyside/pysidesignal.cpp
index 291de73d8..17071cd1d 100644
--- a/sources/pyside6/libpyside/pysidesignal.cpp
+++ b/sources/pyside6/libpyside/pysidesignal.cpp
@@ -185,7 +185,8 @@ static PyObject *signalInstanceRepr(PyObject *obSelf)
auto *self = reinterpret_cast<PySideSignalInstance *>(obSelf);
auto *typeName = Py_TYPE(obSelf)->tp_name;
return Shiboken::String::fromFormat("<%s %s at %p>", typeName,
- self->d->signature.constData(), obSelf);
+ self->d ? self->d->signature.constData()
+ : "(no signature)", obSelf);
}
static PyMethodDef SignalInstance_methods[] = {
@@ -436,6 +437,10 @@ static PyObject *signalInstanceConnect(PyObject *self, PyObject *args, PyObject
return nullptr;
PySideSignalInstance *source = reinterpret_cast<PySideSignalInstance *>(self);
+ if (!source->d) {
+ PyErr_Format(PyExc_RuntimeError, "cannot connect uninitialized SignalInstance");
+ return nullptr;
+ }
Shiboken::AutoDecRef pyArgs(PyList_New(0));
bool match = false;
@@ -552,6 +557,10 @@ static int argCountInSignature(const char *signature)
static PyObject *signalInstanceEmit(PyObject *self, PyObject *args)
{
PySideSignalInstance *source = reinterpret_cast<PySideSignalInstance *>(self);
+ if (!source->d) {
+ PyErr_Format(PyExc_RuntimeError, "cannot emit uninitialized SignalInstance");
+ return nullptr;
+ }
// PYSIDE-2201: Check if the object has vanished meanwhile.
// Tried to revive it without exception, but this gives problems.
@@ -625,6 +634,10 @@ static PyObject *signalInstanceGetItem(PyObject *self, PyObject *key)
static PyObject *signalInstanceDisconnect(PyObject *self, PyObject *args)
{
auto source = reinterpret_cast<PySideSignalInstance *>(self);
+ if (!source->d) {
+ PyErr_Format(PyExc_RuntimeError, "cannot disconnect uninitialized SignalInstance");
+ return nullptr;
+ }
Shiboken::AutoDecRef pyArgs(PyList_New(0));
PyObject *slot = Py_None;
diff --git a/sources/pyside6/tests/pysidetest/signalinstance_equality_test.py b/sources/pyside6/tests/pysidetest/signalinstance_equality_test.py
index 732420c4d..d09d63c0e 100644
--- a/sources/pyside6/tests/pysidetest/signalinstance_equality_test.py
+++ b/sources/pyside6/tests/pysidetest/signalinstance_equality_test.py
@@ -12,7 +12,7 @@ init_test_paths(False)
from helper.usesqapplication import UsesQApplication
-from PySide6.QtCore import QFile, QObject, QTimer, Signal, Slot
+from PySide6.QtCore import QFile, QObject, QTimer, Signal, SignalInstance, Slot
from PySide6.QtWidgets import QSlider
@@ -40,7 +40,16 @@ class TestSignalInstance(unittest.TestCase):
def test_custom_inherited_signal_instances_are_equal(self):
o = D()
self.assertTrue(o.custom_signal == o.custom_signal)
-
+ # additional tests of old errors from 2010 or so
+ def test_uninitialized_SignalInstance(self):
+ # This will no longer crash
+ print(SignalInstance())
+ with self.assertRaises(RuntimeError):
+ SignalInstance().connect(lambda: None)
+ with self.assertRaises(RuntimeError):
+ SignalInstance().disconnect()
+ with self.assertRaises(RuntimeError):
+ SignalInstance().emit()
class MyWidget(QSlider):
valueChanged = Signal(tuple)