Uploaded image for project: 'Qt for Python'
  1. Qt for Python
  2. PYSIDE-2869

Enum type hints are not compliant with the Python typing specification

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P3: Somewhat important
    • 6.8.0
    • 6.7
    • PySide, Type hints
    • 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:

      Defining Members

      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 

      Source: Enumerations - typing documentation

      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.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            ctismer Christian Tismer
            bflecker Bryton Flecker
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes