Search code examples
python-3.xpyqt5method-signaturekeyword-argument

Where can I find PyQt5 Method Signatures?


I want to write a small application with graphical user interface and for that purpose I installed PyQt5. In a tutorial I found a QMessageBox.information(....) call is done.

I wanted to change the call, so that instead of:

QMessageBox.information(self, "Empty Field", "Please enter a name and address.")

I write keyword arguments, so that I know which of the parameters stand for which content, so that, when I read it in a year, I immediately know what it is about. So I tried:

QMessageBox.information(parent=self, title="Empty Field", message="Please enter a name and address.")

Which at execution time gives me the following error:

Traceback (most recent call last):
File "SimpleExample.py", line 39, in submitContact
QMessageBox.information(parent=self, title="Empty Field", message="Please enter a name and address.")
TypeError: QMessageBox.information(QWidget, str, str, QMessageBox.StandardButtons buttons=QMessageBox.Ok, QMessageBox.StandardButton defaultButton=QMessageBox.NoButton): 'message' is not a valid keyword argument

So my guesses were wrong, but how do I figure out the real method signature? I searched for a while and found this function:

from inspect import getcallargs
getcallargs()

I tried using it like this:

>>> from inspect import getcallargs
>>> from PyQt5.QtWidgets import *
>>> from PyQt5.QtCore import *
>>> getcallargs(QMessageBox.information(), a=1, b=2)

but that also doesn't work:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: QMessageBox.information(QWidget, str, str, QMessageBox.StandardButtons buttons=QMessageBox.Ok, QMessageBox.StandardButton defaultButton=QMessageBox.NoButton): not enough arguments

And no matter how many arguments I add (function 1,2,3,4,5,6,7,8, ...) it's never enough arguments. If it's talking about the arguments of information(), then how am I supposed to find the right amount of arguments of the very function I want to get the arguments for?!

So I thought "Ok lets try and see if I can find the method in the Qt5 docs." but of course, there I am only redirected to the c++ documentation for Qt5 and that one doesn't list a function "information()" for QMessageBox, so I still don't know the names of the keywords.

How can I figure out these names?


Solution

  • In PyQt, keyword arguments are only supported for optional arguments, so you cannot use them as general way of documenting function signatures.

    A quick way to get the correct method signature, is to use the help function in a python interactive session:

    >>> from PyQt5 import Qt
    >>> help(Qt.QMessageBox.information)
    ...
    
    Help on built-in function information:
    
    information(...)
        QMessageBox.information(
            QWidget, str, str,
            QMessageBox.StandardButtons buttons=QMessageBox.Ok,
            QMessageBox.StandardButton defaultButton=QMessageBox.NoButton
        ) -> QMessageBox.StandardButton
    

    This shows that only buttons and defaultButton are available as keyword arguments.

    It's important that you do this, rather than looking at the Qt Docs for QMessageBox.​information, because there is no guarantee that the C++ argument names will match the ones PyQt uses (for more details on this, see Things to be Aware Of: Keyword Arguments in the PyQt Docs).

    PS:

    The restrictions outlined above don't apply to PyQt's Support for Qt Properties, which uses a different underlying mechanism. This functionality provides some Python-specific syntax-sugar which allows Qt properties to be set in the class contructor (via **kwargs, rather than named parameters).

    In this particular case, it's possible to use this mechanism to achieve the desired behaviour because QMessageBox happens to have some properties (if inherited ones are included) that correspond with the relevant parameters in its constructor. However, they don't all have the same names, so you'd need to write something more like this:

    result = QMessageBox(parent,
                icon=QMessageBox.Warning
                windowTitle='Error',
                text='Something went wrong!',
                ).exec()
    

    But in general, its unlikely things will always work out so neatly.