Uploaded image for project: 'Qt for Python'
  1. Qt for Python
  2. PYSIDE-1442

QFlags number methods and qflags_test are both broken

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P2: Important
    • None
    • 5.15.3
    • PySide
    • 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)
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            ctismer Christian Tismer
            ctismer Christian Tismer
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes