Hi,

the documentation of how to use new style signals and slots is relatively 
sparse, thus I wrote some test cases to determine what is to expect. I was 
mostly looking at PyQt4 documentation when working with new style signals and 
slots.
These test cases raised two questions:

1) Even if a slot was annotated with @Slot(type) the connection is made with 
all signals of the same name and not just the signal with the correct overload 
type. The PyQt documentation states that it is using a default overload in 
these situations. What is the right behavior in this case?

    @QtCore.Slot(int)
    @QtCore.Slot('double')
    @QtCore.Slot(str)
    @QtCore.Slot('QVariant')
    def slot1(self, value1):
        self._value1 = value1

    @QtCore.Slot(int)
    def slot1Int(self, value1):
        self._value1Int = value1

    def testAutomaticType(self):
        spinBox = QtGui.QSpinBox()
        spinBox.valueChanged.connect(self.slot1Int)
        spinBox.valueChanged.emit(1)
        self.assertEqual(1, self._value1Int)

2) float is no valid type for double signals, although a Python float is a C 
signed double. Should the Python type float be a valid type for signal 
overrides?
    
    def testDoubleSignal2(self):
        spinBox = QtGui.QDoubleSpinBox()
        spinBox.valueChanged[float].connect(self.slot1)
        spinBox.valueChanged[float].emit(2.0)
        self.assertEqual(2.0, self._value1)

The testPartial and testLambda methods are test cases for bug #542. In the case 
of the clicked signal of a QPushButton, the optional signal parameter "checked 
= false" seems to get passed along to slots that are partial or lambda 
functions.

Test output
-----------

Finding files...
['/.../new_style_signals_slots.py'] ... done
Importing test modules ... done.

testAutomaticSignalType (new_style_signals_slots.NewSignalsAndSlotsTestCase) 
... FAIL
testDoubleSignal1 (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... ok
testDoubleSignal2 (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... ERROR
testIntSignal1 (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... ok
testIntSignal2 (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... ok
testLambda (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... FAIL
testMultiParameters (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... ok
testPartial (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... FAIL
TypeErrortestPythonSignal (new_style_signals_slots.NewSignalsAndSlotsTestCase) 
... ok
testStrSignal1 (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... ok
testStrSignal2 (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... : 
slot1() takes exactly 2 arguments (3 given)
ok
testStrSignal3 (new_style_signals_slots.NewSignalsAndSlotsTestCase) ... ok

======================================================================
ERROR: testDoubleSignal2 (new_style_signals_slots.NewSignalsAndSlotsTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/.../new_style_signals_slots.py", line 105, in testDoubleSignal2
    spinBox.valueChanged[float].connect(self.slot1)
IndexError: Signature valueChanged(qreal) not found for signal: valueChanged

======================================================================
FAIL: testAutomaticSignalType 
(new_style_signals_slots.NewSignalsAndSlotsTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/.../new_style_signals_slots.py", line 65, in testAutomaticSignalType
    self.assertEqual(1, self._value1Int)
AssertionError: 1 != u''

======================================================================
FAIL: testLambda (new_style_signals_slots.NewSignalsAndSlotsTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/.../new_style_signals_slots.py", line 114, in testLambda
    self.assertEqual('Button', self._value1)
AssertionError: 'Button' != True

======================================================================
FAIL: testPartial (new_style_signals_slots.NewSignalsAndSlotsTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/.../new_style_signals_slots.py", line 121, in testPartial
    self.assertEqual('Button', self._value1)
AssertionError: 'Button' != None

----------------------------------------------------------------------
Ran 12 tests in 0.013s

FAILED (failures=3, errors=1)


The test cases are attached.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import unittest
import PySide.QtCore as QtCore
import PySide.QtGui as QtGui

from functools import partial

def getApplication():
    app = QtCore.QCoreApplication.instance()
    if app is None:
        app = QtGui.QApplication(sys.argv)
    return app

app = getApplication()

class PythonMessage(object):
    
    def __init__(self, message):
        super(PythonMessage, self).__init__()
        self._message = message

    def __repr__(self):
        return self._message

class PythonSignalTester(QtCore.QObject):
    
    def __init__(self, parent=None):
        super(PythonSignalTester, self).__init__(parent)
        
    signal1 = QtCore.Signal('QVariant')
    
    signal2 = QtCore.Signal(str, 'QVariant')

class NewSignalsAndSlotsTestCase(unittest.TestCase):
    
    def __init__(self, *args, **kwargs):
        super(NewSignalsAndSlotsTestCase, self).__init__(*args, **kwargs)
        self._value1 = None
        self._value1Int = None
        self._value2 = None
    
    @QtCore.Slot(int)
    @QtCore.Slot(float)
    @QtCore.Slot(str)
    @QtCore.Slot('QVariant')
    def slot1(self, value1):
        self._value1 = value1

    @QtCore.Slot(int)
    def slot1Int(self, value1):
        self._value1Int = value1

    @QtCore.Slot(str, 'QVariant')
    def slot2(self, value1, value2):
        self._value1 = value1
        self._value2 = value2
        
    def testAutomaticType(self):
        spinBox = QtGui.QSpinBox()
        spinBox.valueChanged.connect(self.slot1Int)
        spinBox.valueChanged.emit(1)
        self.assertEqual(1, self._value1Int)
        
    def testIntSignal1(self):
        spinBox = QtGui.QSpinBox()
        spinBox.valueChanged['int'].connect(self.slot1)
        spinBox.valueChanged['int'].emit(1)
        self.assertEqual(1, self._value1)

    def testIntSignal2(self):
        spinBox = QtGui.QSpinBox()
        spinBox.valueChanged[int].connect(self.slot1)
        spinBox.valueChanged[int].emit(2)
        self.assertEqual(2, self._value1)
    
    def testStrSignal1(self):
        spinBox = QtGui.QSpinBox()
        spinBox.valueChanged['QString'].connect(self.slot1)
        spinBox.valueChanged['QString'].emit(u'1')
        self.assertEqual(u'1', self._value1)
        
    def testStrSignal2(self):
        spinBox = QtGui.QSpinBox()
        spinBox.valueChanged[str].connect(self.slot1)
        spinBox.valueChanged[str].emit('2')
        self.assertEqual('2', self._value1)
        
    def testStrSignal3(self):
        spinBox = QtGui.QSpinBox()
        spinBox.valueChanged[unicode].connect(self.slot1)
        spinBox.valueChanged[unicode].emit(u'3')
        self.assertEqual(u'3', self._value1)
    
    def testDoubleSignal1(self):
        spinBox = QtGui.QDoubleSpinBox()
        spinBox.valueChanged['double'].connect(self.slot1)
        spinBox.valueChanged['double'].emit(1.0)
        self.assertEqual(1.0, self._value1)

    def testDoubleSignal2(self):
        spinBox = QtGui.QDoubleSpinBox()
        spinBox.valueChanged[float].connect(self.slot1)
        spinBox.valueChanged[float].emit(2.0)
        self.assertEqual(2.0, self._value1)
        
    def testLambda(self):
        func = lambda x='Button' : self.slot1(x)
        button = QtGui.QPushButton("Button")
        button.clicked.connect(func)
        button.clicked.emit()
        self.assertEqual('Button', self._value1)
        
    def testPartial(self):
        func = partial(self.slot1, 'False')
        button = QtGui.QPushButton("Button")
        button.clicked.connect(func)
        button.clicked.emit()
        self.assertEqual('Button', self._value1)
        
    def testPythonSignal(self):
        message = PythonMessage('This is a Python Object')
        signalTester = PythonSignalTester()
        signalTester.signal1.connect(self.slot1)
        signalTester.signal1.emit(message)
        self.assertEqual(repr(message), repr(self._value1))
        self.assertEqual(message, self._value1)
        
    def testMultiParameterSignal(self):
        message = PythonMessage('bla')
        signalTester = PythonSignalTester()
        signalTester.signal2.connect(self.slot2)
        signalTester.signal2.emit('foo', message)
        self.assertEqual('foo', self._value1)
        self.assertEqual(message, self._value2)


Thanks a lot!

/Christian
_______________________________________________
PySide mailing list
[email protected]
http://lists.openbossa.org/listinfo/pyside

Reply via email to