def runsource(self, source, filename="User's code", symbol="single"): """Compile and run some source in the interpreter. Arguments are as for compile_command(). One several things can happen: 1) The input is incorrect; compile_command() raised an exception (SyntaxError or OverflowError). A syntax traceback will be printed by calling the showsyntaxerror() method. ##Crunchy: or calling errors.simplify_syntax_error() 2) The input is incomplete, and more input is required; compile_command() returned None. Nothing happens. 3) The input is complete; compile_command() returned a code object. The code is executed by calling self.runcode() (which also handles run-time exceptions). The return value is True in case 2, False in the other cases (unless an exception is raised). The return value can be used to decide whether to use sys.ps1 or sys.ps2 to prompt the next line. """ try: code = self.compile(source, filename, symbol) except (OverflowError, SyntaxError, ValueError): sys.stderr.write(errors.simplify_traceback(source, self.username)) return False if code is None: return True self.runcode(code, source) return False
def exec_code(code, local_dict, source='', username=None): # tested via test_interface.rst import src.errors as errors # prevent premature import import sys # try: exec code in local_dict except: if source is not None: sys.stderr.write(errors.simplify_traceback(source, username=username)) else: raise
def runcode(self, code, source): """Execute a code object. This version temporarily re-assigns sys.displayhook so as to give feedback about type when echoing a value entered at the prompt. """ saved_dp = sys.displayhook sys.displayhook = self.show_expression_value try: exec_code(code, self.locals, source=source, username=self.username) #exec code in self.locals except: sys.stderr.write(errors.simplify_traceback(source, self.username)) else: if softspace(sys.stdout, 0): print sys.displayhook = saved_dp
def runcode(self, code, source): """Execute a code object. When an exception occurs, errors.simplify_traceback() is called to display a traceback. All exceptions are caught. A note about KeyboardInterrupt: this exception may occur elsewhere in this code, and may not always be caught. The caller should be prepared to deal with it. """ try: exec_code(code, self.locals, source=source, username=self.username) #exec code in self.locals except: sys.stderr.write(errors.simplify_traceback(source, self.username)) else: if softspace(sys.stdout, 0): print('')
def runcode(self, code, source): """Execute a code object. This version temporarily re-assigns sys.displayhook so as to give feedback about type when echoing a value entered at the prompt. """ saved_dp = sys.displayhook sys.displayhook = self.show_expression_value try: exec_code(code, self.locals, source=source, username=self.username) # exec code in self.locals except: sys.stderr.write(errors.simplify_traceback(source, self.username)) else: if softspace(sys.stdout, 0): print sys.displayhook = saved_dp
def runcode(self, code, source): """Execute a code object. When an exception occurs, errors.simplify_traceback() is called to display a traceback. All exceptions are caught. A note about KeyboardInterrupt: this exception may occur elsewhere in this code, and may not always be caught. The caller should be prepared to deal with it. """ try: exec_code(code, self.locals, source=source, username=self.username) # exec code in self.locals except: sys.stderr.write(errors.simplify_traceback(source, self.username)) else: if softspace(sys.stdout, 0): print("")
def run(self): """run the code, redirecting stdout, stderr, stdin and returning the string representing the output """ sys.stdin.register_thread(self.channel) sys.stdout.register_thread(self.channel) sys.stderr.register_thread(self.channel) try: try: self.ccode = compile(self.code, "User's code", 'exec') except: try: if self.friendly: sys.stderr.write(errors.simplify_traceback(self.code, self.username)) else: traceback.print_exc() return except: sys.stderr.write("Recovering from internal error in Interpreter.run()") sys.stderr.write("self.channel =%s"%self.channel) return if not self.ccode: #code does nothing return try: # logging the user input first, if required if self.username and self.channel in config[self.username]['logging_uids']: vlam_type = config[self.username]['logging_uids'][self.channel][1] if vlam_type == 'editor': user_code = self.code.split("\n") log_id = config[self.username]['logging_uids'][self.channel][0] if user_code: user_code = '\n'.join(user_code) if not user_code.endswith('\n'): user_code += '\n' else: user_code = _("# no code entered by user\n") data = "<span class='stdin'>" + user_code + "</span>" config[self.username]['log'][log_id].append(data) log_session(username) exec_code(self.ccode, self.symbols, source=None, username=self.username) #exec self.ccode in self.symbols#, {} # note: previously, the "local" directory used for exec # was simply an empty directory. However, this meant that # module names imported outside a function definition # were not available inside that function. This is why # we have commented out the {} as a reminder; self.symbols # will be used for holding both global and local variables. except: try: if self.friendly: sys.stderr.write(errors.simplify_traceback(self.code, self.username)) else: traceback.print_exc() except: sys.stderr.write("Recovering from internal error in Interpreter.run()") sys.stderr.write(".. after trying to call exec_code.") sys.stderr.write("self.channel = %s"%self.channel) finally: if self.doctest: # attempting to log if self.username and self.channel in config[self.username]['logging_uids']: code_lines = self.code.split("\n") user_code = [] for line in code_lines: # __teststring identifies the beginning of the code # that is passed to a doctest (see vlam_doctest.py) # This will have been appended to the user's code. if line.startswith("__teststring"): break user_code.append(line) log_id = config[self.username]['logging_uids'][self.channel][0] if user_code: user_code = '\n' + '\n'.join(user_code) if not user_code.endswith('\n'): user_code += '\n' else: user_code = _("# no code entered by user\n") # separating each attempts user_code = "\n" + "- "*25 + "\n" + user_code data = "<span class='stdin'>" + user_code + "</span>" config[self.username]['log'][log_id].append(data) log_session(self.username) # proceed with regular output if self.friendly: message, success = errors.simplify_doctest_error_message( self.doctest_out.getvalue()) if success: sys.stdout.write(message) else: sys.stderr.write(message) else: sys.stdout.write(self.doctest_out.getvalue()) sys.stdin.unregister_thread() sys.stdout.unregister_thread() sys.stderr.unregister_thread()
def run(self): """run the code, redirecting stdout, stderr, stdin and returning the string representing the output """ sys.stdin.register_thread(self.channel) sys.stdout.register_thread(self.channel) sys.stderr.register_thread(self.channel) try: try: self.ccode = compile(self.code, "User's code", "exec") except: try: if self.friendly: sys.stderr.write(errors.simplify_traceback(self.code, self.username)) else: traceback.print_exc() return except: sys.stderr.write("Recovering from internal error in Interpreter.run()") sys.stderr.write("self.channel =%s" % self.channel) return if not self.ccode: # code does nothing return try: # logging the user input first, if required if self.username and self.channel in config[self.username]["logging_uids"]: vlam_type = config[self.username]["logging_uids"][self.channel][1] if vlam_type == "editor": user_code = self.code.split("\n") log_id = config[self.username]["logging_uids"][self.channel][0] if user_code: user_code = "\n".join(user_code) if not user_code.endswith("\n"): user_code += "\n" else: user_code = _("# no code entered by user\n") data = "<span class='stdin'>" + user_code + "</span>" config[self.username]["log"][log_id].append(data) log_session(username) exec_code(self.ccode, self.symbols, source=None, username=self.username) # exec self.ccode in self.symbols#, {} # note: previously, the "local" directory used for exec # was simply an empty directory. However, this meant that # module names imported outside a function definition # were not available inside that function. This is why # we have commented out the {} as a reminder; self.symbols # will be used for holding both global and local variables. except: try: if self.friendly: sys.stderr.write(errors.simplify_traceback(self.code, self.username)) else: traceback.print_exc() except: sys.stderr.write("Recovering from internal error in Interpreter.run()") sys.stderr.write(".. after trying to call exec_code.") sys.stderr.write("self.channel = %s" % self.channel) finally: if self.doctest: # attempting to log if self.username and self.channel in config[self.username]["logging_uids"]: code_lines = self.code.split("\n") user_code = [] for line in code_lines: # __teststring identifies the beginning of the code # that is passed to a doctest (see vlam_doctest.py) # This will have been appended to the user's code. if line.startswith("__teststring"): break user_code.append(line) log_id = config[self.username]["logging_uids"][self.channel][0] if user_code: user_code = "\n" + "\n".join(user_code) if not user_code.endswith("\n"): user_code += "\n" else: user_code = _("# no code entered by user\n") # separating each attempts user_code = "\n" + "- " * 25 + "\n" + user_code data = "<span class='stdin'>" + user_code + "</span>" config[self.username]["log"][log_id].append(data) log_session(self.username) # proceed with regular output if self.friendly: message, success = errors.simplify_doctest_error_message(self.doctest_out.getvalue()) if success: sys.stdout.write(message) else: sys.stderr.write(message) else: sys.stdout.write(self.doctest_out.getvalue()) sys.stdin.unregister_thread() sys.stdout.unregister_thread() sys.stderr.unregister_thread()