Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
None
-
5.15.3
-
None
Description
There is `qflags_test.py` which seems to work on Python 2 but breaks on Python 3.
This was not touched for a very long time, and nobody realized that both the tests
and the implementation were broken. That combination was quite a puzzle to solve.
First, the wrong test:
class QFlagsWrongType(unittest.TestCase): def testWrongType(self): '''Wrong type passed to QFlags binary operators''' self.assertRaises(TypeError, Qt.NoItemFlags | '43') self.assertRaises(TypeError, Qt.NoItemFlags & '43') self.assertRaises(TypeError, 'jabba' & Qt.NoItemFlags) self.assertRaises(TypeError, 'hut' & Qt.NoItemFlags) self.assertRaises(TypeError, Qt.NoItemFlags & QObject()) if __name__ == '__main__': unittest.main()
This test is very much broken, because the expressions like Qt.NoItemFlags | '43' are
executed right away as testWrongType is executed, before self.assertRaises has
a chance to do its work.
On Python 2 this did quasi-work, because the error stayed in sys.last_type etc. Python 2
seemed to pick up the exception that had been already set.
On Python 3, the situation was more complicated since in fact some exception chaining happened.
A SystemError was reported together with TypeError because there was an unhandled exception.
And Python 3 is much more correct and did not use the left-over in sys.last_type.
PySide did not check the result of the comparison for wrong types at the right time and later produced a SystemError. After fixing that, things became better:
Now the TypeError was reported, although there were self.assertRaises(TypeError) calls.
The right solution was finally to fix the test as well:
- Do not evaluate it too early but in the context of self.assertRaises(TypeError)
class QFlagsWrongType(unittest.TestCase): def testWrongType(self): '''Wrong type passed to QFlags binary operators''' self.assertRaises(TypeError, operator.or_, Qt.NoItemFlags, '43') self.assertRaises(TypeError, operator.and_, Qt.NoItemFlags, '43') self.assertRaises(TypeError, operator.and_, 'jabba', Qt.NoItemFlags) self.assertRaises(TypeError, operator.and_, 'hut', Qt.NoItemFlags) self.assertRaises(TypeError, operator.and_, Qt.NoItemFlags, QObject()) # making sure this actually does not fail all the time self.assertEqual(operator.or_(Qt.NoItemFlags, 43), 43)
and finally some more tests but less verbose:
class QFlagsWrongType(unittest.TestCase): def testWrongType(self): '''Wrong type passed to QFlags binary operators''' for op in operator.or_, operator.and_, operator.xor: for x in '43', 'jabba', QObject, object: self.assertRaises(TypeError, op, Qt.NoItemFlags, x) self.assertRaises(TypeError, op, x, Qt.NoItemFlags) # making sure this actually does not fail all the time self.assertEqual(operator.or_(Qt.NoItemFlags, 43), 43)