Details
-
Bug
-
Resolution: Done
-
P2: Important
-
1.2.x, 5.11.0
-
Ubuntu 12.04 x64 with Python 3.4.0 x64 running PySide 1.2.2 installed via pip 1.5.6. I had previously seen the problem with Python 3.3.5 and PySide 1.2.1 using the attached "enum.py" and upgraded in hopes that it would be fixed.
-
4f1739e062623d3ab8aebe9540e945464734a75b (pyside/pyside-setup/5.14)
Description
When attempting to use the new Python 3.4.0 "enum.Enum", I encounter multiple problems.
Consider the following PY file:
from enum import Enum from PySide import QtCore, QtGui import sys import traceback class MYENUM(Enum): A = 1 B = 2 C = 3 def work(val): print("'work' called with val {}".format(repr(val))) class TwoButton(QtGui.QWidget): works = QtCore.Signal(str) import pdb; pdb.set_trace() worksNot = QtCore.Signal(MYENUM) def __init__(self): super().__init__() layout = QtGui.QHBoxLayout() btn = QtGui.QPushButton('Works', self) layout.addWidget(btn) btn.clicked.connect(self.onWorks) btn = QtGui.QPushButton('Doesn\'t Work', self) layout.addWidget(btn) btn.clicked.connect(self.onDoesntWork) self.setWindowTitle('Enum Signal Bug Demo') self.setLayout(layout) self.show() def onWorks(self): self.works.emit("hello123") def onDoesntWork(self): try: self.worksNot.emit(MYENUM.A) except: traceback.print_exc() if __name__ == '__main__': app = QtGui.QApplication(sys.argv) wgt = TwoButton() wgt.works.connect(work) wgt.worksNot.connect(work) sys.exit(app.exec_())
USER@USER-PC:~/scripts$ python3.4 pysideEnumBug.py Segmentation fault (core dumped) USER@USER-PC:~/scripts$ python3.4 pysideEnumBug.py > /home/USER/scripts/pysideEnumBug.py(18)TwoButton() -> worksNot = QtCore.Signal(MYENUM) (Pdb) s --Call-- > /usr/lib/python3.4/enum.py(263)__len__() -> def __len__(cls): (Pdb) n > /usr/lib/python3.4/enum.py(264)__len__() -> return len(cls._member_names_) (Pdb) s --Return-- > /usr/lib/python3.4/enum.py(264)__len__()->3 -> return len(cls._member_names_) (Pdb) s --Call-- > /usr/lib/python3.4/enum.py(257)__getitem__() -> def __getitem__(cls, name): (Pdb) n > /usr/lib/python3.4/enum.py(258)__getitem__() -> return cls._member_map_[name] (Pdb) s KeyError: 0 > /usr/lib/python3.4/enum.py(258)__getitem__() -> return cls._member_map_[name] (Pdb) s --Return-- > /usr/lib/python3.4/enum.py(258)__getitem__()->None -> return cls._member_map_[name] (Pdb) s Segmentation fault (core dumped) USER@USER-PC:~/scripts$
"name" in this case is an integer, and PySide uses the length reported by "_len_" to query the various indexes of the MYENUM object. Since Enum doesn't support indexing, it raises a KeyError and this causes the segmentation fault.
If I modify the source code for "enum.Enum._getitem" to accept integers and return the proper item from its internal OrderedDict (e.g. ".getitem_(1)" would return MYENUM.A), the code will compile, but then I'll get "TypeError: worksNot() only accepts 0 arguments, 2 given!" when I try to do "worksNot.emit(MYENUM.A)". I've attached the modified "enum.py" to this bug report.
USER@USER-PC:~/scripts$ python3.4 pysideEnumBug.py > /home/USER/scripts/pysideEnumBug.py(19)TwoButton() -> worksNot = QtCore.Signal(MYENUM) (Pdb) c #Click the "Works" button. 'work' called with val 'hello123' #Click the "Doesn't Work" button. Traceback (most recent call last): File "pysideEnumBug.py", line 39, in onDoesntWork self.worksNot.emit(MYENUM.A) TypeError: worksNot() only accepts 0 arguments, 2 given!
Such an error message is typically a symptom of the target class not deriving from the new Python class type. However, this is Python 3.x; all classes are the new type. For the sake of completeness, I tried modifying the enum.Enum source code to explicitly derive from "object" ("class Enum(object, metaclass=EnumMeta)"), but this did not change the outcome.