def simplify_syntax_error(code, ex_type, value, trace, lineno, username): """ print out a syntax error closely based on showsyntaxerror from the code module in the standard library """ filename = _(u"User's code").encode( "utf-8") # will most likely not be used # Work hard to stuff the correct filename in the exception try: msg, (filename, lineno, offset, line) = value except: # Not the format we expect; leave it alone pass else: # Stuff in the right filename value = SyntaxError(msg, (filename, lineno, offset, line)) sys.last_value = value if username and config[username]['friendly']: # ignore that filename stuff! tb_list = traceback.format_exception_only(ex_type, value)[1:] tb_list.insert(0, "Error on line %s:\n" % lineno) else: tb_list = traceback.format_exception_only(ex_type, value) retval = StringIO() map(retval.write, tb_list) out = retval.getvalue().replace("Error on line", _(u"Error on line")) return out.encode("utf-8")
def simplify_syntax_error(code, ex_type, value, trace, lineno, username): """ print out a syntax error closely based on showsyntaxerror from the code module in the standard library """ filename = _("User's code") # will most likely not be used # Work hard to stuff the correct filename in the exception try: msg, (filename, lineno, offset, line) = value except: # Not the format we expect; leave it alone pass else: # Stuff in the right filename value = SyntaxError(msg, (filename, lineno, offset, line)) sys.last_value = value if username and config[username]['friendly']:# ignore that filename stuff! tb_list = traceback.format_exception_only(ex_type, value)[1:] tb_list.insert(0, "Error on line %s:\n"%lineno) else: tb_list = traceback.format_exception_only(ex_type, value) retval = StringIO() list(map(retval.write, tb_list)) out = retval.getvalue().replace("Error on line", _("Error on line") ) return out
class CrunchyChecker: """Class to configure and start a pychecker analysis """ def __init__(self): self._report = None self._code = None self._output_buffer = None def run(self, code): """Make the analysis""" self._code = code # Save the code in a temporary file temp = tempfile.NamedTemporaryFile(suffix = '.py') temp.write(self._code) temp.flush() fname = os.path.basename(temp.name) self._output_buffer = StringIO() checker._printWarnings = self._printWarnings checker.main(['dummy_arg', '--only', temp.name]) # remove all traces of the Temporary file name self._report = self._output_buffer.getvalue().replace(temp.name, 'line') self._report = self._report.replace(fname[:-3] + ":", "") self._output_buffer.close() temp.close() def get_report(self): """Return the full report""" return "Report from pychecker:\n" + self._report def get_global_score(self): """Return the global score or None if not available. This score can be formatted with "%.2f/10" % score It is not computed by pychecker, but here, by the formule: score = 10 - ((number_of_errors / number_of_lines) * 10) """ if not "UNABLE TO IMPORT" in self.get_report(): # Just count non-empty and non-comment lines code_lines = [line for line in self._code.split('\n') \ if line.strip() and not line.strip().startswith('#')] report_lines = [line for line in self.get_report().split('\n') \ if line] if len(report_lines) == 1: return 10 number_of_errors = float(len(report_lines)-1) number_of_lines = float(len(code_lines)) return 10 - ((number_of_errors / number_of_lines) * 10) else: return 0 def _printWarnings(self, warnings, stream=None): """This function call the original checker._printWarnings, but set the stream to self._output_buffer """ original_printWarnings(warnings, self._output_buffer)
class CrunchyChecker: """Class to configure and start a pychecker analysis """ def __init__(self): self._report = None self._code = None self._output_buffer = None def run(self, code): """Make the analysis""" self._code = code # Save the code in a temporary file temp = tempfile.NamedTemporaryFile(suffix='.py') temp.write(self._code) temp.flush() fname = os.path.basename(temp.name) self._output_buffer = StringIO() checker._printWarnings = self._printWarnings checker.main(['dummy_arg', '--only', temp.name]) # remove all traces of the Temporary file name self._report = self._output_buffer.getvalue().replace( temp.name, 'line') self._report = self._report.replace(fname[:-3] + ":", "") self._output_buffer.close() temp.close() def get_report(self): """Return the full report""" return "Report from pychecker:\n" + self._report def get_global_score(self): """Return the global score or None if not available. This score can be formatted with "%.2f/10" % score It is not computed by pychecker, but here, by the formule: score = 10 - ((number_of_errors / number_of_lines) * 10) """ if not "UNABLE TO IMPORT" in self.get_report(): # Just count non-empty and non-comment lines code_lines = [line for line in self._code.split('\n') \ if line.strip() and not line.strip().startswith('#')] report_lines = [line for line in self.get_report().split('\n') \ if line] if len(report_lines) == 1: return 10 number_of_errors = float(len(report_lines) - 1) number_of_lines = float(len(code_lines)) return 10 - ((number_of_errors / number_of_lines) * 10) else: return 0 def _printWarnings(self, warnings, stream=None): """This function call the original checker._printWarnings, but set the stream to self._output_buffer """ original_printWarnings(warnings, self._output_buffer)
def read(self): # tested '''create fake file from a tree, adding DTD and charset information and return its value as a string''' self.fix_divs() # fix required when using etree fake_file = StringIO() fake_file.write(DTD + '\n') self.add_charset() try: self.tree.write(fake_file) except Exception: return handle_exception() return fake_file.getvalue()
def run(self, code): """Make the analysis""" temp = tempfile.NamedTemporaryFile(suffix = '.py') temp.write(code) temp.flush() output_buffer = StringIO() self.linter.reporter.set_output(output_buffer) self.linter.check(temp.name) self._report = output_buffer.getvalue().replace(temp.name, 'line ') output_buffer.close() temp.close()
def run(self, code): """Make the analysis""" temp = tempfile.NamedTemporaryFile(suffix='.py') temp.write(code) temp.flush() output_buffer = StringIO() self.linter.reporter.set_output(output_buffer) self.linter.check(temp.name) self._report = output_buffer.getvalue().replace(temp.name, 'line ') output_buffer.close() temp.close()
def run_sample(name): # tested '''Given a setup script, as a precursor, executes a code sample and compares the output with some expected result.''' if name in code_setups: try: complete_code = code_setups[name] + '\n' + code_samples[name] except KeyError: sys.__stderr__.write("There was an error in run_sample().") else: try: complete_code = code_samples[name] except KeyError: sys.__stderr__.write("There was an error in run_sample.") # since Crunchy often redefines sys.stdout, we can't simply set # it back to sys.__stdout__ after redirection saved_stdout = sys.stdout redirected = StringIO() sys.stdout = redirected exec(complete_code) sys.stdout = saved_stdout return compare(expected_outputs[name], redirected.getvalue())
def run(self, code): """Make the analysis This function is inspired from the check function of the pyflakes start script. """ print("run called in pychecker") self._code = code # Open a buffer for the output output = StringIO() # Start the check try: tree = compiler.parse(self._code) except (SyntaxError, IndentationError): value = sys.exc_info()[1] try: (lineno, offset, line) = value[1][1:] except IndexError: print >> output, _('Could not compile the code.') else : if line.endswith("\n"): line = line[:-1] print >> output, _('line %d: could not compile') % lineno print >> output, line print >> output, " " * (offset-2), "^" self._nb_errors = None else: w = checker.Checker(tree, 'line') w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno)) for warning in w.messages: print >> output, warning self._nb_errors = len(w.messages) # Get the output and remove the irrelevant file path self._report = output.getvalue() # Close the buffer output.close()
def run(self, code): """Make the analysis This function is inspired from the check function of the pyflakes start script. """ print("run called in pychecker") self._code = code # Open a buffer for the output output = StringIO() # Start the check try: tree = compiler.parse(self._code) except (SyntaxError, IndentationError): value = sys.exc_info()[1] try: (lineno, offset, line) = value[1][1:] except IndexError: print >> output, _('Could not compile the code.') else: if line.endswith("\n"): line = line[:-1] print >> output, _('line %d: could not compile') % lineno print >> output, line print >> output, " " * (offset - 2), "^" self._nb_errors = None else: w = checker.Checker(tree, 'line') w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno)) for warning in w.messages: print >> output, warning self._nb_errors = len(w.messages) # Get the output and remove the irrelevant file path self._report = output.getvalue() # Close the buffer output.close()
class Interpreter(KillableThread): """ Run python source asynchronously """ def __init__(self, code, channel, symbols = None, doctest=False, username=None): threading.Thread.__init__(self) self.code = trim_empty_lines_from_end(code) + "\n" # the extra new line character at the end above prevents a syntax error # if the last line is a comment. self.channel = channel if username is not None: self.username = username self.friendly = config[self.username]['friendly'] else: try: pageid = self.channel.split("_")[0] self.username = names[pageid] self.friendly = config[self.username]['friendly'] except: self.friendly = False print ("Exception raised in Interpreter.init(); channel = %s" % self.channel) try: u_print("username = "******"username not defined...") self.username = None try: u_print("pageid in names: ", self.channel.split("_")[0] in names) except: pass self.symbols = {} if symbols is not None: self.symbols.update(symbols) self.doctest = doctest if self.doctest: self.doctest_out = StringIO() self.symbols['doctest_out'] = self.doctest_out 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()
class Interpreter(KillableThread): """ Run python source asynchronously """ def __init__(self, code, channel, symbols=None, doctest=False, username=None): threading.Thread.__init__(self) self.code = trim_empty_lines_from_end(code) + "\n" # the extra new line character at the end above prevents a syntax error # if the last line is a comment. self.channel = channel if username is not None: self.username = username self.friendly = config[self.username]["friendly"] else: try: pageid = self.channel.split("_")[0] self.username = names[pageid] self.friendly = config[self.username]["friendly"] except: self.friendly = False print("Exception raised in Interpreter.init(); channel = %s" % self.channel) try: u_print("username = "******"username not defined...") self.username = None try: u_print("pageid in names: ", self.channel.split("_")[0] in names) except: pass self.symbols = {} if symbols is not None: self.symbols.update(symbols) self.doctest = doctest if self.doctest: self.doctest_out = StringIO() self.symbols["doctest_out"] = self.doctest_out 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 simplify_traceback(code=None, username=None): ''' inspired by simplifytraceback from the code module in the standard library. The first stack item because it is our own code; it is removed in the standard traceback in the code module. ''' try: ex_type, value, trace = sys.exc_info() sys.last_type = ex_type sys.last_traceback = trace sys.last_value = value except: return "Internal error: could not retrieve traceback information." try: lineno = trace.tb_next.tb_lineno except: lineno = trace.tb_lineno if ex_type is SyntaxError: return simplify_syntax_error(code, ex_type, value, trace, lineno, username) if ex_type is SystemExit: value = "Your program exited.\n" tblist = traceback.extract_tb(trace) del tblist[:1] tb_list = traceback.format_list(tblist) if tb_list: tb_list.insert(0, "Traceback (most recent call last):\n") tb_list[len(tb_list):] = traceback.format_exception_only(ex_type, value) saved_tb_list = [] for line in tb_list: saved_tb_list.append(line) if username and config[username]['friendly']: try: if code is not None: code_line = code.split('\n')[lineno - 1] else: try: dummy_filename, dummy_line_number, dummy_function_name, \ code_line = traceback.extract_tb(trace)[2] except: code_line = None del tb_list[0] tb_list[0] = tb_list[0].replace(' File "Crunchy console", line', _("Error on line")) tb_list[0] = tb_list[0].replace(' File "User\'s code", line', _("Error on line")) tb_list[0] = tb_list[0].replace(', in <module>', ':') if code_line is not None: tb_list.insert(1, ">>> " + code_line + "\n") for index, line in enumerate(tb_list): if ' File "Crunchy console", line' in line: tb_list[index] = line.replace(' File "Crunchy console", line', _("called by line")) if ', in <module>' in line: tb_list[index] = line.replace(', in <module>', '') except: tb_list = saved_tb_list retval = StringIO() list(map(retval.write, tb_list)) if ex_type is SystemExit: out = retval.getvalue().replace("Your program exited.", _("Your program exited.") ) return out if debug: if username: added_info = ("Crunchy debug:: In errors.simplify_traceback:\n" "username = %s"%username + "friendly = " + str(config[username]['friendly'])) else: added_info = ("Crunchy debug:: " "In errors.simplify_traceback: username=%s\n"%username) else: added_info = '' return retval.getvalue() + added_info
def simplify_traceback(code=None, username=None): ''' inspired by simplifytraceback from the code module in the standard library. The first stack item because it is our own code; it is removed in the standard traceback in the code module. ''' try: ex_type, value, trace = sys.exc_info() sys.last_type = ex_type sys.last_traceback = trace sys.last_value = value except: return "Internal error: could not retrieve traceback information." try: lineno = trace.tb_next.tb_lineno except: lineno = trace.tb_lineno if ex_type is SyntaxError: return simplify_syntax_error(code, ex_type, value, trace, lineno, username) if ex_type is SystemExit: value = "Your program exited.\n" tblist = traceback.extract_tb(trace) del tblist[:1] tb_list = traceback.format_list(tblist) if tb_list: tb_list.insert(0, "Traceback (most recent call last):\n") tb_list[len(tb_list):] = traceback.format_exception_only(ex_type, value) saved_tb_list = [] for line in tb_list: saved_tb_list.append(line) if username and config[username]['friendly']: try: if code is not None: code_line = code.split('\n')[lineno - 1] else: try: dummy_filename, dummy_line_number, dummy_function_name, \ code_line = traceback.extract_tb(trace)[2] except: code_line = None del tb_list[0] tb_list[0] = tb_list[0].replace(' File "Crunchy console", line', _(u"Error on line")) tb_list[0] = tb_list[0].replace(' File "User\'s code", line', _(u"Error on line")) tb_list[0] = tb_list[0].replace(', in <module>', ':') if code_line is not None: tb_list.insert(1, ">>> " + code_line + "\n") for index, line in enumerate(tb_list): if ' File "Crunchy console", line' in line: tb_list[index] = line.replace( ' File "Crunchy console", line', _(u"called by line")) if ', in <module>' in line: tb_list[index] = line.replace(', in <module>', '') except: tb_list = saved_tb_list retval = StringIO() map(retval.write, tb_list) if ex_type is SystemExit: out = retval.getvalue().replace("Your program exited.", _(u"Your program exited.")) return out.encode("utf-8") if debug: if username: added_info = ("Crunchy debug:: In errors.simplify_traceback:\n" "username = %s" % username + "friendly = " + str(config[username]['friendly'])) else: added_info = ("Crunchy debug:: " "In errors.simplify_traceback: username=%s\n" % username) else: added_info = '' return retval.getvalue().encode("utf-8") + added_info