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

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


On Tue, Apr 26, 2022 at 09:36:25PM +0200, Florian Bruhin wrote:
> 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.

I spoke too soon, here is something that seems to work, somehow.
The point about "probably too much black magic" still stands, though.

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 --------------
from enum import Enum

class SomePyQtEnum(Enum):

    one = 1
    two = 2

    @classmethod
    def _from_qt(cls, value):
        try:
            return cls(value)
        except ValueError:
            new_member = object.__new__(cls)
            new_member._name_ = f"unknown: {value}"
            new_member._value_ = value
            cls._value2member_map_[value] = new_member
            return new_member

print(SomePyQtEnum._from_qt(1))
print(SomePyQtEnum._from_qt(2))
print(SomePyQtEnum._from_qt(3))
-------------- 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/dd555fd1/attachment.sig>


More information about the PyQt mailing list