Details
-
Bug
-
Resolution: Fixed
-
P3: Somewhat important
-
6.7
-
None
-
1080236f3 (dev)
Description
Problem:
When Qt started using the new Python-style Enums, they were generated with the following type hints:
class Qt(Shiboken.Object): class AlignmentFlag(enum.IntFlag): AlignLeading : Qt.AlignmentFlag = ... # 0x1 AlignLeft : Qt.AlignmentFlag = ... # 0x1 AlignRight : Qt.AlignmentFlag = ... # 0x2 AlignTrailing : Qt.AlignmentFlag = ... # 0x2 AlignHCenter : Qt.AlignmentFlag = ... # 0x4 AlignJustify : Qt.AlignmentFlag = ... # 0x8 AlignAbsolute : Qt.AlignmentFlag = ... # 0x10 AlignHorizontal_Mask : Qt.AlignmentFlag = ... # 0x1f AlignTop : Qt.AlignmentFlag = ... # 0x20 AlignBottom : Qt.AlignmentFlag = ... # 0x40 AlignVCenter : Qt.AlignmentFlag = ... # 0x80 AlignCenter : Qt.AlignmentFlag = ... # 0x84 AlignBaseline : Qt.AlignmentFlag = ... # 0x100 AlignVertical_Mask : Qt.AlignmentFlag = ... # 0x1e0
This is problematic as it currently is in violation of the enum typing specification:
Members defined within an enum class should not include explicit type annotations. Type checkers should infer a literal type for all members. A type checker should report an error if a type annotation is used for an enum member because this type will be incorrect and misleading to readers of the code:
class Pet(Enum): CAT = 1 # OK DOG: int = 2 # Type checker error
Impact:
As the current type hints are invalid, this issue raises numerous type errors when attempting to use Qt enumerations within type hints and pattern matching.
For instance, when attempting to use Literal[Qt.ItemDataRole.DisplayRole] as a type hint, Pyright raises three different errors in strict mode:
Type of "DisplayRole" is unknown Pylance(reportUnknownMemberType) |
Type arguments for "Literal" must be None, a literal value (int, bool, str, or bytes), or an enum value Pylance(reportInvalidTypeForm) |
Variable not allowed in type expression Pylance(reportInvalidTypeForm) |
Proposed Solution:
The simplest solution would likely be the removal of the type hints outright. In the case of the Qt.AlignmentFlag enum from earlier, this would look like the following:
class Qt(Shiboken.Object): class AlignmentFlag(enum.IntFlag): AlignLeading = ... # 0x1 AlignLeft = ... # 0x1 AlignRight = ... # 0x2 AlignTrailing = ... # 0x2 AlignHCenter = ... # 0x4 AlignJustify = ... # 0x8 AlignAbsolute = ... # 0x10 AlignHorizontal_Mask = ... # 0x1f AlignTop = ... # 0x20 AlignBottom = ... # 0x40 AlignVCenter = ... # 0x80 AlignCenter = ... # 0x84 AlignBaseline = ... # 0x100 AlignVertical_Mask = ... # 0x1e0
However, this solution is somewhat incomplete and misleading since the Qt.AlignLeading and Qt.AlignTrailing members are synonyms/aliases for Qt.AlignLeft and Qt.AlignRight respectively.
Although this can be proven at runtime, it would be helpful to indicate which values are aliases by changing the type hints to the following:
class Qt(Shiboken.Object): class AlignmentFlag(enum.IntFlag): AlignLeft = ... # 0x1 AlignLeading = AlignLeft AlignRight = ... # 0x2 AlignTrailing = AlignRight AlignHCenter = ... # 0x4 AlignJustify = ... # 0x8 AlignAbsolute = ... # 0x10 AlignHorizontal_Mask = ... # 0x1f AlignTop = ... # 0x20 AlignBottom = ... # 0x40 AlignVCenter = ... # 0x80 AlignCenter = ... # 0x84 AlignBaseline = ... # 0x100 AlignVertical_Mask = ... # 0x1e0
Note that this would require the Qt.AlignmentFlag.AlignLeft and Qt.AlignmentFlag.AlignLeading members to swap positions. Due to this, I'm uncertain whether this change should be considered as part of this bugfix or if it should be moved to a new feature request.