Fix dialog subprocesses: centralize Qt env setup and extract base class
- Add dialog_env.py service: forces QT_QPA_PLATFORM=xcb on Linux so Qt doesn't crash under Wayland in spawned subprocesses - Use QMessageBox instance (instead of static methods) for msg/question dialogs so WindowStaysOnTopHint can be set, making them visible - Add TestItemDialogBase with _run_dialog/_run_dialog_with_result/_cleanup_process, removing duplicated subprocess launch/poll/terminate logic from all 7 dialog items - Reduce terminate() join timeout from 2s to 0.2s across all dialog items Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -185,7 +185,9 @@ def main(args, conn=None):
|
|||||||
SettingsApplication = "testium_choices_dlg_" + args[0]
|
SettingsApplication = "testium_choices_dlg_" + args[0]
|
||||||
SettingsLastChoices = "last_choice"
|
SettingsLastChoices = "last_choice"
|
||||||
success = True
|
success = True
|
||||||
app = QApplication()
|
from interpreter.test_items import dialog_env
|
||||||
|
dialog_env.setup()
|
||||||
|
app = QApplication(['testium'])
|
||||||
d = ChoicesDialog()
|
d = ChoicesDialog()
|
||||||
d.setFixedSize(800, 600)
|
d.setFixedSize(800, 600)
|
||||||
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
|
|||||||
15
src/testium/interpreter/test_items/dialog_env.py
Normal file
15
src/testium/interpreter/test_items/dialog_env.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
"""Qt platform environment setup for dialog subprocesses.
|
||||||
|
|
||||||
|
Call setup() at the start of every dialog subprocess main() function
|
||||||
|
to ensure the correct Qt platform plugin is selected.
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
"""Configure the Qt environment for dialog subprocess usage."""
|
||||||
|
if sys.platform.startswith('linux'):
|
||||||
|
# On Linux/Wayland, force X11 (via XWayland) to avoid crashes
|
||||||
|
# when Qt is initialized inside a multiprocessing subprocess.
|
||||||
|
os.environ['QT_QPA_PLATFORM'] = 'xcb'
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
|
|
||||||
from PySide6.QtCore import (Qt)
|
from PySide6.QtCore import (Qt)
|
||||||
from PySide6.QtWidgets import (QApplication, QDialog)
|
from PySide6.QtWidgets import (QApplication, QDialog)
|
||||||
@@ -18,7 +17,9 @@ class TestDialogWindow(QDialog, dialog_image_win.Ui_Dialog):
|
|||||||
|
|
||||||
def main(args, conn):
|
def main(args, conn):
|
||||||
success = True
|
success = True
|
||||||
app = QApplication(args)
|
from interpreter.test_items import dialog_env
|
||||||
|
dialog_env.setup()
|
||||||
|
app = QApplication(['testium'])
|
||||||
d = TestDialogWindow()
|
d = TestDialogWindow()
|
||||||
d.setFixedSize(700,600)
|
d.setFixedSize(700,600)
|
||||||
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
|
|
||||||
from PySide6.QtWidgets import (QApplication, QDialog)
|
|
||||||
from PySide6.QtCore import (Qt)
|
|
||||||
from PySide6.QtWidgets import QMessageBox
|
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
|
||||||
|
from PySide6.QtWidgets import (QApplication, QMessageBox)
|
||||||
|
from PySide6.QtCore import Qt
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
app = QApplication(sys.argv)
|
from interpreter.test_items import dialog_env
|
||||||
reply = QMessageBox.information(None, args[0], args[1], QMessageBox.Ok)
|
dialog_env.setup()
|
||||||
|
app = QApplication(['testium'])
|
||||||
|
msg = QMessageBox()
|
||||||
|
msg.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
|
msg.setWindowTitle(args[0])
|
||||||
|
msg.setText(args[1])
|
||||||
|
msg.setIcon(QMessageBox.Information)
|
||||||
|
msg.setStandardButtons(QMessageBox.Ok)
|
||||||
|
msg.exec()
|
||||||
|
|
||||||
if hasattr(sys, "frozen"):
|
if hasattr(sys, "frozen"):
|
||||||
#all standard streams are replaced by dummy one to avoid cx_freeze flushing bug.
|
|
||||||
class dummyStream:
|
class dummyStream:
|
||||||
''' dummyStream behaves like a stream but does nothing. '''
|
|
||||||
def __init__(self): pass
|
def __init__(self): pass
|
||||||
def write(self,data): pass
|
def write(self, data): pass
|
||||||
def read(self,data): pass
|
def read(self, data): pass
|
||||||
def flush(self): pass
|
def flush(self): pass
|
||||||
def close(self): pass
|
def close(self): pass
|
||||||
|
|
||||||
# and now redirect all default streams to this dummyStream:
|
|
||||||
sys.stdout = dummyStream()
|
sys.stdout = dummyStream()
|
||||||
sys.stderr = dummyStream()
|
sys.stderr = dummyStream()
|
||||||
sys.stdin = dummyStream()
|
sys.stdin = dummyStream()
|
||||||
@@ -31,6 +35,3 @@ def main(args):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main(sys.argv[1:])
|
main(sys.argv[1:])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ class TestDialogWindow(QDialog, dialog_note_win.Ui_Dialog):
|
|||||||
|
|
||||||
def main(args, conn=None):
|
def main(args, conn=None):
|
||||||
success = True
|
success = True
|
||||||
app = QApplication(args)
|
from interpreter.test_items import dialog_env
|
||||||
|
dialog_env.setup()
|
||||||
|
app = QApplication(['testium'])
|
||||||
d = TestDialogWindow()
|
d = TestDialogWindow()
|
||||||
d.setFixedSize(387,224)
|
d.setFixedSize(387,224)
|
||||||
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
|
|||||||
@@ -1,29 +1,36 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
|
|
||||||
from PySide6.QtWidgets import (QApplication, QDialog)
|
|
||||||
from PySide6.QtCore import (Qt)
|
|
||||||
from PySide6.QtWidgets import QMessageBox
|
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
|
||||||
def main(args, conn):
|
from PySide6.QtWidgets import (QApplication, QMessageBox)
|
||||||
app = QApplication(sys.argv)
|
from PySide6.QtCore import Qt
|
||||||
reply = QMessageBox.question(None, args[0], args[1], QMessageBox.Yes|QMessageBox.No)
|
|
||||||
|
|
||||||
|
|
||||||
|
def main(args, conn):
|
||||||
|
try:
|
||||||
|
from interpreter.test_items import dialog_env
|
||||||
|
dialog_env.setup()
|
||||||
|
app = QApplication(['testium'])
|
||||||
|
msg = QMessageBox()
|
||||||
|
msg.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
|
msg.setWindowTitle(args[0])
|
||||||
|
msg.setText(args[1])
|
||||||
|
msg.setIcon(QMessageBox.Question)
|
||||||
|
msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
||||||
|
reply = msg.exec()
|
||||||
conn.send(reply)
|
conn.send(reply)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"dialog_question error: {e}", file=sys.stderr)
|
||||||
|
finally:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
if hasattr(sys, "frozen"):
|
if hasattr(sys, "frozen"):
|
||||||
#all standard streams are replaced by dummy one to avoid cx_freeze flushing bug.
|
|
||||||
class dummyStream:
|
class dummyStream:
|
||||||
''' dummyStream behaves like a stream but does nothing. '''
|
|
||||||
def __init__(self): pass
|
def __init__(self): pass
|
||||||
def write(self,data): pass
|
def write(self, data): pass
|
||||||
def read(self,data): pass
|
def read(self, data): pass
|
||||||
def flush(self): pass
|
def flush(self): pass
|
||||||
def close(self): pass
|
def close(self): pass
|
||||||
|
|
||||||
# and now redirect all default streams to this dummyStream:
|
|
||||||
sys.stdout = dummyStream()
|
sys.stdout = dummyStream()
|
||||||
sys.stderr = dummyStream()
|
sys.stderr = dummyStream()
|
||||||
sys.stdin = dummyStream()
|
sys.stdin = dummyStream()
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ class DialogSleepWindow(QDialog, dialog_sleep_win.Ui_SleepDialogWindow):
|
|||||||
|
|
||||||
def main(args, conn=None):
|
def main(args, conn=None):
|
||||||
success = True
|
success = True
|
||||||
app = QApplication(sys.argv)
|
from interpreter.test_items import dialog_env
|
||||||
|
dialog_env.setup()
|
||||||
|
app = QApplication(['testium'])
|
||||||
d = DialogSleepWindow()
|
d = DialogSleepWindow()
|
||||||
d.setFixedSize(379,129)
|
d.setFixedSize(379,129)
|
||||||
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ class TestDialogWindow(QDialog, dialog_value_win.Ui_Dialog):
|
|||||||
|
|
||||||
def main(args, conn=None):
|
def main(args, conn=None):
|
||||||
success = True
|
success = True
|
||||||
app = QApplication(args)
|
from interpreter.test_items import dialog_env
|
||||||
|
dialog_env.setup()
|
||||||
|
app = QApplication(['testium'])
|
||||||
d = TestDialogWindow()
|
d = TestDialogWindow()
|
||||||
d.setFixedSize(387,224)
|
d.setFixedSize(387,224)
|
||||||
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
from multiprocessing import Process, Pipe
|
from interpreter.test_items.test_item import test_run
|
||||||
|
from interpreter.test_items.test_result import TestValue
|
||||||
from interpreter.test_items.test_item import TestItem, test_run
|
|
||||||
from interpreter.test_items.test_result import TestResult, TestValue
|
|
||||||
from interpreter.test_items.dialog_choices_files import choices_dialog
|
from interpreter.test_items.dialog_choices_files import choices_dialog
|
||||||
import libs.testium as tm
|
from interpreter.test_items.test_item_dialog_base import TestItemDialogBase
|
||||||
from lib.tum_except import ETUMSyntaxError, item_load_context
|
|
||||||
from interpreter.utils.constants import TestItemType as cst
|
from interpreter.utils.constants import TestItemType as cst
|
||||||
|
from lib.tum_except import item_load_context
|
||||||
|
import libs.testium as tm
|
||||||
|
|
||||||
|
|
||||||
class TestItemChoicesDialog(TestItem):
|
class TestItemChoicesDialog(TestItemDialogBase):
|
||||||
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
||||||
self._name = cst.TYPE_CHOICES_DLG.item_name
|
self._name = cst.TYPE_CHOICES_DLG.item_name
|
||||||
super().__init__(dict_item, parent, status_queue, filename=filename)
|
super().__init__(dict_item, parent, status_queue, filename=filename)
|
||||||
@@ -24,18 +23,13 @@ class TestItemChoicesDialog(TestItem):
|
|||||||
q = self._prms.expanse(self._question)
|
q = self._prms.expanse(self._question)
|
||||||
choices = self._prms.expanse(self._choices)
|
choices = self._prms.expanse(self._choices)
|
||||||
icon = self._prms.expanse(self._default_icon)
|
icon = self._prms.expanse(self._default_icon)
|
||||||
parent_conn, child_conn = Pipe()
|
result = self._run_dialog_with_result(choices_dialog.main, [self.name(), q, choices, icon])
|
||||||
p = Process(
|
if result is None:
|
||||||
target=choices_dialog.main, args=([self.name(), q, choices, icon], child_conn)
|
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
|
||||||
)
|
return
|
||||||
p.start()
|
val, succ = result
|
||||||
val, succ = parent_conn.recv()
|
|
||||||
p.join()
|
|
||||||
|
|
||||||
self.result.value = val
|
self.result.value = val
|
||||||
|
|
||||||
if succ:
|
if succ:
|
||||||
# The result of the test item is put into the global dict
|
|
||||||
tm.setgd("cs_" + self._name, val)
|
tm.setgd("cs_" + self._name, val)
|
||||||
self.result.set(TestValue.SUCCESS, str(val))
|
self.result.set(TestValue.SUCCESS, str(val))
|
||||||
else:
|
else:
|
||||||
|
|||||||
43
src/testium/interpreter/test_items/test_item_dialog_base.py
Normal file
43
src/testium/interpreter/test_items/test_item_dialog_base.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
from multiprocessing import Process, Pipe
|
||||||
|
|
||||||
|
from interpreter.test_items.test_item import TestItem
|
||||||
|
|
||||||
|
|
||||||
|
class TestItemDialogBase(TestItem):
|
||||||
|
"""Base class for test items that launch a Qt dialog in a subprocess."""
|
||||||
|
|
||||||
|
def _cleanup_process(self, p):
|
||||||
|
if p.is_alive():
|
||||||
|
p.terminate()
|
||||||
|
p.join(timeout=0.2)
|
||||||
|
if p.is_alive():
|
||||||
|
p.kill()
|
||||||
|
p.join()
|
||||||
|
|
||||||
|
def _run_dialog(self, target, args):
|
||||||
|
"""Launch target(args) in a subprocess with no return value.
|
||||||
|
|
||||||
|
Returns the subprocess exit code.
|
||||||
|
"""
|
||||||
|
p = Process(target=target, args=(args,))
|
||||||
|
p.start()
|
||||||
|
while p.is_alive() and not self._is_stopped:
|
||||||
|
p.join(timeout=0.5)
|
||||||
|
self._cleanup_process(p)
|
||||||
|
return p.exitcode
|
||||||
|
|
||||||
|
def _run_dialog_with_result(self, target, args):
|
||||||
|
"""Launch target(args, child_conn) in a subprocess and return what it sends.
|
||||||
|
|
||||||
|
Returns the received value, or None if stopped or if the subprocess crashed.
|
||||||
|
"""
|
||||||
|
parent_conn, child_conn = Pipe()
|
||||||
|
p = Process(target=target, args=(args, child_conn))
|
||||||
|
p.start()
|
||||||
|
result = None
|
||||||
|
while p.is_alive() and not self._is_stopped:
|
||||||
|
if parent_conn.poll(0.5):
|
||||||
|
result = parent_conn.recv()
|
||||||
|
break
|
||||||
|
self._cleanup_process(p)
|
||||||
|
return result
|
||||||
@@ -1,20 +1,18 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
from multiprocessing import Process, Pipe
|
|
||||||
|
|
||||||
from interpreter.test_items.test_item import TestItem, test_run
|
from interpreter.test_items.test_item import test_run
|
||||||
from interpreter.test_items.test_result import TestResult, TestValue
|
from interpreter.test_items.test_result import TestValue
|
||||||
from interpreter.test_items.dialog_image_files import dialog_image
|
from interpreter.test_items.dialog_image_files import dialog_image
|
||||||
import libs.testium as tm
|
from interpreter.test_items.test_item_dialog_base import TestItemDialogBase
|
||||||
from interpreter.utils.constants import TestItemType as cst
|
from interpreter.utils.constants import TestItemType as cst
|
||||||
from lib.tum_except import ETUMSyntaxError, item_load_context
|
from lib.tum_except import item_load_context
|
||||||
|
import libs.testium as tm
|
||||||
|
|
||||||
|
|
||||||
class TestItemImageDialog(TestItem):
|
class TestItemImageDialog(TestItemDialogBase):
|
||||||
"""dialog_image item usage.
|
"""dialog_image item usage.
|
||||||
dialog_image name: Nice image, question: could you press the red button, filename: img.jpg
|
dialog_image name: Nice image, question: could you press the red button, filename: img.jpg
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
||||||
self._name = cst.TYPE_IMAGE_DLG.item_name
|
self._name = cst.TYPE_IMAGE_DLG.item_name
|
||||||
super().__init__(dict_item, parent, status_queue, filename=filename)
|
super().__init__(dict_item, parent, status_queue, filename=filename)
|
||||||
@@ -26,11 +24,6 @@ class TestItemImageDialog(TestItem):
|
|||||||
|
|
||||||
@test_run
|
@test_run
|
||||||
def execute(self):
|
def execute(self):
|
||||||
ourpath = __file__
|
|
||||||
test_file = os.path.join(
|
|
||||||
os.path.dirname(ourpath), "dialog_image_files", "dialog_image.py"
|
|
||||||
)
|
|
||||||
|
|
||||||
q = self._prms.expanse(self._question)
|
q = self._prms.expanse(self._question)
|
||||||
image_path = self._prms.expanse(self._filename)
|
image_path = self._prms.expanse(self._filename)
|
||||||
print("Image Displayed:\n" + q + "\n" + image_path)
|
print("Image Displayed:\n" + q + "\n" + image_path)
|
||||||
@@ -38,29 +31,10 @@ class TestItemImageDialog(TestItem):
|
|||||||
image_path = os.path.normpath(
|
image_path = os.path.normpath(
|
||||||
os.path.join(tm.gd("test_directory"), image_path)
|
os.path.join(tm.gd("test_directory"), image_path)
|
||||||
)
|
)
|
||||||
|
succ = self._run_dialog_with_result(dialog_image.main, [self.name(), q, image_path])
|
||||||
parent_conn, child_conn = Pipe()
|
if succ is None:
|
||||||
p = Process(
|
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
|
||||||
target=dialog_image.main, args=([self.name(), q, image_path], child_conn)
|
elif succ:
|
||||||
)
|
|
||||||
p.start()
|
|
||||||
succ = parent_conn.recv()
|
|
||||||
p.join()
|
|
||||||
if succ:
|
|
||||||
self.result.set(TestValue.SUCCESS)
|
self.result.set(TestValue.SUCCESS)
|
||||||
else:
|
else:
|
||||||
self.result.set(TestValue.FAILURE)
|
self.result.set(TestValue.FAILURE)
|
||||||
|
|
||||||
|
|
||||||
def mypath():
|
|
||||||
if hasattr(sys, "frozen"):
|
|
||||||
return os.path.dirname(sys.executable)
|
|
||||||
return os.path.dirname(__file__)
|
|
||||||
|
|
||||||
|
|
||||||
from multiprocessing import Process
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
p = Process(target=test_dialog.main, args=(["bob", "bab"],))
|
|
||||||
p.start()
|
|
||||||
p.join()
|
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from multiprocessing import Process, Pipe
|
|
||||||
|
|
||||||
from interpreter.test_items.test_item import (TestItem, test_run)
|
from interpreter.test_items.test_item import test_run
|
||||||
from interpreter.test_items.test_result import (TestValue)
|
from interpreter.test_items.test_result import TestValue
|
||||||
from interpreter.test_items.dialog_msg_files import msg_dialog
|
from interpreter.test_items.dialog_msg_files import msg_dialog
|
||||||
|
from interpreter.test_items.test_item_dialog_base import TestItemDialogBase
|
||||||
from interpreter.utils.constants import TestItemType as cst
|
from interpreter.utils.constants import TestItemType as cst
|
||||||
from lib.tum_except import ETUMSyntaxError, item_load_context
|
from lib.tum_except import item_load_context
|
||||||
|
|
||||||
class TestItemMsgDialog(TestItem):
|
|
||||||
|
class TestItemMsgDialog(TestItemDialogBase):
|
||||||
"""dialog_message item usage.
|
"""dialog_message item usage.
|
||||||
dialog_message name: Nice message, question: Open the door and press OK
|
dialog_message name: Nice message, question: Open the door and press OK
|
||||||
"""
|
"""
|
||||||
def __init__(self, dict_item, parent = None, status_queue=None, filename=""):
|
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
||||||
self._name = cst.TYPE_MESSAGE_DLG.item_name
|
self._name = cst.TYPE_MESSAGE_DLG.item_name
|
||||||
super().__init__(dict_item, parent, status_queue, filename=filename)
|
super().__init__(dict_item, parent, status_queue, filename=filename)
|
||||||
self._type = cst.TYPE_MESSAGE_DLG
|
self._type = cst.TYPE_MESSAGE_DLG
|
||||||
@@ -22,28 +23,10 @@ class TestItemMsgDialog(TestItem):
|
|||||||
|
|
||||||
@test_run
|
@test_run
|
||||||
def execute(self):
|
def execute(self):
|
||||||
ourpath = __file__
|
|
||||||
test_file = os.path.join(os.path.dirname(ourpath),
|
|
||||||
'dialog_msg_files',
|
|
||||||
'msg_dialog.py')
|
|
||||||
|
|
||||||
q = self._prms.expanse(self._question)
|
q = self._prms.expanse(self._question)
|
||||||
print("Message Displayed:\n" + q)
|
print("Message Displayed:\n" + q)
|
||||||
parent_conn, child_conn = Pipe()
|
exitcode = self._run_dialog(msg_dialog.main, [self.name(), q])
|
||||||
p=Process(target=msg_dialog.main,
|
if exitcode == 0:
|
||||||
args=([self.name(), q],))
|
|
||||||
p.start()
|
|
||||||
p.join()
|
|
||||||
self.result.set(TestValue.SUCCESS)
|
self.result.set(TestValue.SUCCESS)
|
||||||
|
else:
|
||||||
def mypath():
|
self.result.set(TestValue.FAILURE, f"Dialog subprocess exited with code {exitcode}")
|
||||||
if hasattr(sys, "frozen"):
|
|
||||||
return os.path.dirname(sys.executable)
|
|
||||||
return os.path.dirname(__file__)
|
|
||||||
|
|
||||||
from multiprocessing import Process
|
|
||||||
|
|
||||||
if __name__=='__main__':
|
|
||||||
p=Process(target=msg_dialog.main, args=(['bob', 'bab'],))
|
|
||||||
p.start()
|
|
||||||
p.join()
|
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
import os
|
from interpreter.test_items.test_item import test_run
|
||||||
import sys
|
from interpreter.test_items.test_result import TestValue
|
||||||
from multiprocessing import Process, Pipe
|
|
||||||
|
|
||||||
from interpreter.test_items.test_item import (TestItem, test_run)
|
|
||||||
from interpreter.test_items.test_result import (TestResult, TestValue)
|
|
||||||
from interpreter.test_items.dialog_note_files import test_dialog
|
from interpreter.test_items.dialog_note_files import test_dialog
|
||||||
from lib.tum_except import ETUMSyntaxError, item_load_context
|
from interpreter.test_items.test_item_dialog_base import TestItemDialogBase
|
||||||
import libs.testium as tm
|
|
||||||
from interpreter.utils.constants import TestItemType as cst
|
from interpreter.utils.constants import TestItemType as cst
|
||||||
|
from lib.tum_except import item_load_context
|
||||||
|
import libs.testium as tm
|
||||||
|
|
||||||
class TestItemNoteDialog(TestItem):
|
|
||||||
def __init__(self, dict_item, parent = None, status_queue=None, filename=""):
|
class TestItemNoteDialog(TestItemDialogBase):
|
||||||
|
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
||||||
self._name = cst.TYPE_NOTE_DLG.item_name
|
self._name = cst.TYPE_NOTE_DLG.item_name
|
||||||
super().__init__(dict_item, parent, status_queue, filename=filename)
|
super().__init__(dict_item, parent, status_queue, filename=filename)
|
||||||
self._type = cst.TYPE_NOTE_DLG
|
self._type = cst.TYPE_NOTE_DLG
|
||||||
@@ -20,18 +18,13 @@ class TestItemNoteDialog(TestItem):
|
|||||||
|
|
||||||
@test_run
|
@test_run
|
||||||
def execute(self):
|
def execute(self):
|
||||||
ourpath = __file__
|
|
||||||
test_file = os.path.join(os.path.dirname(ourpath),
|
|
||||||
'dialog_note_files',
|
|
||||||
'test_dialog.py')
|
|
||||||
|
|
||||||
q = self._prms.expanse(self._question)
|
q = self._prms.expanse(self._question)
|
||||||
print("Question:\n" + q)
|
print("Question:\n" + q)
|
||||||
parent_conn, child_conn = Pipe()
|
result = self._run_dialog_with_result(test_dialog.main, [self.name(), q])
|
||||||
p=Process(target=test_dialog.main, args=([self.name(), q],child_conn))
|
if result is None:
|
||||||
p.start()
|
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
|
||||||
val, succ = parent_conn.recv()
|
return
|
||||||
p.join()
|
val, succ = result
|
||||||
tm.setgd(self.name(), val)
|
tm.setgd(self.name(), val)
|
||||||
print("\n" + ("-" * 80) + "\n")
|
print("\n" + ("-" * 80) + "\n")
|
||||||
print("- Test note\n")
|
print("- Test note\n")
|
||||||
@@ -43,15 +36,3 @@ class TestItemNoteDialog(TestItem):
|
|||||||
self.result.set(TestValue.SUCCESS, val)
|
self.result.set(TestValue.SUCCESS, val)
|
||||||
else:
|
else:
|
||||||
self.result.set(TestValue.FAILURE, val)
|
self.result.set(TestValue.FAILURE, val)
|
||||||
|
|
||||||
def mypath():
|
|
||||||
if hasattr(sys, "frozen"):
|
|
||||||
return os.path.dirname(sys.executable)
|
|
||||||
return os.path.dirname(__file__)
|
|
||||||
|
|
||||||
from multiprocessing import Process
|
|
||||||
|
|
||||||
if __name__=='__main__':
|
|
||||||
p=Process(target=test_dialog.main, args=(['bob', 'bab'],))
|
|
||||||
p.start()
|
|
||||||
p.join()
|
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
from multiprocessing import Process, Pipe
|
|
||||||
|
|
||||||
from PySide6.QtWidgets import QMessageBox
|
from PySide6.QtWidgets import QMessageBox
|
||||||
|
|
||||||
from interpreter.test_items.test_item import (TestItem, test_run)
|
from interpreter.test_items.test_item import test_run
|
||||||
from interpreter.test_items.test_result import (TestResult, TestValue)
|
from interpreter.test_items.test_result import TestValue
|
||||||
from interpreter.test_items.dialog_question_files import question_dialog
|
from interpreter.test_items.dialog_question_files import question_dialog
|
||||||
from lib.tum_except import ETUMSyntaxError, item_load_context
|
from interpreter.test_items.test_item_dialog_base import TestItemDialogBase
|
||||||
from interpreter.utils.constants import TestItemType as cst
|
from interpreter.utils.constants import TestItemType as cst
|
||||||
|
from lib.tum_except import item_load_context
|
||||||
|
|
||||||
class TestItemQuestionDialog(TestItem):
|
|
||||||
|
class TestItemQuestionDialog(TestItemDialogBase):
|
||||||
"""dialog_question item usage.
|
"""dialog_question item usage.
|
||||||
dialog_question name: Nice question, question: "If OK, press OK, If not, press cancel"
|
dialog_question name: Nice question, question: "If OK, press OK, If not, press cancel"
|
||||||
"""
|
"""
|
||||||
def __init__(self, dict_item, parent = None, status_queue=None, filename=""):
|
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
||||||
self._name = cst.TYPE_QUESTION_DLG.item_name
|
self._name = cst.TYPE_QUESTION_DLG.item_name
|
||||||
super().__init__(dict_item, parent, status_queue, filename=filename)
|
super().__init__(dict_item, parent, status_queue, filename=filename)
|
||||||
self._type = cst.TYPE_QUESTION_DLG
|
self._type = cst.TYPE_QUESTION_DLG
|
||||||
@@ -24,34 +22,15 @@ class TestItemQuestionDialog(TestItem):
|
|||||||
|
|
||||||
@test_run
|
@test_run
|
||||||
def execute(self):
|
def execute(self):
|
||||||
ourpath = __file__
|
|
||||||
test_file = os.path.join(os.path.dirname(ourpath),
|
|
||||||
'dialog_question_files',
|
|
||||||
'question_dialog.py')
|
|
||||||
|
|
||||||
q = self._prms.expanse(self._question)
|
q = self._prms.expanse(self._question)
|
||||||
print('Question asked:\n' + q + '\n')
|
print('Question asked:\n' + q + '\n')
|
||||||
parent_conn, child_conn = Pipe()
|
succ = self._run_dialog_with_result(question_dialog.main, [self.name(), q])
|
||||||
p=Process(target=question_dialog.main,
|
if succ is None:
|
||||||
args=([self.name(), q],child_conn))
|
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
|
||||||
p.start()
|
return
|
||||||
succ = parent_conn.recv()
|
|
||||||
p.join()
|
|
||||||
if succ == QMessageBox.Yes:
|
if succ == QMessageBox.Yes:
|
||||||
self.result.set(TestValue.SUCCESS)
|
self.result.set(TestValue.SUCCESS)
|
||||||
print('Answer: YES\n')
|
print('Answer: YES\n')
|
||||||
else:
|
else:
|
||||||
self.result.set(TestValue.FAILURE)
|
self.result.set(TestValue.FAILURE)
|
||||||
print('Answer: NO\n')
|
print('Answer: NO\n')
|
||||||
|
|
||||||
def mypath():
|
|
||||||
if hasattr(sys, "frozen"):
|
|
||||||
return os.path.dirname(sys.executable)
|
|
||||||
return os.path.dirname(__file__)
|
|
||||||
|
|
||||||
from multiprocessing import Process
|
|
||||||
|
|
||||||
if __name__=='__main__':
|
|
||||||
p=Process(target=test_dialog.main, args=(['bob', 'bab'],))
|
|
||||||
p.start()
|
|
||||||
p.join()
|
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
import os
|
from interpreter.test_items.test_item import test_run
|
||||||
import sys
|
from interpreter.test_items.test_result import TestValue
|
||||||
from multiprocessing import Process, Pipe
|
|
||||||
|
|
||||||
from interpreter.test_items.test_item import (TestItem, test_run)
|
|
||||||
from interpreter.test_items.test_result import (TestResult, TestValue)
|
|
||||||
from interpreter.test_items.tested_references_files import tested_refs_dialog
|
from interpreter.test_items.tested_references_files import tested_refs_dialog
|
||||||
import libs.testium as tm
|
from interpreter.test_items.test_item_dialog_base import TestItemDialogBase
|
||||||
from lib.tum_except import ETUMSyntaxError, item_load_context
|
|
||||||
from interpreter.utils.constants import TestItemType as cst
|
from interpreter.utils.constants import TestItemType as cst
|
||||||
|
from lib.tum_except import item_load_context
|
||||||
|
import libs.testium as tm
|
||||||
|
|
||||||
class TestItemTestedRefsDialog(TestItem):
|
|
||||||
|
class TestItemTestedRefsDialog(TestItemDialogBase):
|
||||||
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
||||||
self._name = cst.TYPE_REFERENCE_DLG.item_name
|
self._name = cst.TYPE_REFERENCE_DLG.item_name
|
||||||
super().__init__(dict_item, parent, status_queue, filename=filename)
|
super().__init__(dict_item, parent, status_queue, filename=filename)
|
||||||
@@ -21,34 +19,27 @@ class TestItemTestedRefsDialog(TestItem):
|
|||||||
|
|
||||||
@test_run
|
@test_run
|
||||||
def execute(self):
|
def execute(self):
|
||||||
ourpath=__file__
|
q = self._prms.expanse(self._question)
|
||||||
test_file=os.path.join(os.path.dirname(ourpath),
|
init_values = ','.join(self._init_values)
|
||||||
'tested_references_files',
|
result = self._run_dialog_with_result(tested_refs_dialog.main, [self.name(), q, init_values])
|
||||||
'tested_refs_dialog.py')
|
if result is None:
|
||||||
|
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
|
||||||
|
return
|
||||||
|
val, succ = result
|
||||||
|
|
||||||
q=self._prms.expanse(self._question)
|
titems = []
|
||||||
parent_conn, child_conn=Pipe()
|
|
||||||
init_values=','.join(self._init_values)
|
|
||||||
p=Process(target=tested_refs_dialog.main,
|
|
||||||
args=([self.name(), q, init_values],
|
|
||||||
child_conn))
|
|
||||||
p.start()
|
|
||||||
val, succ=parent_conn.recv()
|
|
||||||
p.join()
|
|
||||||
|
|
||||||
titems=[]
|
|
||||||
if len(val) > 0:
|
if len(val) > 0:
|
||||||
i = 0
|
i = 0
|
||||||
for sitem in val.split(','):
|
for sitem in val.split(','):
|
||||||
titem={}
|
titem = {}
|
||||||
telems=sitem.split('/')
|
telems = sitem.split('/')
|
||||||
titem['reference']=telems[0]
|
titem['reference'] = telems[0]
|
||||||
titem['revision']=telems[1]
|
titem['revision'] = telems[1]
|
||||||
titem['serial']=telems[2]
|
titem['serial'] = telems[2]
|
||||||
print("Identification:\n" + str(titem))
|
print("Identification:\n" + str(titem))
|
||||||
titems.append(titem)
|
titems.append(titem)
|
||||||
self.result.reported = {'reference_{}'.format(i): titem}
|
self.result.reported = {'reference_{}'.format(i): titem}
|
||||||
i = i + 1
|
i += 1
|
||||||
self.result.value = titems
|
self.result.value = titems
|
||||||
tm.setgd('tested_items', titems)
|
tm.setgd('tested_items', titems)
|
||||||
if len(val) > 0:
|
if len(val) > 0:
|
||||||
@@ -58,15 +49,3 @@ class TestItemTestedRefsDialog(TestItem):
|
|||||||
self.result.set(TestValue.FAILURE, val)
|
self.result.set(TestValue.FAILURE, val)
|
||||||
else:
|
else:
|
||||||
self.result.set(TestValue.FAILURE, 'The dialog did not return any value')
|
self.result.set(TestValue.FAILURE, 'The dialog did not return any value')
|
||||||
|
|
||||||
def mypath():
|
|
||||||
if hasattr(sys, "frozen"):
|
|
||||||
return os.path.dirname(sys.executable)
|
|
||||||
return os.path.dirname(__file__)
|
|
||||||
|
|
||||||
from multiprocessing import Process
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
p=Process(target=test_dialog.main, args=(['bob', 'bab'],))
|
|
||||||
p.start()
|
|
||||||
p.join()
|
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
import os
|
from interpreter.test_items.test_item import test_run
|
||||||
import sys
|
from interpreter.test_items.test_result import TestValue
|
||||||
from multiprocessing import Process, Pipe
|
|
||||||
|
|
||||||
from interpreter.test_items.test_item import (TestItem, test_run)
|
|
||||||
from interpreter.test_items.test_result import (TestResult, TestValue)
|
|
||||||
from interpreter.test_items.dialog_value_files import test_dialog
|
from interpreter.test_items.dialog_value_files import test_dialog
|
||||||
import libs.testium as tm
|
from interpreter.test_items.test_item_dialog_base import TestItemDialogBase
|
||||||
from lib.tum_except import ETUMSyntaxError, item_load_context
|
|
||||||
from interpreter.utils.constants import TestItemType as cst
|
from interpreter.utils.constants import TestItemType as cst
|
||||||
|
from lib.tum_except import item_load_context
|
||||||
|
import libs.testium as tm
|
||||||
|
|
||||||
class TestItemValueDialog(TestItem):
|
|
||||||
|
class TestItemValueDialog(TestItemDialogBase):
|
||||||
"""dialog_value item usage.
|
"""dialog_value item usage.
|
||||||
dialog_value name: Enter value, question: "Which value did you measure?"
|
dialog_value name: Enter value, question: "Which value did you measure?"
|
||||||
"""
|
"""
|
||||||
def __init__(self, dict_item, parent = None, status_queue=None, filename=""):
|
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
||||||
self._name = cst.TYPE_VALUE_DLG.item_name
|
self._name = cst.TYPE_VALUE_DLG.item_name
|
||||||
super().__init__(dict_item, parent, status_queue, filename=filename)
|
super().__init__(dict_item, parent, status_queue, filename=filename)
|
||||||
self._type = cst.TYPE_VALUE_DLG
|
self._type = cst.TYPE_VALUE_DLG
|
||||||
@@ -24,19 +22,14 @@ class TestItemValueDialog(TestItem):
|
|||||||
|
|
||||||
@test_run
|
@test_run
|
||||||
def execute(self):
|
def execute(self):
|
||||||
ourpath = __file__
|
|
||||||
test_file = os.path.join(os.path.dirname(ourpath),
|
|
||||||
'dialog_value_files',
|
|
||||||
'test_dialog.py')
|
|
||||||
|
|
||||||
q = self._prms.expanse(self._question)
|
q = self._prms.expanse(self._question)
|
||||||
d = self._prms.expanse(self._default)
|
d = self._prms.expanse(self._default)
|
||||||
print("Question:\n" + q)
|
print("Question:\n" + q)
|
||||||
parent_conn, child_conn = Pipe()
|
result = self._run_dialog_with_result(test_dialog.main, [self.name(), q, d])
|
||||||
p=Process(target=test_dialog.main, args=([self.name(), q, d],child_conn))
|
if result is None:
|
||||||
p.start()
|
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
|
||||||
val, succ = parent_conn.recv()
|
return
|
||||||
p.join()
|
val, succ = result
|
||||||
tm.setgd(self.name(), val)
|
tm.setgd(self.name(), val)
|
||||||
print("Answer: " + val)
|
print("Answer: " + val)
|
||||||
if len(val) > 0:
|
if len(val) > 0:
|
||||||
@@ -48,15 +41,3 @@ class TestItemValueDialog(TestItem):
|
|||||||
self.result.set(TestValue.FAILURE, val)
|
self.result.set(TestValue.FAILURE, val)
|
||||||
else:
|
else:
|
||||||
self.result.set(TestValue.FAILURE, 'The dialog did not return any value')
|
self.result.set(TestValue.FAILURE, 'The dialog did not return any value')
|
||||||
|
|
||||||
def mypath():
|
|
||||||
if hasattr(sys, "frozen"):
|
|
||||||
return os.path.dirname(sys.executable)
|
|
||||||
return os.path.dirname(__file__)
|
|
||||||
|
|
||||||
from multiprocessing import Process
|
|
||||||
|
|
||||||
if __name__=='__main__':
|
|
||||||
p=Process(target=test_dialog.main, args=(['bob', 'bab'],))
|
|
||||||
p.start()
|
|
||||||
p.join()
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
|
||||||
from PySide6.QtWidgets import (QApplication, QDialog, QTableWidgetItem)
|
from PySide6.QtWidgets import (QApplication, QDialog, QTableWidgetItem)
|
||||||
@@ -20,7 +19,9 @@ def main(args, conn=None):
|
|||||||
SettingsApplication = 'testium_ref_item'
|
SettingsApplication = 'testium_ref_item'
|
||||||
SettingsLastReference = 'lastReference'
|
SettingsLastReference = 'lastReference'
|
||||||
success = True
|
success = True
|
||||||
app = QApplication(args)
|
from interpreter.test_items import dialog_env
|
||||||
|
dialog_env.setup()
|
||||||
|
app = QApplication(['testium'])
|
||||||
d = TestedRefsWindow()
|
d = TestedRefsWindow()
|
||||||
d.setFixedSize(481,386)
|
d.setFixedSize(481,386)
|
||||||
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
d.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
|
|||||||
Reference in New Issue
Block a user