Wednesday 15 December 2010

QtCore.QDate gotcha for python dictionaries

I came across an odd little issue this morning while creating a data model for a diary I am writing.

In the model, Data is stored in a dictionary, with dates as keys.
For a variety of reasons, my first choice was to use a QDate for the keys, however this produced odd results.
The following example code should demonstrate.

>>> from PyQt4.QtCore import QDate
>>> mydict = {}
>>> for year in range(2009,2013):
...     dt = QDate(year,1,1)
...     while dt.year() == year:
...         mydict[d] = "boo"
...         dt = dt.addDays(1)
>>>
>>> mydict.keys()[:3]
3: [PyQt4.QtCore.QDate(2011, 8, 21),
 PyQt4.QtCore.QDate(2009, 12, 17),
 PyQt4.QtCore.QDate(2009, 7, 15)]
>>>
>>> mydict[QDate(2011,8,21)]
KeyError: PyQt4.QtCore.QDate(2011, 8, 21)

so what is going on? The dictionary DOES have a key of QDate(2011,8,21)... but is unable to find it.

In debugging, I was reminded that python dictionaries hash the key values and it turns out that there is a known bug in QDate.__hash__
>>> d1 = QDate(2009,12,9)
>>> d1.__hash__()
4: 48759696
>>>
>>> d2 = QDate(2009,12,9)
>>> d2.__hash__()
5: 45344152
>>>


this has been fixed in the very latest versions of PyQt4 I believe (including the python3 version)
In the meantime, I am simply adding a step of conversion to python date types for the keys.

>>> d1.toPyDate().__hash__()
6: 5917697570912074722
>>> d2.toPyDate().__hash__()
7: 5917697570912074722
>>>