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