def test_worker_stop(): procedure = RandomProcedure() file = tempfile.mktemp() results = Results(procedure, file) worker = Worker(results) worker.start() worker.stop() assert worker.should_stop() worker.join()
def test_worker_stop(): p = procedure.TestProcedure() f = tempfile.mktemp() r = Results(p, f) w = Worker(r) w.start() w.stop() assert w.should_stop() w.join()
class Manager(QtCore.QObject): """Controls the execution of :class:`.Experiment` classes by implementing a queue system in which Experiments are added, removed, executed, or aborted. When instantiated, the Manager is linked to a :class:`.Browser` and a PyQtGraph `PlotItem` within the user interface, which are updated in accordance with the execution status of the Experiments. """ _is_continuous = True _start_on_add = True queued = QtCore.QSignal(object) running = QtCore.QSignal(object) finished = QtCore.QSignal(object) failed = QtCore.QSignal(object) aborted = QtCore.QSignal(object) abort_returned = QtCore.QSignal(object) log = QtCore.QSignal(object) def __init__(self, plot, browser, port=5888, log_level=logging.INFO, parent=None): super(Manager, self).__init__(parent=parent) self.experiments = ExperimentQueue() self._worker = None self._running_experiment = None self._monitor = None self.log_level = log_level self.plot = plot self.browser = browser self.port = port def is_running(self): """ Returns True if a procedure is currently running """ return self._running_experiment is not None def running_experiment(self): if self.is_running(): return self._running_experiment else: raise Exception("There is no Experiment running") def _update_progress(self, progress): if self.is_running(): self._running_experiment.browser_item.setProgress(progress) def _update_status(self, status): if self.is_running(): self._running_experiment.procedure.status = status self._running_experiment.browser_item.setStatus(status) def _update_log(self, record): self.log.emit(record) def load(self, experiment): """ Load a previously executed Experiment """ self.plot.addItem(experiment.curve) self.browser.add(experiment) self.experiments.append(experiment) def queue(self, experiment): """ Adds an experiment to the queue. """ self.load(experiment) self.queued.emit(experiment) if self._start_on_add and not self.is_running(): self.next() def remove(self, experiment): """ Removes an Experiment """ self.experiments.remove(experiment) self.browser.takeTopLevelItem( self.browser.indexOfTopLevelItem(experiment.browser_item)) self.plot.removeItem(experiment.curve) def clear(self): """ Remove all Experiments """ for experiment in self.experiments[:]: self.remove(experiment) def next(self): """ Initiates the start of the next experiment in the queue as long as no other experiments are currently running and there is a procedure in the queue. """ if self.is_running(): raise Exception("Another procedure is already running") else: if self.experiments.has_next(): log.debug("Manager is initiating the next experiment") experiment = self.experiments.next() self._running_experiment = experiment self._worker = Worker(experiment.results, port=self.port, log_level=self.log_level) self._monitor = Monitor(self._worker.monitor_queue) self._monitor.worker_running.connect(self._running) self._monitor.worker_failed.connect(self._failed) self._monitor.worker_abort_returned.connect( self._abort_returned) self._monitor.worker_finished.connect(self._finish) self._monitor.progress.connect(self._update_progress) self._monitor.status.connect(self._update_status) self._monitor.log.connect(self._update_log) self._monitor.start() self._worker.start() def _running(self): if self.is_running(): self.running.emit(self._running_experiment) def _clean_up(self): self._worker.join() del self._worker del self._monitor self._worker = None self._running_experiment = None log.debug("Manager has cleaned up after the Worker") def _failed(self): log.debug("Manager's running experiment has failed") experiment = self._running_experiment self._clean_up() self.failed.emit(experiment) def _abort_returned(self): log.debug("Manager's running experiment has returned after an abort") experiment = self._running_experiment self._clean_up() self.abort_returned.emit(experiment) def _finish(self): log.debug("Manager's running experiment has finished") experiment = self._running_experiment self._clean_up() experiment.browser_item.setProgress(100.) experiment.curve.update() self.finished.emit(experiment) if self._is_continuous: # Continue running procedures self.next() def resume(self): """ Resume processing of the queue. """ self._start_on_add = True self._continous = True self.next() def abort(self): """ Aborts the currently running Experiment, but raises an exception if there is no running experiment """ if not self.is_running(): raise Exception("Attempting to abort when no experiment " "is running") else: self._start_on_add = False self._continous = False self._worker.stop() self.aborted.emit(self._running_experiment)
class Manager(QtCore.QObject): """Controls the execution of :class:`.Experiment` classes by implementing a queue system in which Experiments are added, removed, executed, or aborted. When instantiated, the Manager is linked to a :class:`.Browser` and a PyQtGraph `PlotItem` within the user interface, which are updated in accordance with the execution status of the Experiments. """ _is_continuous = True _start_on_add = True queued = QtCore.QSignal(object) running = QtCore.QSignal(object) finished = QtCore.QSignal(object) failed = QtCore.QSignal(object) aborted = QtCore.QSignal(object) abort_returned = QtCore.QSignal(object) log = QtCore.QSignal(object) def __init__(self, plot, browser, port=5888, log_level=logging.INFO, parent=None): super(Manager, self).__init__(parent=parent) self.experiments = ExperimentQueue() self._worker = None self._running_experiment = None self._monitor = None self.log_level = log_level self.plot = plot self.browser = browser self.port = port def is_running(self): """ Returns True if a procedure is currently running """ return self._running_experiment is not None def running_experiment(self): if self.is_running(): return self._running_experiment else: raise Exception("There is no Experiment running") def _update_progress(self, progress): if self.is_running(): self._running_experiment.browser_item.setProgress(progress) def _update_status(self, status): if self.is_running(): self._running_experiment.procedure.status = status self._running_experiment.browser_item.setStatus(status) def _update_log(self, record): self.log.emit(record) def load(self, experiment): """ Load a previously executed Experiment """ self.plot.addItem(experiment.curve) self.browser.add(experiment) self.experiments.append(experiment) def queue(self, experiment): """ Adds an experiment to the queue. """ self.load(experiment) self.queued.emit(experiment) if self._start_on_add and not self.is_running(): self.next() def remove(self, experiment): """ Removes an Experiment """ self.experiments.remove(experiment) self.browser.takeTopLevelItem(self.browser.indexOfTopLevelItem(experiment.browser_item)) self.plot.removeItem(experiment.curve) def clear(self): """ Remove all Experiments """ for experiment in self.experiments[:]: self.remove(experiment) def next(self): """ Initiates the start of the next experiment in the queue as long as no other experiments are currently running and there is a procedure in the queue. """ if self.is_running(): raise Exception("Another procedure is already running") else: if self.experiments.has_next(): log.debug("Manager is initiating the next experiment") experiment = self.experiments.next() self._running_experiment = experiment self._worker = Worker(experiment.results, port=self.port, log_level=self.log_level) self._monitor = Monitor(self._worker.monitor_queue) self._monitor.worker_running.connect(self._running) self._monitor.worker_failed.connect(self._failed) self._monitor.worker_abort_returned.connect(self._abort_returned) self._monitor.worker_finished.connect(self._finish) self._monitor.progress.connect(self._update_progress) self._monitor.status.connect(self._update_status) self._monitor.log.connect(self._update_log) self._monitor.start() self._worker.start() def _running(self): if self.is_running(): self.running.emit(self._running_experiment) def _clean_up(self): self._worker.join() del self._worker del self._monitor self._worker = None self._running_experiment = None log.debug("Manager has cleaned up after the Worker") def _failed(self): log.debug("Manager's running experiment has failed") experiment = self._running_experiment self._clean_up() self.failed.emit(experiment) def _abort_returned(self): log.debug("Manager's running experiment has returned after an abort") experiment = self._running_experiment self._clean_up() self.abort_returned.emit(experiment) def _finish(self): log.debug("Manager's running experiment has finished") experiment = self._running_experiment self._clean_up() experiment.browser_item.setProgress(100.0) experiment.curve.update() self.finished.emit(experiment) if self._is_continuous: # Continue running procedures self.next() def resume(self): """ Resume processing of the queue. """ self._start_on_add = True self._continous = True self.next() def abort(self): """ Aborts the currently running Experiment, but raises an exception if there is no running experiment """ if not self.is_running(): raise Exception("Attempting to abort when no experiment " "is running") else: self._start_on_add = False self._continous = False self._worker.stop() self.aborted.emit(self._running_experiment)