Details
-
Bug
-
Resolution: Invalid
-
Not Evaluated
-
None
-
5.15.2, 6.2.0
-
None
-
Reproduced on:
- Python 3.9.6 + PySide 5.15.2
- Python 3.9.6 + PySide 6.2.0
Description
I'm unsure if this is a bug, but here goes:
I have a QtCore.QAbstractListModel subclass. In the data method, I return a QtGui.QIcon instance from a cache (to make things simpler in the example below, I use the global namespace as a cache). I expect that this instance should be returned on every call to data() made with the same index + role (again for this example I just always return it regardless of Index or role because KISS). As you can see from the result below, the icon inside the data method is the global icon but what's being returned from data() is a new Icon every time (I store the result in a list so the memory address of the previous result doesn't get gc'd and re-used, which python has a tendency to do, as this would mask the problem).
from PySide6 import QtCore, QtGui icon = QtGui.QIcon.fromTheme('folder') print('global', icon) class MyModel(QtCore.QAbstractListModel): def rowCount(self, parent=QtCore.QModelIndex()) -> int: return 1 def data(self, index, role=QtCore.Qt.DecorationRole): print('inside_data', icon) return icon if __name__ == '__main__': model = MyModel() idx = model.index(0, 0) icons = [idx.data(role=QtCore.Qt.DecorationRole) for _ in range(5)] for ico in icons: print('result of index.data()', ico)
This outputs:
global <PySide6.QtGui.QIcon(null) at 0x7f0c680710c0>
inside_data <PySide6.QtGui.QIcon(null) at 0x7f0c680710c0>
inside_data <PySide6.QtGui.QIcon(null) at 0x7f0c680710c0>
inside_data <PySide6.QtGui.QIcon(null) at 0x7f0c680710c0>
inside_data <PySide6.QtGui.QIcon(null) at 0x7f0c680710c0>
inside_data <PySide6.QtGui.QIcon(null) at 0x7f0c680710c0>
result of index.data() <PySide6.QtGui.QIcon(null) at 0x7f0c66355500>
result of index.data() <PySide6.QtGui.QIcon(null) at 0x7f0c66355540>
result of index.data() <PySide6.QtGui.QIcon(null) at 0x7f0c663555c0>
result of index.data() <PySide6.QtGui.QIcon(null) at 0x7f0c66355640>
result of index.data() <PySide6.QtGui.QIcon(null) at 0x7f0c663556c0>
As you can see each returned value from index.data() occupies a different address in memory. I would expect it to be the same object as the one logged inside data() and at the module level.
This actually led to a memory leak that caused my machine to crash as my delegate was doing some caching using the functools.cache decorator (which doesn't let you choose a cache_key, it automatically uses object._hash_ which default to a unique id per object). One of the element used for caching was the icon returned by data. That means I was filling a cache but never using it (and since the icon was cached, its memory space was also never re-used so: crash)
Is this normal behavior?