def __init__(self, filename, source): global TK_ROOT self.filename = filename self.source = source self.report = RunReport() self.tk_root = TK_ROOT self.running = True ## This is a hack so let's check... try: self.tk_root.nametowidget('.') except e: raise ValueError("TK Root is not set (please report)")
def run_module(self, event=None): """ Run the code : give the file name and code will be run from the source file """ # already running if self.running_interpreter_callback: if self.running_interpreter_proxy and self.running_interpreter_proxy.process.is_alive( ): report = RunReport() report.set_header("\n====== STOP ======\n") report.add_execution_error('error', tr('User interruption')) report.set_footer("\n==================\n") self.running_interpreter_callback(False, report) self.running_interpreter_callback = None return # not (yet) running if self.editor_list.get_size() == 0: self.main_view.console.no_file_to_run_message() return reply = self.editor_list.get_current_editor().maybesave_run() if (reply != "cancel"): file_name = self.editor_list.get_current_editor().long_title() self.update_title() self.status_bar.update_save_label(file_name) self.console.run(file_name)
def run_module(self, event=None): """ Run the code : give the file name and code will be run from the source file """ # already running if self.running_interpreter_callback: if self.running_interpreter_proxy and self.running_interpreter_proxy.process.is_alive(): report = RunReport() report.set_header("\n====== STOP ======\n") report.add_execution_error('error', tr('User interruption')) report.set_footer("\n==================\n") self.running_interpreter_callback(False, report) self.running_interpreter_callback = None return # not (yet) running if self.editor_list.get_size() == 0: self.main_view.console.no_file_to_run_message() return reply = self.editor_list.get_current_editor().maybesave_run() if (reply != "cancel"): file_name = self.editor_list.get_current_editor().long_title() self.update_title() self.status_bar.update_save_label(file_name) self.console.run(file_name)
def __init__(self, tk_root, filename, source): self.filename = filename self.source = source self.report = RunReport() self.tk_root = tk_root self.running = True ## This is a hack so let's check... try: self.tk_root.nametowidget('.') except e: raise ValueError("TK Root is not set (please report)")
def run_module(self, event=None): """ Run the code : give the file name and code will be run from the source file """ tracing.user_is_interacting() # already running if self.running_interpreter_callback: if self.running_interpreter_proxy and self.running_interpreter_proxy.process.is_alive( ): report = RunReport() report.set_header("\n====== STOP ======\n") report.add_execution_error('error', tr('User interruption'), class_name='UserTerminatedError') report.set_footer("\n==================\n") self.running_interpreter_callback(False, report) self.running_interpreter_callback = None return # not (yet) running if self.editor_list.get_size() == 0: self.main_view.console.no_file_to_run_message() return reply = self.editor_list.get_current_editor().maybesave_run() if (reply != "cancel"): self.editor_list.get_current_editor().send_update_changed_line( force_sending=True) tracing.send_statement( "started", "execution", { "https://www.lip6.fr/mocah/invalidURI/extensions/mode": tr(self.mode) }) tracing.save_execution_start() file_name = self.editor_list.get_current_editor().long_title() self.update_title() self.status_bar.update_save_label(file_name) self.console.run(file_name)
class FullRunner: """ Runs a code under the full mode """ def __init__(self, filename, source): self.filename = filename self.source = source self.report = RunReport() def get_report(self): """ Return the report """ return self.report def execute_or_eval(self, mode, locals): """ Run the code """ basic_interpreter = InteractiveInterpreter(locals=locals) with tempfile.TemporaryFile(mode='w+', prefix='interpreter_error') as error_output: original_error = sys.stderr sys.stderr = error_output try: if mode == 'exec': code = compile(self.source, self.filename, 'exec') else: code = compile(self.expr, '<string>', 'eval') except: InteractiveInterpreter.showsyntaxerror(self.filename) sys.stderr.seek(0) result = sys.stderr.read() self.report.add_compilation_error('error', err_type='SyntaxError', details=result) return False else: # No compilation errors here if mode == 'exec': result = basic_interpreter.runcode(code) sys.stderr.seek(0) result = sys.stderr.read() if result: self.report.add_compilation_error('error', err_type='SyntaxError', details=result) return False else: sys.stdout.seek(0) result = sys.stdout.read() self.report.set_result(result) return True else: # mode eval try: result = eval(code, locals, locals) except Exception as err: a, b, tb = sys.exc_info() # Get the traceback object # Extract the information for the traceback corresponding to the error # inside the source code : [0] refers to the result = exec(code) # traceback, [1] refers to the last error inside code filename, lineno, file_type, line = traceback.extract_tb(tb)[1] print(traceback.format_exception(a, b, tb)) tb_str = "".join(traceback.format_exception_only(a, b)) self.report.add_execution_error('error', a.__name__, details=str(err)) return False self.report.set_result(result) return True finally: sys.stderr = original_error def execute(self, locals): """ Run the code """ return self.execute_or_eval('exec', locals) def evaluate(self, expr, locals): """ Lanches the evaluation with the locals dict built before """ self.expr = expr result = self.execute_or_eval('eval', locals) self.expr = None return result
def __init__(self, filename, source): self.filename = filename self.source = source self.report = RunReport()
def __init__(self, dbstate, uistate): RunReport(dbstate, uistate, "DescendantBookReport", "descendant_book", "Descendant Book", "DescendantBookReport", "DescendantBookOptions")
class StudentRunner: """ Runs a code under the student mode """ def __init__(self, filename, source): global TK_ROOT self.filename = filename self.source = source self.report = RunReport() self.tk_root = TK_ROOT self.running = True ## This is a hack so let's check... try: self.tk_root.nametowidget('.') except e: raise ValueError("TK Root is not set (please report)") def get_report(self): """ Return the report """ return self.report def execute(self, locals): """ Run the file : customized parsing for checking rules, compile and execute """ # Compile the code and get the AST from it, which will be used for all # the conventions checkings that need to be done try: self.AST = ast.parse(self.source, self.filename) # Handle the different kinds of compilation errors except IndentationError as err: self.report.add_compilation_error('error', tr("Bad indentation"), err.lineno, err.offset) return False except SyntaxError as err: self.report.add_compilation_error('error', tr("Syntax error"), err.lineno, err.offset, details=err.text) return False except Exception as err: typ, exc, tb = sys.exc_info() self.report.add_compilation_error('error', str(typ), err.lineno, err.offset, details=str(err)) return False # No compilation error here # perform the local checks if not self.check_rules(self.report): return False else: return self.run(locals) # Run the code if it passed all the convention tests def _extract_error_details(self, err): err_str = err.args[0] start = err_str.find("'") + 1 end = err_str.find("'", start + 1) details = err_str[start:end] return details def _exec_or_eval(self, mode, code, globs, locs): assert mode=='exec' or mode=='eval' try: if mode=='exec': result = exec(code, globs, locs) elif mode=='eval': result = eval(code, globs, locs) except TypeError as err: a, b, tb = sys.exc_info() filename, lineno, file_type, line = traceback.extract_tb(tb)[-1] err_str = self._extract_error_details(err) self.report.add_execution_error('error', tr("Type error"), lineno, details=str(err)) return (False, None) except NameError as err: a, b, tb = sys.exc_info() # Get the traceback object # Extract the information for the traceback corresponding to the error # inside the source code : [0] refers to the result = exec(code) # traceback, [1] refers to the last error inside code filename, lineno, file_type, line = traceback.extract_tb(tb)[-1] err_str = self._extract_error_details(err) self.report.add_execution_error('error', tr("Name error (unitialized variable?)"), lineno, details=err_str) return (False, None) except ZeroDivisionError: a, b, tb = sys.exc_info() filename, lineno, file_type, line = traceback.extract_tb(tb)[-1] self.report.add_execution_error('error', tr("Division by zero"), lineno if mode=='exec' else None) return (False, None) except AssertionError: a, b, tb = sys.exc_info() lineno=None traceb = traceback.extract_tb(tb) if len(traceb) > 1: filename, lineno, file_type, line = traceb[-1] self.report.add_execution_error('error', tr("Assertion error (failed test?)"), lineno) return (False, None) except Exception as err: a, b, tb = sys.exc_info() # Get the traceback object # Extract the information for the traceback corresponding to the error # inside the source code : [0] refers to the result = exec(code) # traceback, [1] refers to the last error inside code lineno=None traceb = traceback.extract_tb(tb) if len(traceb) > 1: filename, lineno, file_type, line = traceb[-1] self.report.add_execution_error('error', a.__name__, lineno, details=str(err)) return (False, None) finally: self.running = False return (True, result) def run(self, locals): """ Run the code, add the execution errors to the rapport, if any """ locals = install_locals(locals) code = compile(self.source, self.filename, 'exec') (ok, result) = self._exec_or_eval('exec', code, locals, locals) if not ok: return False # if no error get the output sys.stdout.seek(0) result = sys.stdout.read() self.report.set_output(result) return True def evaluate(self, expr, locals): """ Lanches the evaluation with the locals dict built before """ locals = install_locals(locals) (ok, result) = self._exec_or_eval('eval', expr, locals, locals) if not ok: return False else: sys.stdout.seek(0) outp = sys.stdout.read() self.report.set_output(outp) self.report.set_result(result) return True def check_rules(self, report): """ Check if the code follows the class rules """ if not self.check_asserts(): return False if not self.check_specifications(): return False return True def check_specifications(self): """ Is there a valid specification for each function ? """ # Put the checking code here return True def check_asserts(self): """ Are there asserts at the end of the source code ? """ # TODO : a finer check is needed return True
class FullRunner: """ Runs a code under the full mode """ def __init__(self, filename, source): self.filename = filename self.source = source self.report = RunReport() def get_report(self): """ Return the report """ return self.report def execute_or_eval(self, mode, locals): """ Run the code """ basic_interpreter = InteractiveInterpreter(locals=locals) with tempfile.TemporaryFile( mode='w+', prefix='interpreter_error') as error_output: original_error = sys.stderr sys.stderr = error_output try: if mode == 'exec': code = compile(self.source, self.filename, 'exec') else: code = compile(self.expr, '<string>', 'eval') except: InteractiveInterpreter.showsyntaxerror(self.filename) sys.stderr.seek(0) result = sys.stderr.read() self.report.add_compilation_error('error', err_type='SyntaxError', details=result) return False else: # No compilation errors here if mode == 'exec': result = basic_interpreter.runcode(code) sys.stderr.seek(0) result = sys.stderr.read() if result: self.report.add_compilation_error( 'error', err_type='SyntaxError', details=result) return False else: sys.stdout.seek(0) result = sys.stdout.read() self.report.set_result(result) return True else: # mode eval try: result = eval(code, locals, locals) except Exception as err: a, b, tb = sys.exc_info() # Get the traceback object # Extract the information for the traceback corresponding to the error # inside the source code : [0] refers to the result = exec(code) # traceback, [1] refers to the last error inside code filename, lineno, file_type, line = traceback.extract_tb( tb)[1] print(traceback.format_exception(a, b, tb)) tb_str = "".join(traceback.format_exception_only(a, b)) self.report.add_execution_error('error', a.__name__, details=str(err)) return False self.report.set_result(result) return True finally: sys.stderr = original_error def execute(self, locals): """ Run the code """ return self.execute_or_eval('exec', locals) def evaluate(self, expr, locals): """ Lanches the evaluation with the locals dict built before """ self.expr = expr result = self.execute_or_eval('eval', locals) self.expr = None return result
class StudentRunner: """ Runs a code under the student mode """ def __init__(self, tk_root, filename, source): self.filename = filename self.source = source self.report = RunReport() self.tk_root = tk_root self.running = True ## This is a hack so let's check... try: self.tk_root.nametowidget('.') except e: raise ValueError("TK Root is not set (please report)") def get_report(self): """ Return the report """ return self.report def execute(self, locals): """ Run the file : customized parsing for checking rules, compile and execute """ # Compile the code and get the AST from it, which will be used for all # the conventions checkings that need to be done try: self.AST = ast.parse(self.source, self.filename) # Handle the different kinds of compilation errors except IndentationError as err: self.report.add_compilation_error('error', tr("Bad indentation"), err.lineno, err.offset) return False except SyntaxError as err: self.report.add_compilation_error('error', tr("Syntax error"), err.lineno, err.offset, details=err.text) return False except Exception as err: typ, exc, tb = sys.exc_info() self.report.add_compilation_error('error', str(typ), err.lineno, err.offset, details=str(err)) return False # No parsing error here # perform the local checks ret_val = True if not self.check_rules(self.report): ret_val = False self.run(locals) # we still run the code even if there is a convention error else: ret_val = self.run(locals) # Run the code if it passed all the convention tests if ret_val: self.report.nb_passed_tests = self.nb_asserts return ret_val def _extract_error_details(self, err): err_str = err.args[0] start = err_str.find("'") + 1 end = err_str.find("'", start + 1) details = err_str[start:end] return details def _exec_or_eval(self, mode, code, globs, locs): assert mode=='exec' or mode=='eval' try: if mode=='exec': result = exec(code, globs, locs) elif mode=='eval': result = eval(code, globs, locs) except TypeError as err: a, b, tb = sys.exc_info() filename, lineno, file_type, line = traceback.extract_tb(tb)[-1] err_str = self._extract_error_details(err) self.report.add_execution_error('error', tr("Type error"), lineno, details=str(err)) return (False, None) except NameError as err: a, b, tb = sys.exc_info() # Get the traceback object # Extract the information for the traceback corresponding to the error # inside the source code : [0] refers to the result = exec(code) # traceback, [1] refers to the last error inside code filename, lineno, file_type, line = traceback.extract_tb(tb)[-1] err_str = self._extract_error_details(err) self.report.add_execution_error('error', tr("Name error (unitialized variable?)"), lineno, details=err_str) return (False, None) except ZeroDivisionError: a, b, tb = sys.exc_info() filename, lineno, file_type, line = traceback.extract_tb(tb)[-1] self.report.add_execution_error('error', tr("Division by zero"), lineno if mode=='exec' else None) return (False, None) except AssertionError: a, b, tb = sys.exc_info() lineno=None traceb = traceback.extract_tb(tb) if len(traceb) > 1: filename, lineno, file_type, line = traceb[-1] self.report.add_execution_error('error', tr("Assertion error (failed test?)"), lineno) return (True, None) except Exception as err: a, b, tb = sys.exc_info() # Get the traceback object # Extract the information for the traceback corresponding to the error # inside the source code : [0] refers to the result = exec(code) # traceback, [1] refers to the last error inside code lineno=None traceb = traceback.extract_tb(tb) if len(traceb) > 1: filename, lineno, file_type, line = traceb[-1] self.report.add_execution_error('error', a.__name__, lineno, details=str(err)) return (False, None) finally: self.running = False return (True, result) def run(self, locals): """ Run the code, add the execution errors to the rapport, if any """ locals = install_locals(locals) code = None try: code = compile(self.source, self.filename, 'exec') except SyntaxError as err: self.report.add_compilation_error('error', tr("Syntax error"), err.lineno, err.offset, details=str(err)) return False except Exception as err: typ, exc, tb = sys.exc_info() self.report.add_compilation_error('error', str(typ), err.lineno, err.offset, details=str(err)) return False (ok, result) = self._exec_or_eval('exec', code, locals, locals) #if not ok: # return False # if no error get the output sys.stdout.seek(0) result = sys.stdout.read() self.report.set_output(result) return ok def evaluate(self, expr, locals): """ Launches the evaluation with the locals dict built before """ locals = install_locals(locals) (ok, result) = self._exec_or_eval('eval', expr, locals, locals) if not ok: return False else: sys.stdout.seek(0) outp = sys.stdout.read() self.report.set_output(outp) self.report.set_result(result) return True def check_rules(self, report): """ Check if the code follows the class rules """ if not self.check_asserts(): return False if not self.check_specifications(): return False if not self.check_types(): return False return True def check_specifications(self): """ Is there a valid specification for each function ? """ # Put the checking code here return True def check_asserts(self): """ Are there asserts at the end of the source code ? """ self.nb_asserts = 0 defined_funs = set() funcalls = set() for node in self.AST.body: #print("node: {}".format(node)) if isinstance(node, ast.Assert): #print("assert found: {}".format(node)) call_visit = FunCallsVisitor() call_visit.visit(node) self.nb_asserts += 1 funcalls.update(call_visit.funcalls) elif isinstance(node, ast.FunctionDef): defined_funs.add(node.name) #print("defined funs = {}".format(defined_funs)) #print("funcalls = {}".format(funcalls)) self.report.nb_defined_funs = len(defined_funs) missing = defined_funs.difference(funcalls) if missing: self.report.add_convention_error('warning', tr('Missing tests') , details="\n" + tr('Untested functions: ') + "{}".format(missing) + "\n") elif defined_funs: # all the functions are tested at least once self.report.add_convention_error('run', tr('All functions tested'), details="==> " + tr("All functions tested (good)")) return True def check_types(self): type_ctx = typecheck_from_ast(self.AST, self.filename, self.source) fatal_error = False if len(type_ctx.type_errors) == 0: # no type error self.report.add_convention_error('run', tr('Program type-checked'), details=tr('==> the program is type-checked (very good)\n')) return True # convert type errors to report messages for type_error in type_ctx.type_errors: type_error.report(self.report) if type_error.is_fatal(): fatal_error = True #print("fatal_error = ", str(fatal_error)) return not fatal_error
class StudentRunner: """ Runs a code under the student mode """ def __init__(self, tk_root, filename, source): self.filename = filename self.source = source self.report = RunReport() self.tk_root = tk_root self.running = True ## This is a hack so let's check... try: self.tk_root.nametowidget('.') except e: raise ValueError("TK Root is not set (please report)") def get_report(self): """ Return the report """ return self.report def execute(self, locals): """ Run the file : customized parsing for checking rules, compile and execute """ # Compile the code and get the AST from it, which will be used for all # the conventions checkings that need to be done try: self.AST = ast.parse(self.source, self.filename) # Handle the different kinds of compilation errors except IndentationError as err: self.report.add_compilation_error('error', tr("Bad indentation"), err.lineno, err.offset) return False except SyntaxError as err: self.report.add_compilation_error('error', tr("Syntax error"), err.lineno, err.offset, details=err.text) return False except Exception as err: typ, exc, tb = sys.exc_info() self.report.add_compilation_error('error', str(typ), err.lineno, err.offset, details=str(err)) return False # No parsing error here # perform the local checks ret_val = True if not self.check_rules(self.report): ret_val = False self.run( locals ) # we still run the code even if there is a convention error else: ret_val = self.run( locals) # Run the code if it passed all the convention tests if ret_val: self.report.nb_passed_tests = self.nb_asserts return ret_val def _extract_error_details(self, err): err_str = err.args[0] start = err_str.find("'") + 1 end = err_str.find("'", start + 1) details = err_str[start:end] return details def _exec_or_eval(self, mode, code, globs, locs): assert mode == 'exec' or mode == 'eval' try: if mode == 'exec': print(ast.dump(self.AST)) self.AST = FunctionDefVisitor().visit(self.AST) ast.fix_missing_locations(self.AST) print(ast.dump(self.AST)) visitor = AstVisitor() for node in self.AST.body: visitor.visit(node) #compiled = compile(self.AST, filename = "<string>", mode="exec") result = exec(code, globs, locs) elif mode == 'eval': result = eval(code, globs, locs) except TypeError as err: a, b, tb = sys.exc_info() filename, lineno, file_type, line = traceback.extract_tb(tb)[-1] err_str = self._extract_error_details(err) self.report.add_execution_error('error', tr("Type error"), lineno, details=str(err)) return (False, None) except NameError as err: a, b, tb = sys.exc_info() # Get the traceback object # Extract the information for the traceback corresponding to the error # inside the source code : [0] refers to the result = exec(code) # traceback, [1] refers to the last error inside code filename, lineno, file_type, line = traceback.extract_tb(tb)[-1] err_str = self._extract_error_details(err) self.report.add_execution_error( 'error', tr("Name error (unitialized variable?)"), lineno, details=err_str) return (False, None) except ZeroDivisionError: a, b, tb = sys.exc_info() filename, lineno, file_type, line = traceback.extract_tb(tb)[-1] self.report.add_execution_error('error', tr("Division by zero"), lineno if mode == 'exec' else None) return (False, None) except AssertionError: a, b, tb = sys.exc_info() lineno = None traceb = traceback.extract_tb(tb) if len(traceb) > 1: filename, lineno, file_type, line = traceb[-1] self.report.add_execution_error( 'error', tr("Assertion error (failed test?)"), lineno) return (True, None) except PreconditionException: # "a, b, tb = sys.exc_info() # lineno=None # traceb = traceback.extract_tb(tb) # if len(traceb) > 1: # filename, lineno, file_type, line = traceb[-1] # self.report.add_execution_error('error', tr("Precondition error"), lineno)" print("ICI") return (True, None) except Exception as err: a, b, tb = sys.exc_info() # Get the traceback object # Extract the information for the traceback corresponding to the error # inside the source code : [0] refers to the result = exec(code) # traceback, [1] refers to the last error inside code lineno = None traceb = traceback.extract_tb(tb) if len(traceb) > 1: filename, lineno, file_type, line = traceb[-1] self.report.add_execution_error('error', a.__name__, lineno, details=str(err)) return (False, None) finally: self.running = False return (True, result) def run(self, locals): """ Run the code, add the execution errors to the rapport, if any """ locals = install_locals(locals) code = None try: code = compile(self.source, self.filename, 'exec') except SyntaxError as err: self.report.add_compilation_error('error', tr("Syntax error"), err.lineno, err.offset, details=str(err)) return False except Exception as err: typ, exc, tb = sys.exc_info() self.report.add_compilation_error('error', str(typ), err.lineno, err.offset, details=str(err)) return False (ok, result) = self._exec_or_eval('exec', code, locals, locals) #if not ok: # return False # if no error get the output sys.stdout.seek(0) result = sys.stdout.read() self.report.set_output(result) return ok def evaluate(self, expr, locals): """ Launches the evaluation with the locals dict built before """ locals = install_locals(locals) (ok, result) = self._exec_or_eval('eval', expr, locals, locals) if not ok: return False else: sys.stdout.seek(0) outp = sys.stdout.read() self.report.set_output(outp) self.report.set_result(result) return True def check_rules(self, report): """ Check if the code follows the class rules """ if not self.check_asserts(): return False if not self.check_specifications(): return False if not self.check_types(): return False return True def check_specifications(self): """ Is there a valid specification for each function ? """ # Put the checking code here return True def check_asserts(self): """ Are there asserts at the end of the source code ? """ self.nb_asserts = 0 defined_funs = set() funcalls = set() for node in self.AST.body: #print("node: {}".format(node)) if isinstance(node, ast.Assert): #print("assert found: {}".format(node)) call_visit = FunCallsVisitor() call_visit.visit(node) self.nb_asserts += 1 funcalls.update(call_visit.funcalls) elif isinstance(node, ast.FunctionDef): defined_funs.add(node.name) #print("defined funs = {}".format(defined_funs)) #print("funcalls = {}".format(funcalls)) self.report.nb_defined_funs = len(defined_funs) missing = defined_funs.difference(funcalls) if missing: self.report.add_convention_error('warning', tr('Missing tests'), details="\n" + tr('Untested functions: ') + "{}".format(missing) + "\n") elif defined_funs: # all the functions are tested at least once self.report.add_convention_error('run', tr('All functions tested'), details="==> " + tr("All functions tested (good)")) return True def check_types(self): type_ctx = typecheck_from_ast(self.AST, self.filename, self.source) fatal_error = False if len(type_ctx.type_errors) == 0: # no type error self.report.add_convention_error( 'run', tr('Program type-checked'), details=tr('==> the program is type-checked (very good)\n')) return True # convert type errors to report messages for type_error in type_ctx.type_errors: type_error.report(self.report) if type_error.is_fatal(): fatal_error = True #print("fatal_error = ", str(fatal_error)) return not fatal_error