PyQt6: QEvent.type() returns int instead of QEvent.Type

Florian Bruhin me at the-compiler.org
Tue Apr 26 20:36:24 BST 2022


On Tue, Apr 26, 2022 at 09:19:05AM +0100, Phil Thompson wrote:
> 
> On 21/04/2022 10:37, Florian Bruhin wrote:
> > Hey,
> > 
> > With PyQt5:
> > 
> >     >>> evtype = QEvent(QEvent.Type.User).type()
> >     >>> evtype
> >     1000
> >     >>> type(evtype)
> >     <class 'PyQt5.QtCore.QEvent.Type'>
> > 
> > and even:
> > 
> >     >>> evtype = QEvent(QEvent.Type.User + 1).type()
> >     >>> evtype
> >     1001
> >     >>> type(evtype)
> >     <class 'PyQt5.QtCore.QEvent.Type'>
> > 
> > but with PyQt6, the type information gets lost:
> > 
> >     >>> evtype = QEvent(QEvent.Type.User).type()
> >     >>> evtype
> >     1000
> >     >>> type(evtype)
> >     <class 'int'>
> > 
> > From what I understand, it's not possible to convert arbitrary values
> > into an IntEnum:
> > 
> >     >>> QEvent.Type(QEvent.Type.User + 1)
> >     [...]
> >     ValueError: 1001 is not a valid QEvent.Type
> > 
> > But least for types which are part of QEvent.Type, calling .type()
> > should perhaps return the IntEnum value again instead of falling back to
> > an int without any type information? Given that IntEnum is an int
> > subclass, this should be a backwards-compatible change too.
> 
> I've been adopting a piecemeal approach to this sort of thing so far. For
> example having QEvent.type() return an int and adding an extra QEvent ctor
> that accepts an int, and similar with gesture types. However the issue you
> point out in your other email (new enum members in later versions of Qt) is
> something I hadn't considered.
> 
> I think the solution is to take the approach you suggest above and apply it
> to all enums (no matter what their base type is). In other words, when
> converting from Python to a C++ enum both a Python enum and an int will be
> accepted. When converting from a C++ enum to Python then the corresponding
> enum member will be returned or an int if there is no such member.
> 
> This would mean that there is no need for me to apply special treatment to
> individual methods (as the change is implemented in the sip module) and the
> approach should be future-proof.
> 
> Thoughts?

Hm, I don't really like the lost type safety when accepting ints.
However, at the same time I can't think of a proper way to solve the
"new enum members" problem.

I tried coercing Python into having some kind of special
SomeEnum.missing(42) value instead, which acts like a member of the
enum, but can also hold an arbitrary value. enum.py sure is some crazy
black magic. I bet it would be possible somehow (custom enum metaclass
defining __instancecheck__ perhaps?), but at this point there is so much
black magic involved I'm not sure it would be a better solution.

Another possibility would perhaps be to generate dummy .valN values for
every possible value, inspired by this:
https://bubblesorted.raab.link/content/automatically-fill-missing-values-python-enum

But no idea how that behaves performance-wise with what I'm guessing
would be 2**16 dummy values for every enum.

So yeah, back to ints I suppose, unless someone has a better idea.

Florian

-- 
            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/20220426/e8cbee2b/attachment.sig>


More information about the PyQt mailing list