def test_functions(): assert formatDuration(1) == '1 second' assert formatDuration(4) == '4 seconds' assert formatDuration(154, precise=False) == '3 min' assert formatDuration(154, precise=True) == '2 min, 34 sec' assert formatDuration(7199) == '2 h, 0 min' assert formatDuration(3700) == '1 h, 2 min' assert formatDuration(24 * 3600 + 7240, precise=False) == '1 day, 2 h' assert formatDuration(48 * 3600 - 1) == '2 days, 0 h' assert bitDescription(0x5, (0, 'a'), (1, 'b', 'c'), (2, 'd', 'e')) == 'a, c, d' assert parseConnectionString('[email protected]:pass@host:1301', 1302) == \ {'user': '******', 'password': '******', 'host': 'host', 'port': 1301} assert parseConnectionString('user:@host', 1302) == \ {'user': '******', 'password': '', 'host': 'host', 'port': 1302} assert parseConnectionString('user@host:1301', 1302) == \ {'user': '******', 'password': None, 'host': 'host', 'port': 1301} assert parseConnectionString('user@ho-st:1301', 1302) == \ {'user': '******', 'password': None, 'host': 'ho-st', 'port': 1301} assert parseConnectionString('', 1302) is None assert parseConnectionString('host?', 1302) is None # pylint: disable=range-builtin-not-iterating assert [tuple(x) for x in chunks(range(10), 3)] == \ [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9,)]
def sleep(secs): """Sleep for a given number of seconds. This is different from Python's `time.sleep()` in that it allows breaking and stopping the sleep, and supports dry run mode. Fractional values are supported. Examples: >>> sleep(10) # sleep for 10 seconds >>> sleep(0.5) # sleep for half a second """ session.log.info('sleeping for %.1f seconds...', secs) if session.mode == SIMULATION: session.clock.tick(secs) return def f_notify(tmr): session.breakpoint(2) # allow break and continue here session.action('%s left' % formatDuration(tmr.remaining_time())) session.beginActionScope('Sleeping') session.action('%s left' % formatDuration(secs)) try: tmr = Timer(secs) tmr.wait(interval=1.0, notify_func=f_notify) finally: session.endActionScope()
def on_range_change(self): try: rng = abs(float(self.start.text()) - float(self.stop.text())) secs = rng / float(self.speed.text()) pnts = int(secs / float(self.delta.text())) self.totalLabel.setText('Total: %d points, %s' % (pnts, formatDuration(secs))) except (ValueError, ArithmeticError): self.totalLabel.setText('Total:') self.changed()
def on_range_change(self): try: pnts = self.numpoints.value() rng = abs(float(self.step.text())) secs = pnts * rng / float(self.speed.text()) self.totalLabel.setText('Total: %d points, %s' % (pnts, formatDuration(secs))) except (ValueError, ArithmeticError): self.totalLabel.setText('Total:') self.changed()
def _RunScript(filename, statdevices, debug=False): fn = _scriptfilename(filename) if not path.isfile(fn) and os.access(fn, os.R_OK): raise UsageError('The file %r does not exist or is not readable' % fn) if session.mode == SIMULATION: starttime = session.clock.time for dev in statdevices: if not isinstance(dev, Readable): session.log.warning('unable to collect statistics on %r', dev) continue dev._sim_min = None dev._sim_max = None session.log.info('running user script: %s', fn) try: fp = io.open(fn, 'r', encoding='utf-8') except Exception as e: if session.mode == SIMULATION: session.log.exception('Dry run: error opening script') return raise NicosError('cannot open script %r: %s' % (filename, e)) with fp: code = fp.read() # guard against bare excepts code = fixupScript(code) # quick guard against self-recursion if session.experiment and session.experiment.scripts and \ code.strip() == session.experiment.scripts[-1].strip(): raise NicosError('script %r would call itself, aborting' % filename) def compiler(src): return compile(src + '\n', fn, 'exec', CO_DIVISION) compiled = session.scriptHandler(code, fn, compiler) with _ScriptScope(path.basename(fn), code): try: exec_(compiled, session.namespace) except Exception: if debug: traceback.print_exc() raise session.log.info('finished user script: %s', fn) if session.mode == SIMULATION: session.log.info('simulated minimum runtime: %s', formatDuration(session.clock.time - starttime, precise=False)) for dev in statdevices: if not isinstance(dev, Readable): continue session.log.info('%s: min %s, max %s, last %s %s', dev.name, dev.format(dev._sim_min), dev.format(dev._sim_max), dev.format(dev._sim_value), dev.unit)
def on_range_change(self): try: start = float(self.start.text()) end = float(self.stop.text()) step = float(self.step.text()) counttime = float(self.delta.text()) numpoints = int(round((end - start) / step + 1)) secs = numpoints * counttime self.totalLabel.setText("Total: %d points, %s" % (numpoints, formatDuration(secs))) except (ValueError, ArithmeticError): self.totalLabel.setText("Total:") self.changed()
def _RunCode(code, debug=False): if session.mode == SIMULATION: starttime = session.clock.time code = fixupScript(code) try: exec_(code, session.namespace) except Exception: if debug: traceback.print_exc() raise if session.mode == SIMULATION: session.log.info('simulated minimum runtime: %s', formatDuration(session.clock.time - starttime, precise=False))
def updateTable(self): self.table.setRowCount(0) table = self.measdef.getTable() if not table: return first = table[0] self.table.setRowCount(len(table)) self.table.setColumnCount(len(first)) self.table.setHorizontalHeaderLabels(first.keys()) total_time = 0 for i, entry in enumerate(table): for j, element in enumerate(entry.values()): item = QTableWidgetItem(element.getDispValue()) self.table.setItem(i, j, item) if element.eltype == 'time': total_time += element.getValue() self.table.resizeRowsToContents() self.totalTime.setText(formatDuration(total_time)) self.changed()
def on_client_simresult(self, data): timing, devinfo, uuid = data if uuid != self.simuuid: return self.simuuid = None # show timing if timing < 0: self.simTotalTime.setText('Error occurred') self.simFinished.setText('See messages') else: self.simTotalTime.setText(formatDuration(timing, precise=False)) self.simFinished.setText(formatEndtime(timing)) # device ranges for devname, (_dval, dmin, dmax, aliases) in devinfo.items(): if dmin is not None: aliascol = 'aliases: ' + ', '.join(aliases) if aliases else '' item = QTreeWidgetItem([devname, dmin, '-', dmax, '', aliascol]) self.simRanges.addTopLevelItem(item) self.simRanges.sortByColumn(0, Qt.AscendingOrder)
def f_notify(tmr): session.breakpoint(2) # allow break and continue here session.action('%s left' % formatDuration(tmr.remaining_time()))
def signal(self, name, data=None, exc=None): """Handles any kind of signal/event sent by the daemon.""" try: # try to order the elifs by frequency if name == 'message': if self.in_editing: self.message_queue.append(data) else: self.put_message(data) elif name == 'status': status, line = data if status == STATUS_IDLE or status == STATUS_IDLEEXC: new_status = 'idle' self.stop_pending = False elif status != STATUS_INBREAK: new_status = 'running' else: new_status = 'paused' if status != self.status: self.set_status(new_status) if line != self.current_line: self.current_line = line elif name == 'cache': if data[1].endswith('/scriptpath'): self.scriptpath = self.eval( 'session.experiment.scriptpath', '.') elif name == 'processing': script = data.get('script') if script is None: return self.current_filename = data.get('name') or '' script = script.splitlines() or [''] if script != self.current_script: self.current_script = script self.pending_requests.pop(data['reqid'], None) self.set_status(self.status) elif name == 'request': if 'script' in data: self.pending_requests[data['reqid']] = data self.set_status(self.status) elif name == 'blocked': removed = [ _f for _f in (self.pending_requests.pop(reqid, None) for reqid in data) if _f ] if removed: self.put_client('%d script(s) or command(s) removed from ' 'queue.' % len(removed)) self.show_pending() self.set_status(self.status) elif name == 'updated': if 'script' in data: self.pending_requests[data['reqid']] = data elif name == 'rearranged': old_reqs = self.pending_requests.copy() self.pending_requests.clear() for reqid in data: self.pending_requests[reqid] = old_reqs[reqid] elif name == 'connected': self.reconnect_count = 0 self.initial_update() elif name == 'disconnected': self.put_client('Disconnected from server, use /reconnect to ' 'try reconnecting.') self.current_mode = MASTER self.debug_mode = False self.pending_requests.clear() self.set_status('disconnected') elif name == 'showhelp': self.showhelp(data[1]) elif name == 'simmessage': if data[5] in [self.simuuid, '0']: if not self.in_editing: self.put_message(data, sim=True) elif name == 'simresult': if data and data[2] in [self.simuuid, '0']: timing, devinfo, _ = data if timing < 0: self.put_client('Dry run resulted in an error.') return self.put_client( 'Simulated minimum runtime: %s ' '(finishes approximately %s). Device ranges:' % (formatDuration(timing, precise=False), formatEndtime(timing))) if devinfo: dnwidth = max(map(len, devinfo)) sorteditems = sorted(devinfo.items(), key=lambda x: x[0].lower()) for devname, (_, dmin, dmax, aliases) in sorteditems: aliascol = 'aliases: ' + ', '.join( aliases) if aliases else '' self.put('# %-*s: %10s <-> %-10s %s' % (dnwidth, devname, dmin, dmax, aliascol)) elif name == 'mode': self.current_mode = data self.set_status(self.status) elif name == 'setup': self.scriptpath = self.eval('session.experiment.scriptpath', '.') self.instrument = self.eval('session.instrument.instrument', self.instrument) elif name == 'debugging': self.debug_mode = data readline_finish_callback(False) elif name == 'plugplay': if data[0] == 'added': self.put_client('new sample environment detected: load ' 'setup %r to activate' % data[1]) elif data[0] == 'removed': self.put_client('sample environment removed: unload ' 'setup %r to clear devices' % data[1]) elif name == 'eta': self.handle_eta(data) elif name == 'broken': self.put_error(data) self.reconnect_count = self.RECONNECT_TRIES self.reconnect_time = self.RECONNECT_INTERVAL_SHORT self.schedule_reconnect() elif name == 'failed': if self.reconnect_count: self.schedule_reconnect() else: self.put_error(data) elif name == 'error': self.put_error(data) # and we ignore all other signals except Exception as e: self.put_error('In %s event handler: %s.' % (name, e))
def _update_time(self): self.totalLbl.setText('Total time: %s' % formatDuration(self.getSettings()['totaltime']))
def multiWait(devices): """Wait for the *devices*. Returns a dictionary mapping devices to current values after waiting. This is the main waiting loop to be used when waiting for multiple devices. It checks the device status until all devices are OK or errored. Errors raised are handled like in the following way: The error is logged, and the first exception with the highest serverity (exception in `CONTINUE_EXECPTIONS` < `SKIP_EXCPTIONS` < other exceptions) is re-raised at the end. *baseclass* allows to restrict the devices waited on. """ from nicos.core.device import Waitable def get_target_str(): return ', '.join( '%s -> %s' % (dev, dev.format(dev.target)) if hasattr(dev, 'target') else str(dev) for dev in reversed(devlist)) delay = 0.3 final_exc = None devlist = list(devIter(devices, baseclass=Waitable, allwaiters=True)) session.log.debug('multiWait: initial devices %s, all waiters %s', devices, devlist) values = {} loops = -2 # wait 2 iterations for full loop eta_update = 1 if session.mode != SIMULATION else 0 first_ts = currenttime() session.beginActionScope('Waiting') eta_str = '' target_str = get_target_str() session.action(target_str) try: while devlist: session.log.debug('multiWait: iteration %d, devices left %s', loops, devlist) loops += 1 for dev in devlist[:]: try: done = dev.isCompleted() if done: dev.finish() except Exception: final_exc = filterExceptions(sys.exc_info(), final_exc) # remove this device from the waiters - we might still have # its subdevices in the list so that multiWait() should not # return until everything is either OK or ERROR devlist.remove(dev) if devlist: # at least one more device left, show the exception now dev.log.exception('while waiting') continue if not done: # we found one busy dev, normally go to next iteration # until this one is done (saves going through the whole # list of devices and doing unnecessary HW communication) if loops % 10: break # every 10 loops, go through everything to get an accurate # display in the action line continue if dev in devices: # populate the results dictionary, but only with the values # of excplicitly given devices values[dev] = dev.read() # this device is done: don't wait for it anymore devlist.remove(dev) target_str = get_target_str() session.action(eta_str + target_str) if devlist: if eta_update >= 1: eta_update -= 1 now = currenttime() eta = {dev.estimateTime(now - first_ts) for dev in devlist} eta.discard(None) # use max here as we wait for ALL movements to finish eta_str = ('estimated %s left / ' % formatDuration(max(eta)) if eta else '') session.action(eta_str + target_str) session.delay(delay) eta_update += delay if final_exc: reraise(*final_exc) finally: session.endActionScope() session.log.debug('multiWait: finished') return values