Closed pgh268400 closed 4 weeks ago
Sorry I couldn't repo. seems to work
are you sure you are importing Ui_MainWindow
correctly?
if you right click go to def on Ui_MainWindow
below, where does it take you?
class MainWindow(QMainWindow, Ui_MainWindow):
I had to add from ui.compiled_ui import Ui_MainWindow
Yes you are right. I think I made a mistake while managing several pieces of code. Sorry for the confusion.
I updated the code again.
Ui_MainWindow leads to a class in compiled_ui.py in the ui folder.
Ctrl + Click on Ui_MainWindow PYQT5 problem (Unknown)
Could it be a problem with my computer environment that you are unable to reproduce?
I don't know the nuances of making an analysis successful in PySide.
@EricTraut
any ideas on why swapping multiple heritance order is affecting member variables
repo: pip install PyQt5
from PyQt5.QtWidgets import QMainWindow
class Foo():
pushButton = "button"
class Bar(QMainWindow, Foo):
def __init__(self) -> None:
self.pushButton # type is Unknown
class Bar2(Foo, QMainWindow):
def __init__(self) -> None:
self.pushButton # type is str
The problem here is that QMainWindow
has a class within its class hierarchy with an unknown type. That means its MRO (method resolution order) cannot be properly determined statically.
QMainWindow
derives from QWidget
which derives from QtGui.QPaintDevice
which derives from a class called PyQt5.sipsimplewrapper
. This class is not defined anywhere in Python code (in either a ".py" or ".pyi" file). It appears to be implemented in a native library, so pyright has no visibility into its type.
It looks like many Qt classes ultimately derive from PyQt5.sipsimplewrapper
, so this is probably wreaking havoc for proper type evaluations. The maintainers of PyQt5 should update the library to define this class, even if it's a dummy class definition like class sipsimplewrapper: ...
.
I actually checked that there is no static type declaration for PyQt5.sipsimplewrapper. (I think it's loading during runtime to glue C++ and Python together.)
So in conclusion, is it a problem with the pyqt5 library?
By the way, why was the type inference for pyqt5 done properly in the old version of pylance?
At least it wasn't a problem when I used it before.
If you want to apply a manual fix to your local copy of the library, you can open the PyQt5/__init__.py
file and paste the following to the end of the file:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
class sipsimplewrapper: ...
The behavior for handling unknown base classes hasn't changed for years in pyright (the type checker upon which pylance is based), so any change you've seen is probably due to either 1) changes in the library, or 2) changes in how you're using the library (e.g. the order in which you've specified the base classes, as in the example above).
When an Any
type is introduced into the class hierarchy, a static type checker is effectively "blinded". It can't know what attributes and methods will be present on the class from that parent class or any class that comes beyond it in the MRO. If you are defining your own class with multiple base classes, you can impact the MRO (method resolution ordering) by changing the order of your base classes. This will affect the MRO linearization and potentially change where the Any
entry is.
@erictraut
Wow. I didn't know I could get such a high quality answer.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
class sipsimplewrapper: ...
The problem was solved by manually adding the code you actually provided to the library file. After reviewing the Pyside6 library code, considering that there is no static type issue like this (sipsimplewrapper does not exist in the first place in Pyside6), I think the library issue is correct.
I think all I have to do now is ask the PyQt5 administrator to statically define sipsimplewrapper. (Is it correct?) However, since PyQt5 itself is a GPL license, if I continue to develop it, there may be licensing problems, and since this library is not publicly receiving Pull Requests from Github, I think I should consider migrating PySide6 from LGPL with relatively loose licenses.
And I didn't quite understand what you explained in number 3, does the reason why the type is presumed to be Unknown so far means that all type reasoning is broken because the highest class, sipsimplewrapper, was an undefined Any type?
Environment data
Venv
pip 23.1.2 PyQt5 5.15.9 PyQt5-Qt5 5.15.2 PyQt5-sip 12.12.2 setuptools 65.5.0 ////////////////// pip 23.1.2 PySide6 6.5.2
PySide6-Addons 6.5.2
PySide6-Essentials 6.5.2
setuptools 65.5.0 shiboken6 6.5.2
Code Snippet
PyQt5 example (code in problem situation)
Works fine in PySide6 (weird part)
Expected behavior + Actual behavior
Since Pylance has been updated, the part that inherits the PyQt5 UI does not properly infer the type of the self variable.
For example, in the code above self.pushButton should be inferred as QPushButton . (At least it was in previous versions) But since Pylance was updated, oddly PyQt5's UI inheritance variable inference doesn't work. More troubling is that type inference works well in PySide6, which has almost the same implementation as PyQT5.
In the previous pylance version, the uic part of PyQt5 could not be inferred properly, but after the update, the uic part was properly inferred, so I think something has changed in the pylance implementation.
Logs