Issue
When I run mypy with the --strict
flag, it complains that "QPushButton" has no attribute "clicked". Pycharm also complains about this issue. Despite this, the code runs fine. For example:
import sys
from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("My App")
self.resize(500, 500)
layout = QVBoxLayout()
self.btn = QPushButton("Click Me")
self.btn.clicked.connect(self.btn_clicked)
layout.addWidget(self.btn)
self.setLayout(layout)
self.show()
def btn_clicked(self) -> None:
print("Button clicked")
app = QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec())
Running mypy . --strict
on this raises the following error:
example.py:13: error: "QPushButton" has no attribute "clicked"
Found 1 error in 1 file (checked 1 source file)
Is what I am doing bad practice? Most of the documentation online, including on Qt's official Python documentation says to connect a button to a function in this way.
If this isn't bad practice, is there a way to make Pycharm and mypy not complain about this way of connecting a button?
Solution
As already written in short by @noEmbryo and @ekhumoro in the comments:
Is what I am doing bad practice?
No. You following the official documentation and what you do is correct. The problem is that there is a bug within the types generated for the PySide. PySide/Qt is written in C++ and there only Python Bindings generated for it.
Typing Support for Python is fairly new and still under active development. So in general you will run into troubles from time to time using it. This also means that there is no straight forward way to convert the C++ typing information into Python type informations.
Is there a way to make Pycharm and mypy not complain about this way of connecting a button?
Yes. There are three possibilities:
Wait until the bug is fixed in PySide (i.e. in Version 6.5.0, but if you look at the related issue, there are also some backports to older versions)
Ignore the given error (for the time it is not fixed upstream in PySide)
self.btn.clicked.connect(self.btn_clicked) # type: ignore[attr-defined]
- Create a Wrapper around the Button to tell the type checker, that the clicked attribute actually exists and is a Signal.
import sys
from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
from PySide6.QtCore import Signal
class QPushButtonWithSignals(QPushButton):
"""Remove attributes below once Signal typing issues are fixed upstream"""
clicked: Signal
# Add other missing Signals here if used
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("My App")
self.resize(500, 500)
layout = QVBoxLayout()
self.btn = QPushButtonWithSignals("Click Me")
self.btn.clicked.connect(self.btn_clicked)
…
Answered By - Kound
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.