def parseScript(script, name=None, format=None, compilecode=True): if compilecode: def compiler(src): if not isinstance(src, text_type): src = src.decode('utf-8') return compile(src + '\n', '<script>', 'single', CO_DIVISION) else: compiler = lambda src: src if '\n' not in script: # if the script is a single line, compile it like a line # in the interactive interpreter, so that expression # results are shown code = [session.commandHandler(script, compiler)] blocks = None else: pycode = script # check for SPM scripts if format != 'py': pycode = session.scriptHandler(script, name or '', lambda c: c) # replace bare except clauses in the code with "except Exception" # so that ControlStop is not caught pycode = fixupScript(pycode) if not compilecode: # no splitting desired code = [compiler(pycode)] blocks = None else: # long script: split into blocks code, blocks = splitBlocks(pycode) return code, blocks
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 _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 update(self, text, reason, controller, user): """Update the code with a new script. This method is called from a different thread than execute(), so we must unset the _run flag before doing anything to self.curblock, self.code or self.blocks. """ if not self.blocks: raise ScriptError('cannot update single-line script') text = fixupScript(text) newcode, newblocks = splitBlocks(text) # stop execution after the current block self._run.clear() curblock = self.curblock # this may be off by one try: # make sure that everything that has already been executed matches if curblock >= len(newblocks): # insufficient number of new blocks raise ScriptError('new script too short') # compare all executed blocks for i in range(curblock + 1): if not self._compare(self.blocks[i], newblocks[i]): raise ScriptError('new script differs in already executed ' 'part of the code') # everything is ok, replace the script and the remaining blocks self.text = text session.scriptEvent('update', (self.name, self.text)) # also set the updating user as the new user of the script self.user = user if session._experiment and session.mode == MASTER: scr = list(session.experiment.scripts) # convert readonly list scr[self._exp_script_index] = self.text session.experiment.scripts = scr updateLinecache('<script>', text) self.code, self.blocks = newcode, newblocks self.resetSimstate() # let the client know of the update controller.eventfunc('processing', self.serialize()) updatemsg = 'UPDATE (%s)' % reason if reason else 'UPDATE' session.log.log(INPUT, formatScript(self, updatemsg)) finally: # let the script continue execution in any case self._run.set()