From e6fbc6b88e0c11d4985fe73c900d9fb6bce74598 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Fri, 14 Jun 2024 15:49:52 +0200 Subject: [PATCH 1/5] Also ignore AttributeError as occuring in CI --- src/silx/gui/plot/PlotWidget.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/silx/gui/plot/PlotWidget.py b/src/silx/gui/plot/PlotWidget.py index 6b1e1df698..e28162e2b7 100755 --- a/src/silx/gui/plot/PlotWidget.py +++ b/src/silx/gui/plot/PlotWidget.py @@ -1,6 +1,6 @@ # /*########################################################################## # -# Copyright (c) 2004-2023 European Synchrotron Radiation Facility +# Copyright (c) 2004-2024 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -828,10 +828,10 @@ def showEvent(self, event): def hideEvent(self, event): super(PlotWidget, self).hideEvent(event) if qt.BINDING == "PySide6": - # Workaround RuntimeError: The SignalInstance object was already deleted + # Workaround RuntimeError/AttributeError: The SignalInstance object was already deleted try: self.sigVisibilityChanged.emit(False) - except RuntimeError as e: + except (RuntimeError, AttributeError) as e: _logger.error(f"Exception occured: {e}") else: self.sigVisibilityChanged.emit(False) From 5f00b46dd82f9b7d12258905193a53fff5b5ef2e Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Fri, 14 Jun 2024 15:50:11 +0200 Subject: [PATCH 2/5] Process Qt events after deletion of the plot widget --- src/silx/gui/plot/test/testPixelIntensityHistoAction.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/silx/gui/plot/test/testPixelIntensityHistoAction.py b/src/silx/gui/plot/test/testPixelIntensityHistoAction.py index 7fd87e887a..00374fa266 100644 --- a/src/silx/gui/plot/test/testPixelIntensityHistoAction.py +++ b/src/silx/gui/plot/test/testPixelIntensityHistoAction.py @@ -1,6 +1,6 @@ # /*########################################################################## # -# Copyright (c) 2016-2018 European Synchrotron Radiation Facility +# Copyright (c) 2016-2024 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -47,6 +47,7 @@ def setUp(self): def tearDown(self): del self.plotImage + self.qapp.processEvents() super(TestPixelIntensitiesHisto, self).tearDown() def testShowAndHide(self): From 28074d132a399d0dbd73940b7a4b9621529dfa7a Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Fri, 14 Jun 2024 16:39:32 +0200 Subject: [PATCH 3/5] process events and wait longer to avoid test issues --- src/silx/gui/dialog/test/test_datafiledialog.py | 5 +++-- src/silx/gui/dialog/test/test_imagefiledialog.py | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/silx/gui/dialog/test/test_datafiledialog.py b/src/silx/gui/dialog/test/test_datafiledialog.py index 887ff1ccf4..1837f22609 100644 --- a/src/silx/gui/dialog/test/test_datafiledialog.py +++ b/src/silx/gui/dialog/test/test_datafiledialog.py @@ -1,6 +1,6 @@ # /*########################################################################## # -# Copyright (c) 2016-2022 European Synchrotron Radiation Facility +# Copyright (c) 2016-2024 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -115,10 +115,11 @@ def _deleteDialog(self): self.qWaitForDestroy(ref) def qWaitForPendingActions(self, dialog): + self.qapp.processEvents() for _ in range(20): if not dialog.hasPendingEvents(): return - self.qWait(10) + self.qWait(100) raise RuntimeError("Still have pending actions") def assertSamePath(self, path1, path2): diff --git a/src/silx/gui/dialog/test/test_imagefiledialog.py b/src/silx/gui/dialog/test/test_imagefiledialog.py index 9d2c414462..9704b245a4 100644 --- a/src/silx/gui/dialog/test/test_imagefiledialog.py +++ b/src/silx/gui/dialog/test/test_imagefiledialog.py @@ -1,6 +1,6 @@ # /*########################################################################## # -# Copyright (c) 2016-2022 European Synchrotron Radiation Facility +# Copyright (c) 2016-2024 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -122,10 +122,11 @@ def _deleteDialog(self): self.qWaitForDestroy(ref) def qWaitForPendingActions(self, dialog): + self.qapp.processEvents() for _ in range(20): if not dialog.hasPendingEvents(): return - self.qWait(10) + self.qWait(100) raise RuntimeError("Still have pending actions") def assertSamePath(self, path1, path2): From dc12a7f0fcae585d83e98ae3193c3a3b58e9aa9d Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Tue, 18 Jun 2024 10:01:09 +0200 Subject: [PATCH 4/5] Use PlotWidgetTestCase to ensure widget closing cleanly --- .../test/testPixelIntensityHistoAction.py | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/silx/gui/plot/test/testPixelIntensityHistoAction.py b/src/silx/gui/plot/test/testPixelIntensityHistoAction.py index 00374fa266..f66bc927c3 100644 --- a/src/silx/gui/plot/test/testPixelIntensityHistoAction.py +++ b/src/silx/gui/plot/test/testPixelIntensityHistoAction.py @@ -31,32 +31,30 @@ import numpy from silx.utils.testutils import ParametricTestCase -from silx.gui.utils.testutils import TestCaseQt, getQToolButtonFromAction +from silx.gui.utils.testutils import getQToolButtonFromAction from silx.gui import qt from silx.gui.plot import Plot2D +from .utils import PlotWidgetTestCase -class TestPixelIntensitiesHisto(TestCaseQt, ParametricTestCase): +class TestPixelIntensitiesHisto(PlotWidgetTestCase, ParametricTestCase): """Tests for PixelIntensitiesHistoAction widget.""" + def _createPlot(self): + return Plot2D() + def setUp(self): super(TestPixelIntensitiesHisto, self).setUp() self.image = numpy.random.rand(10, 10) - self.plotImage = Plot2D() - self.plotImage.getIntensityHistogramAction().setVisible(True) - - def tearDown(self): - del self.plotImage - self.qapp.processEvents() - super(TestPixelIntensitiesHisto, self).tearDown() + self.plot.getIntensityHistogramAction().setVisible(True) def testShowAndHide(self): """Simple test that the plot is showing and hiding when activating the action""" - self.plotImage.addImage(self.image, origin=(0, 0), legend="sino") - self.plotImage.show() + self.plot.addImage(self.image, origin=(0, 0), legend="sino") + self.plot.show() - histoAction = self.plotImage.getIntensityHistogramAction() + histoAction = self.plot.getIntensityHistogramAction() # test the pixel intensity diagram is showing button = getQToolButtonFromAction(histoAction) @@ -67,7 +65,7 @@ def testShowAndHide(self): self.assertTrue(histoAction.getHistogramWidget().isVisible()) # test the pixel intensity diagram is hiding - self.plotImage.activateWindow() + self.plot.activateWindow() self.qapp.processEvents() self.mouseMove(button) self.mouseClick(button, qt.Qt.LeftButton) @@ -84,15 +82,15 @@ def testImageFormatInput(self): numpy.float32, numpy.float64, ] - self.plotImage.addImage(self.image, origin=(0, 0), legend="sino") - self.plotImage.show() - button = getQToolButtonFromAction(self.plotImage.getIntensityHistogramAction()) + self.plot.addImage(self.image, origin=(0, 0), legend="sino") + self.plot.show() + button = getQToolButtonFromAction(self.plot.getIntensityHistogramAction()) self.mouseMove(button) self.mouseClick(button, qt.Qt.LeftButton) self.qapp.processEvents() for typeToTest in typesToTest: with self.subTest(typeToTest=typeToTest): - self.plotImage.addImage( + self.plot.addImage( self.image.astype(typeToTest), origin=(0, 0), legend="sino" ) @@ -101,10 +99,10 @@ def testScatter(self): xx = numpy.arange(10) yy = numpy.arange(10) value = numpy.sin(xx) - self.plotImage.addScatter(xx, yy, value) - self.plotImage.show() + self.plot.addScatter(xx, yy, value) + self.plot.show() - histoAction = self.plotImage.getIntensityHistogramAction() + histoAction = self.plot.getIntensityHistogramAction() # test the pixel intensity diagram is showing button = getQToolButtonFromAction(histoAction) @@ -123,10 +121,10 @@ def testChangeItem(self): xx = numpy.arange(10) yy = numpy.arange(10) value = numpy.sin(xx) - self.plotImage.addScatter(xx, yy, value) - self.plotImage.show() + self.plot.addScatter(xx, yy, value) + self.plot.show() - histoAction = self.plotImage.getIntensityHistogramAction() + histoAction = self.plot.getIntensityHistogramAction() # test the pixel intensity diagram is showing button = getQToolButtonFromAction(histoAction) @@ -142,7 +140,7 @@ def testChangeItem(self): data1 = items[0].getValueData(copy=False) # Set another item to the plot - self.plotImage.addImage(self.image, origin=(0, 0), legend="sino") + self.plot.addImage(self.image, origin=(0, 0), legend="sino") self.qapp.processEvents() data2 = items[0].getValueData(copy=False) From 70ad770604f03f9da49a3aca7c92349fda0bffbb Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Tue, 18 Jun 2024 11:01:38 +0200 Subject: [PATCH 5/5] use common plot widget setup/destroy implementation --- src/silx/gui/plot/test/testImageView.py | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/silx/gui/plot/test/testImageView.py b/src/silx/gui/plot/test/testImageView.py index df19ab7993..73c632ffb0 100644 --- a/src/silx/gui/plot/test/testImageView.py +++ b/src/silx/gui/plot/test/testImageView.py @@ -1,6 +1,6 @@ # /*########################################################################## # -# Copyright (c) 2017-2021 European Synchrotron Radiation Facility +# Copyright (c) 2017-2024 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -30,30 +30,18 @@ import numpy -from silx.gui import qt -from silx.gui.utils.testutils import TestCaseQt from silx.gui.plot import items from silx.gui.plot.ImageView import ImageView from silx.gui.colors import Colormap +from .utils import PlotWidgetTestCase -class TestImageView(TestCaseQt): +class TestImageView(PlotWidgetTestCase): """Tests of ImageView widget.""" - def setUp(self): - super(TestImageView, self).setUp() - self.plot = ImageView() - self.plot.show() - self.qWaitForWindowExposed(self.plot) - - def tearDown(self): - self.qapp.processEvents() - self.plot.setAttribute(qt.Qt.WA_DeleteOnClose) - self.plot.close() - del self.plot - self.qapp.processEvents() - super(TestImageView, self).tearDown() + def _createPlot(self): + return ImageView() def testSetImage(self): """Test setImage"""