typing: Making pyqtSlot typed

Phil Thompson phil at riverbankcomputing.com
Wed Jul 5 17:20:03 BST 2023


On 29/06/2023 23:20, Florian Bruhin wrote:
> Whoops. Resent without line-wrapping... switched to a new mail-client
> which is based on PyQt btw: https://github.com/akissinger/dodo
> 
> Sorry for the noise!
> 
> -----------
> 
> Hey,
> 
> last one for today :)
> 
> pyqtSlot is currently typed as returning Any:
> 
>     def pyqtSlot(
>         *types,
>         name: typing.Optional[str] = ...,
>         result: typing.Optional[str] = ...,
>     ) -> typing.Any: ...
> 
> which means that incorrect code such as:
> 
>     from PyQt6.QtCore import pyqtSlot
> 
>     @pyqtSlot(int)
>     def func(a: int) -> None:
>         print(a)
> 
>     func("not-an-int")
> 
> can't be typechecked because the pyqtSlot decorator loses the type
> information:
> 
>     slot.py:3: error: Untyped decorator makes function "func" untyped 
> [misc]
> 
> A minimal improvement wound be:
> 
>     FuncT = typing.TypeVar("FuncT", bound=typing.Callable)
>     def pyqtSlot(*types, name: typing.Optional[str] = ..., result:
> typing.Optional[str] = ...) -> typing.Callable[[FuncT], FuncT]: ...
> 
> read as:
> 
>     - FuncT is a type variable, representing any callable
>     - Calling pyqtSlot as e.g. pyqtSlot(int) returns a callable
>       (the decorator)
>     - That decorator takes a FuncT as argument, and returns a FuncT
> 
> Thus, we can teach the type system that @pyqtSlot does not touch the
> decorated function's signature, which then results in mypy catching 
> this
> properly:
> 
>     slot.py:7: error: Argument 1 to "func" has incompatible type
> "str"; expected "int"  [arg-type]
>         func("not-an-int")
> 
> Interestingly, the PyQt6-stubs project has far more complex typing for
> pyqtSlot:
> 
> https://github.com/python-qt-tools/PyQt6-stubs/blob/f623a641cd5cdff53342177e4fbbf9cae8172336/PyQt6-stubs/QtCore.pyi#L7537-L7563
> 
> It's unclear to me how that works in detail and if it's really needed.
> The minimal fix above fixes all related errors for my project (but I
> don't e.g. use QML).
> 
> Florian

Fixed.

Thanks,
Phil


More information about the PyQt mailing list