Source code for schrodinger.application.job_monitor.job_monitor_diagnostics_dialog

import os
from datetime import datetime

from schrodinger.application.job_monitor import diagnostics_dialog_ui
from schrodinger.models import mappers
from schrodinger.models import parameters
from schrodinger.Qt import QtCore
from schrodinger.Qt import QtGui
from schrodinger.tasks import tasks
from schrodinger.ui.qt.basewidgets import BaseDialog
from schrodinger.utils import subprocess

DIAGNOSTICS_STATUS = "Collecting diagnostics..."

MULTI_JOB_DIAGNOSTICS_INFO = """
<p>Archive files containing the diagnostics information have <br/>been added
to the current working directory for each of the<br/>selected jobs.
</p><p>No structures were included in the archives, and all directory <br/>
names were hidden.
</p>
"""

SINGLE_JOB_DIAGNOSTICS_INFO = """
<p>An archive file containing the diagnostics information has<br/>been added to
 the current working directory.</p><p>No structures were included in the
 archive, and all directory<br/>names were hidden.</p>
"""


[docs]class CollectJobDiagnosticsModel(parameters.CompoundParam): job_ids: list
[docs]class CollectJobDiagnosticsDialog(mappers.MapperMixin, BaseDialog): """ :ivar updateStatusBar: a signal to update the status of `CollectJobDiagnosticsTask`. :vartype updateStatusBar: QtCore.pyqtSignal """ model_class = CollectJobDiagnosticsModel ui_module = diagnostics_dialog_ui updateStatusBar = QtCore.pyqtSignal(str)
[docs] def __init__(self, job_ids, parent=None): super().__init__(parent) self.model.job_ids = job_ids
[docs] def initSetUp(self): super().initSetUp() self.setWindowTitle("Job Diagnostics Collected") self.ui.info_icon.setPixmap( QtGui.QPixmap(":/job_monitor/icons/info-h.png")) self.ui.ok_btn.clicked.connect(self.close)
[docs] def startTask(self): self.updateStatusBar.emit(DIAGNOSTICS_STATUS) self.task = CollectJobDiagnosticsTask(input=self.model) self.task.start() self.task.statusChanged.connect(self.onTaskStatusChanged) self.close()
[docs] def onTaskStatusChanged(self, status): t = self.task if status is t.DONE and t.output.success: status = MULTI_JOB_DIAGNOSTICS_INFO if len( self.model.job_ids) > 1 else SINGLE_JOB_DIAGNOSTICS_INFO self.ui.info_label.setText(status) self.run() elif status is t.DONE and not t.output.success: self.warning(f"Postmortem generation failed. Log at " f"{t.getLogPath()}") elif status is t.FAILED: self.warning("Postmortem generation failed.") self.updateStatusBar.emit("")
[docs]class CollectJobDiagnosticsTask(tasks.ThreadFunctionTask): input: CollectJobDiagnosticsModel
[docs] class output(parameters.CompoundParam): success: bool
[docs] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if len(self.input.job_ids) > 1: now = datetime.now() time_stamp = now.strftime("%d%b%Y_%H%M") self.name = f"Diagnostic_Archives_{time_stamp}" task_dir_spec = self.AUTO_TASKDIR if os.path.exists(self.name): task_dir_spec = self.name self.specifyTaskDir(task_dir_spec)
[docs] def mainFunction(self): o = self.output o.success = generate_postmortem(self.input.job_ids, self.getLogPath(), self.getTaskDir())
[docs] def getLogPath(self): return self.getTaskFilename("postmortem-error.log")
[docs]def generate_postmortem(job_ids, log_path, task_dir): args = create_postmortem_args(job_ids) try: with open(log_path, "w") as error_output: exit_code = subprocess.call(args, stdout=error_output, stderr=error_output, cwd=task_dir) except OSError: # Raised when OS fails to open file in write mode return False success = exit_code == 0 return success
[docs]def create_postmortem_args(job_ids): args = ["jsc", "postmortem"] args.extend(job_ids) return args