Skip to content

Commit

Permalink
Merge pull request #39 from astrofrog/fix-pyside-segfault
Browse files Browse the repository at this point in the history
Fix remaining segmentation fault that occurs with the patched QComboBox in PySide
  • Loading branch information
Nodd committed Jun 15, 2016
2 parents 4b5def0 + a7ada0e commit 4a2ef54
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 18 deletions.
18 changes: 8 additions & 10 deletions qtpy/_patch/qcombobox.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ def patch_qcombobox(QComboBox):
from qtpy.QtGui import QIcon
from qtpy.QtCore import Qt, QObject

class userDataWrapper(QObject):
class userDataWrapper():
"""
This class is used to wrap any userData object inside a QObject which
is then supported by all Python Qt wrappers.
This class is used to wrap any userData object. If we don't do this,
then certain types of objects can cause segmentation faults or issues
depending on whether/how __getitem__ is defined.
"""
def __init__(self, data, parent=None):
super(userDataWrapper, self).__init__(parent)
def __init__(self, data):
self.data = data

_addItem = QComboBox.addItem
Expand All @@ -61,8 +61,7 @@ def addItem(self, *args, **kwargs):
and len(args) == 2):
args, kwargs['userData'] = args[:-1], args[-1]
if 'userData' in kwargs:
kwargs['userData'] = userDataWrapper(kwargs['userData'],
parent=self)
kwargs['userData'] = userDataWrapper(kwargs['userData'])
_addItem(self, *args, **kwargs)

_insertItem = QComboBox.insertItem
Expand All @@ -72,14 +71,13 @@ def insertItem(self, *args, **kwargs):
and len(args) == 3):
args, kwargs['userData'] = args[:-1], args[-1]
if 'userData' in kwargs:
kwargs['userData'] = userDataWrapper(kwargs['userData'],
parent=self)
kwargs['userData'] = userDataWrapper(kwargs['userData'])
_insertItem(self, *args, **kwargs)

_setItemData = QComboBox.setItemData

def setItemData(self, index, value, role=Qt.UserRole):
value = userDataWrapper(value, parent=self)
value = userDataWrapper(value)
_setItemData(self, index, value, role=role)

_itemData = QComboBox.itemData
Expand Down
35 changes: 27 additions & 8 deletions tests/test_patch_qcombobox.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ def get_qapp(icon_path=None):
return qapp


class Data(object):
"""
Test class to store in userData. The __getitem__ is needed in order to
reproduce the segmentation fault.
"""
def __getitem__(self, item):
raise ValueError("Failing")


def test_patched_qcombobox():
"""
In PySide, using Python objects as userData in QComboBox causes
Expand All @@ -21,14 +30,6 @@ def test_patched_qcombobox():

app = get_qapp()

class Data(object):
"""
Test class to store in userData. The __getitem__ is needed in order to
reproduce the segmentation fault.
"""
def __getitem__(self, item):
raise ValueError("Failing")

data1 = Data()
data2 = Data()
data3 = Data()
Expand Down Expand Up @@ -73,3 +74,21 @@ def __getitem__(self, item):
assert widget.itemText(4) == 'd'
assert widget.itemText(5) == 'g'
assert widget.itemText(6) == 'f'


def test_model_item():
"""
This is a regression test for an issue that caused the call to item(0)
below to trigger segmentation faults in PySide. The issue is
non-deterministic when running the call once, so we include a loop to make
sure that we trigger the fault.
"""
app = get_qapp()
combo = QtWidgets.QComboBox()
label_data = [('a', None)]
for iter in range(10000):
combo.clear()
for i, (label, data) in enumerate(label_data):
combo.addItem(label, userData=data)
model = combo.model()
model.item(0)

0 comments on commit 4a2ef54

Please sign in to comment.