Search code examples
qtpysidetypingpyside6qt6

PySide6: Signals not included in typing files? (QtCore.pyi etc.)


Consider the following minimal working example:

#!/usr/bin/env python3

from PySide6.QtCore import QTimer
from PySide6.QtWidgets import QLabel, QApplication

app = QApplication()
label = QLabel('Label')

x = 0

def timeout():
  global x
  x += 1
  label.setText(str(x))

timer = QTimer()
timer.timeout.connect(timeout)
timer.start(200)

label.show()
app.exec()

It displays a label (a very tiny window), containing an incrementing counter. This is working all fine. However, I do the development in Visual Studio Code with the PyLance extension and the IDE does not know about the timeout signal of QTimer:

time.timeout tooltip

Fair enough, pressing F12 opens QtCore.pyi with the definition of QTimer and this actually does not contain a timeout member:

class QTimer(PySide6.QtCore.QObject):

    def __init__(self, parent:Optional[PySide6.QtCore.QObject]=...) -> None: ...

    def interval(self) -> int: ...
    def isActive(self) -> bool: ...
    def isSingleShot(self) -> bool: ...
    def killTimer(self, arg__1:int) -> None: ...
    def remainingTime(self) -> int: ...
    def setInterval(self, msec:int) -> None: ...
    def setSingleShot(self, singleShot:bool) -> None: ...
    def setTimerType(self, atype:PySide6.QtCore.Qt.TimerType) -> None: ...
    @overload
    @staticmethod
    def singleShot(arg__1:int, arg__2:Callable) -> None: ...
    @overload
    @staticmethod
    def singleShot(msec:int, receiver:PySide6.QtCore.QObject, member:bytes) -> None: ...
    @overload
    @staticmethod
    def singleShot(msec:int, timerType:PySide6.QtCore.Qt.TimerType, receiver:PySide6.QtCore.QObject, member:bytes) -> None: ...
    @overload
    def start(self) -> None: ...
    @overload
    def start(self, msec:int) -> None: ...
    def stop(self) -> None: ...
    def timerEvent(self, arg__1:PySide6.QtCore.QTimerEvent) -> None: ...
    def timerId(self) -> int: ...
    def timerType(self) -> PySide6.QtCore.Qt.TimerType: ...

This is apparently not limited to QTimer, but holds also e.g. for QAbstractButton, which does not include clicked, pressed, released and toggled. In short, it looks as if all signals would be missing from the objects.

What's going on here? Do I need to install something else besides pip install pyside6 to get all the signals defined in the typing includes? It is, of course, not a showstopper, but would be more convenient if the IDE knew about all members of the objects.

In case it matters, I use the stock python3 of Ubuntu 20.04:

$ python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08) 
[GCC 9.3.0] on linux

Solution

  • This problem has been addressed in PYSIDE-1603 and fixed in 6.4.3 according to Jira.

    The QTimer stubs now include:

    class QTimer(PySide6.QtCore.QObject):
         timeout                  : ClassVar[Signal] = ... # timeout()
    

    Still not great, as Signal ideally should be a generic, so the parameters to emit() and the function for connect() are still not typed. The full Signal signatures are included as a comment however:

    class QObject(Shiboken.Object):
        destroyed                : ClassVar[Signal] = ... # destroyed()
        objectNameChanged        : ClassVar[Signal] = ... # objectNameChanged(QString)