Qt.py icon indicating copy to clipboard operation
Qt.py copied to clipboard

stubs missing signal.connect, disconnect and emit

Open p0las opened this issue 2 years ago • 5 comments

here is a minimalistic example:

from Qt import QtWidgets, QtCore

class Foo(QtWidgets.QWidget):
    my_signal = QtCore.Signal()

    def __init__(self, parent=None):
        super(Foo, self).__init__(parent)
        self.my_signal.connect(self.doSomething)
        
        self.my_signal.emit()
        
    def doSomething(self):
        print("signal emitted")
        

app = QtWidgets.QApplication([])
f = Foo()        
app.exec_()

and what I get in pycharm: image

pycharm is not able to resolve SignaInstance stubs and is looking for the definition in the Signal stub. I'm not sure if this is pycharm issue but I also do not understand why we need two stubs for the same class. Shouldn't we merge SignalInstance stub to Signal? is there any other way to get pycharm to resolve it? I'm getting a lot of false positives in the IDE.

Warning:(88, 17) Unresolved attribute reference 'connect' for class 'Signal' Warning:(107, 64) Unresolved attribute reference 'emit' for class 'Signal'

p0las avatar Nov 15 '23 23:11 p0las

Ping @chadrik, the author of these stubs.

mottosso avatar Nov 16 '23 07:11 mottosso

Hi all, thanks for flagging me.

This is unfortunately an issue with PyCharm. mypy correctly understands that the type of self.my_signal is SignalInstance.

I added a reveal_type statement and ran mypy 1.7 on this code:

from Qt import QtWidgets, QtCore

class Foo(QtWidgets.QWidget):
    my_signal = QtCore.Signal()

    def __init__(self, parent=None):
        super(Foo, self).__init__(parent)
        reveal_type(self.my_signal)
        self.my_signal.connect(self.doSomething)

        self.my_signal.emit()

    def doSomething(self):
        print("signal emitted")

mypy prints the expected type:

tests/test_general.py:8: note: Revealed type is "PySide2.QtCore.SignalInstance"

This appears to be an issue with PyCharm's comprehension of python data descriptors (__get__).

What version of PyCharm are you using?

chadrik avatar Nov 17 '23 19:11 chadrik

I use whatever is the latest one (pro). this issue has been bugging me for a while and I tried a lot of things to fix it recently. I can obviously edit the stubs and make pycharm happy but I wanted to fix it properly and I don't really understand the idea of SignalInstance in the stubs. what is the purpose of this distinction?

p0las avatar Nov 18 '23 01:11 p0las

I think this is the relevant PyCharm ticket: https://youtrack.jetbrains.com/issue/PY-47698/PyCharm-does-not-know-recognize-return-types-of-custom-descriptors

I made these stubs as accurate as possible, so that they would work with advanced code-bases using mypy. It's possible to dumb them down and make them less accurate so that they work with PyCharm. For example, I think removing SignalInstance from QtCore.pyi and editing Signal to the code below would solve your problem:

class Signal:
    def __init__(self, *args, **kwargs) -> None: ...
    def __call__(self, *args, **kwargs): ...
    def connect(self, slot: typing.Callable, type: typing.Union[type, None] = ...) -> bool: ...
    def disconnect(self, slot: typing.Union[typing.Callable, None] = ...) -> None: ...
    def emit(self, *args: typing.Any) -> None: ...
    def __call__(self, *args, **kwargs): ...
    def __getitem__(self, index) -> Signal: ...

I'd rather not have to distribute two sets of stubs -- one for accurate type-checkers and one for broken ones -- but I recognize that PyCharm is much more widely used and relied on than mypy. I'm not sure what a good solution is for this.

chadrik avatar Nov 18 '23 05:11 chadrik

I will report it to pycharm folks. thank you for looking into it.

p0las avatar Nov 18 '23 06:11 p0las

Closing this as it seems unrelated to Qt.py

mottosso avatar Feb 22 '24 19:02 mottosso