class SubprocessTask: """monitor a process and show its progress as a Chimera task Provide a SubprocessMonitor.Popen interface so an instance may be handed to code that is expecting a Subprocess.Popen return value. """ def __init__(self, text, subproc, task=None, afterCB=None, *args, **kw): from tasks import Task self._subproc = subproc self._aborted = False if not isinstance(text, basestring): text = ' '.join(text) if task is None: self._ownTask = True self._task = Task(text, self.cancelCB, self.statusCB) self._text = "" else: self._ownTask = False task.addCallbacks(self.cancelCB, self.statusCB) self._task = task self._text = text self._after = afterCB self.returncode = None def poll(self): return self._subproc.poll() def wait(self): import chimera from chimera import tkgui from chimera.update import UPDATE_INTERVAL from time import sleep interval = UPDATE_INTERVAL / 1000.0 # msec -> sec self.statusCB() while self.returncode is None and not self._aborted: sleep(interval) self.statusCB() tkgui.update_windows() if self._aborted: from chimera import NonChimeraError raise NonChimeraError("Raytrace cancelled by user") return self.returncode def statusCB(self): if not self._subproc: return progress = self._subproc.progress() self.returncode = self._subproc.poll() if self.returncode is not None: self.finished() return if self._text: msg = "%s: %d%% complete" % (self._text, int(progress * 100)) else: msg = "%d%% complete" % int(progress * 100) self._task.updateStatus(msg) def cancelCB(self): print "SubprocessTask canceled" # kill/terminate process if self._subproc: # workaround bug 6451 (_subproc should never be None) self._subproc.terminate() self._aborted = True self.finished() def finished(self, value=None): if self._aborted: status = "aborted" else: status = "completed" if self._text: msg = "%s: %s" % (self._text, status) else: msg = status self._task.updateStatus(msg) if self._ownTask: self._task = None else: self._task.removeCallbacks(self.cancelCB, self.statusCB) self._subproc = None if self._after: self._after(self._aborted)