Handling of flags in PyQt5 / PyQt6

Florian Bruhin me at the-compiler.org
Tue Mar 16 15:55:39 GMT 2021


Hi,

Before I start, a bit of terminology because this particular case is a
bit confusing:

  enum Qt::AlignmentFlag: "enum name" (even though the type says "Flag")
  flags Qt::Alignment:    "flag name"

With that out of the way:

With PyQt5, QFlags are only accessible in scoped form by using their
enum names:

    # flags
    $ python3 -c "from PyQt5.QtCore import Qt; print(type(Qt.Alignment.AlignLeft))"
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    AttributeError: type object 'Alignment' has no attribute 'AlignLeft'
    
    # enum
    $ python3 -c "from PyQt5.QtCore import Qt; print(type(Qt.AlignmentFlag.AlignLeft))"
    <class 'PyQt5.QtCore.Qt.AlignmentFlag'>

With PyQt6, however, the situation is the exact opposite: They are only
accessible by using their flag names:

    # flags
    $ python3 -c "from PyQt6.QtCore import Qt; print(type(Qt.Alignment.AlignLeft))"
    <enum 'Alignment'>
    
    # enum
    $ python3 -c "from PyQt6.QtCore import Qt; print(type(Qt.AlignmentFlag.AlignLeft))"
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    AttributeError: type object 'Qt' has no attribute 'AlignmentFlag'

Or as a more compact overview:

PyQt5: enum only (or unscoped)
PyQt6: flags only
PySide2: flags only (or unscoped)
PySide6: flags only (or unscoped)

This is consistent with what PySide2/PySide6 do (modulo allowing
unscoped access), and according to [1], this seems to be intended:

    Qt provides the QFlags template class as a type-safe way of using
    enum values that can be combined as a set of flags. The name of the
    class is often the plural form of the name of the enum. PyQt5
    implements both of these as separate types. PyQt6 instead combines
    them as a single type, using the plural name, as a sub-class of
    Flag.

However, this makes it difficult to write code which is compatible with
both PyQt5 and PyQt6, since PyQt6 doesn't accept the same form. Is that
an oversight?

If not, what's the best way I could support both? Right now I only can
think of a helper function like:

   get_flag(Qt.Alignment, Qt.AlignmentFlag, 'AlignLeft')

or some kind of custom wrapper around the type, both of which are a bit
of a pain.

Thanks,
Florian

[1] https://www.riverbankcomputing.com/static/Docs/PyQt6/pyqt5_differences.html

-- 
            me at the-compiler.org | https://www.qutebrowser.org 
       https://bruhin.software/ | https://github.com/sponsors/The-Compiler/
       GPG: 916E B0C8 FD55 A072 | https://the-compiler.org/pubkey.asc
             I love long mails! | https://email.is-not-s.ms/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20210316/f984d0ad/attachment.sig>


More information about the PyQt mailing list