def test_standard_exception(self): code = """ def foo(): def bar(): # raises a NameError y = _local + 1 # call inner bar() foo() """ try: exec(code) except NameError: exc_type, exc_value, tb = sys.exc_info() formatter = ErrorFormatter() error = formatter.format(exc_type, exc_value, traceback.extract_tb(tb)) del tb # stacktrace will contain file names that are not portable so don't do equality check error_lines = error.splitlines() # python 3 has a slightly different format of the exception error so just check it looks # approximate correct expected_lines = [ "NameError:.*'_local'.*", ' File ".*test_errorformatter.py", line 56, in test_standard_exception', ' exec(.*)', ' File "<string>", line 8, in <module>', ' File "<string>", line 7, in foo', ' File "<string>", line 5, in bar', ] for produced, expected in zip(error_lines, expected_lines): self.assertRegexpMatches(produced, expected)
def test_syntax_error(self): try: exec("if:") except SyntaxError: exc_type, exc_value = sys.exc_info()[:2] formatter = ErrorFormatter() error = formatter.format(exc_type, exc_value, None) expected = """ File "<string>", line 1 if: ^ SyntaxError: invalid syntax """ self.assertEqual(expected, error)
def __init__(self, view, model): super(PythonFileInterpreterPresenter, self).__init__() # attributes self.view = view self.model = model # offset of executing code from start of the file self._code_start_offset = 0 self._is_executing = False self._error_formatter = ErrorFormatter() # connect signals self.model.sig_exec_success.connect(self._on_exec_success) self.model.sig_exec_error.connect(self._on_exec_error) # starts idle self.view.set_status_message(IDLE_STATUS_MSG)
def test_errors_containing_unicode_produce_expected_value_in_python2(self): if not six.PY2: # everything is already unicode in python > 2 return try: exec("é =") except SyntaxError: exc_type, exc_value = sys.exc_info()[:2] formatter = ErrorFormatter() error = formatter.format(exc_type, exc_value, None) expected = """ File "<string>", line 1 é = ^ SyntaxError: invalid syntax """ self.assertEqual(expected, error)
def __init__(self, view, model): super(PythonFileInterpreterPresenter, self).__init__() # attributes self.view = view self.model = model # offset of executing code from start of the file self._code_start_offset = 0 self._is_executing = False self._error_formatter = ErrorFormatter() # If startup code was executed then populate autocomplete self.view.editor.updateCompletionAPI(self.model.generate_calltips()) # connect signals self.model.sig_exec_success.connect(self._on_exec_success) self.model.sig_exec_error.connect(self._on_exec_error) self.model.sig_exec_progress.connect(self._on_progress_update) # starts idle self.view.set_status_message(IDLE_STATUS_MSG)
class PythonFileInterpreterPresenter(QObject): """Presenter part of MVP to control actions on the editor""" MAX_STACKTRACE_LENGTH = 2 def __init__(self, view, model): super(PythonFileInterpreterPresenter, self).__init__() # attributes self.view = view self.model = model # offset of executing code from start of the file self._code_start_offset = 0 self._is_executing = False self._error_formatter = ErrorFormatter() # connect signals self.model.sig_exec_success.connect(self._on_exec_success) self.model.sig_exec_error.connect(self._on_exec_error) # starts idle self.view.set_status_message(IDLE_STATUS_MSG) @property def is_executing(self): return self._is_executing @is_executing.setter def is_executing(self, value): self._is_executing = value def req_abort(self): if self.is_executing: self.model.abort() self.view.set_status_message(ABORTED_STATUS_MSG) def req_execute_async(self, ignore_selection): return self._req_execute_impl(blocking=False, ignore_selection=ignore_selection) def req_execute_async_blocking(self): self._req_execute_impl(blocking=True) def _req_execute_impl(self, blocking, ignore_selection=False): if self.is_executing: return code_str, self._code_start_offset = self._get_code_for_execution(ignore_selection) if not code_str: return self.is_executing = True self.view.set_editor_readonly(True) self.view.set_status_message(RUNNING_STATUS_MSG) return self.model.execute_async(code_str=code_str, line_offset=self._code_start_offset, filename=self.view.filename, blocking=blocking) def _get_code_for_execution(self, ignore_selection): editor = self.view.editor if not ignore_selection and editor.hasSelectedText(): code_str = editor.selectedText() line_from, _, _, _ = editor.getSelection() else: # run everything in the file code_str = editor.text() line_from = 0 return code_str, line_from def _on_exec_success(self, task_result): self._finish(success=True, task_result=task_result) def _on_exec_error(self, task_error): exc_type, exc_value, exc_stack = task_error.exc_type, task_error.exc_value, task_error.stack exc_stack = traceback.extract_tb(exc_stack)[self.MAX_STACKTRACE_LENGTH:] if hasattr(exc_value, 'lineno'): lineno = exc_value.lineno + self._code_start_offset elif exc_stack is not None: try: lineno = exc_stack[0].lineno + self._code_start_offset except (AttributeError, IndexError): # Python 2 fallback try: lineno = exc_stack[-1][1] + self._code_start_offset except IndexError: lineno = -1 else: lineno = -1 sys.stderr.write(self._error_formatter.format(exc_type, exc_value, exc_stack) + os.linesep) self.view.editor.updateProgressMarker(lineno, True) self._finish(success=False, task_result=task_error) def _finish(self, success, task_result): status = 'successfully' if success else 'with errors' status_message = self._create_status_msg(status, task_result.timestamp, task_result.elapsed_time) self.view.set_status_message(status_message) self.view.set_editor_readonly(False) self.is_executing = False def _create_status_msg(self, status, timestamp, elapsed_time): return IDLE_STATUS_MSG + ' ' + LAST_JOB_MSG_TEMPLATE.format(status, timestamp, elapsed_time)
class PythonFileInterpreterPresenter(QObject): """Presenter part of MVP to control actions on the editor""" def __init__(self, view, model): super(PythonFileInterpreterPresenter, self).__init__() # attributes self.view = view self.model = model # offset of executing code from start of the file self._code_start_offset = 0 self._is_executing = False self._error_formatter = ErrorFormatter() # If startup code was executed then populate autocomplete self.view.editor.updateCompletionAPI(self.model.generate_calltips()) # connect signals self.model.sig_exec_success.connect(self._on_exec_success) self.model.sig_exec_error.connect(self._on_exec_error) self.model.sig_exec_progress.connect(self._on_progress_update) # starts idle self.view.set_status_message(IDLE_STATUS_MSG) @property def is_executing(self): return self._is_executing @is_executing.setter def is_executing(self, value): self._is_executing = value def req_abort(self): if self.is_executing: self.model.abort() def req_execute_async(self): if self.is_executing: return self.is_executing = True code_str, self._code_start_offset = self._get_code_for_execution() if not code_str: return self.view.set_editor_readonly(True) self.view.set_status_message(RUNNING_STATUS_MSG) return self.model.execute_async(code_str, self.view.filename) def _get_code_for_execution(self): editor = self.view.editor if editor.hasSelectedText(): code_str = editor.selectedText() line_from, _, _, _ = editor.getSelection() else: code_str = editor.text() line_from = 0 return code_str, line_from def _on_exec_success(self, task_result): self.view.editor.updateCompletionAPI(self.model.generate_calltips()) self._finish(success=True, elapsed_time=task_result.elapsed_time) def _on_exec_error(self, task_error): exc_type, exc_value, exc_stack = task_error.exc_type, task_error.exc_value, \ task_error.stack if hasattr(exc_value, 'lineno'): lineno = exc_value.lineno + self._code_start_offset elif exc_stack is not None: lineno = exc_stack[-1][1] + self._code_start_offset else: lineno = -1 sys.stderr.write( self._error_formatter.format(exc_type, exc_value, exc_stack) + '\n') self.view.editor.updateProgressMarker(lineno, True) self._finish(success=False, elapsed_time=task_error.elapsed_time) def _finish(self, success, elapsed_time): status = 'successfully' if success else 'with errors' self.view.set_status_message( self._create_status_msg(status, elapsed_time)) self.view.set_editor_readonly(False) self.is_executing = False def _create_status_msg(self, status, elapsed_time): return IDLE_STATUS_MSG + ' ' + \ LAST_JOB_MSG_TEMPLATE.format(status, elapsed_time) def _on_progress_update(self, lineno): """Update progress on the view taking into account if a selection of code is running""" self.view.editor.updateProgressMarker(lineno + self._code_start_offset, False)
class PythonFileInterpreterPresenter(QObject): """Presenter part of MVP to control actions on the editor""" MAX_STACKTRACE_LENGTH = 2 def __init__(self, view, model): super(PythonFileInterpreterPresenter, self).__init__() # attributes self.view = view self.model = model # offset of executing code from start of the file self._code_start_offset = 0 self._is_executing = False self._error_formatter = ErrorFormatter() # If startup code was executed then populate autocomplete self.view.editor.updateCompletionAPI(self.model.generate_calltips()) # connect signals self.model.sig_exec_success.connect(self._on_exec_success) self.model.sig_exec_error.connect(self._on_exec_error) self.model.sig_exec_progress.connect(self._on_progress_update) # starts idle self.view.set_status_message(IDLE_STATUS_MSG) @property def is_executing(self): return self._is_executing @is_executing.setter def is_executing(self, value): self._is_executing = value def req_abort(self): if self.is_executing: self.model.abort() def req_execute_async(self): if self.is_executing: return self.is_executing = True code_str, self._code_start_offset = self._get_code_for_execution() if not code_str: return self.view.set_editor_readonly(True) self.view.set_status_message(RUNNING_STATUS_MSG) return self.model.execute_async(code_str, self.view.filename) def _get_code_for_execution(self): editor = self.view.editor if editor.hasSelectedText(): code_str = editor.selectedText() line_from, _, _, _ = editor.getSelection() else: code_str = editor.text() line_from = 0 return code_str, line_from def _on_exec_success(self, task_result): self.view.editor.updateCompletionAPI(self.model.generate_calltips()) self._finish(success=True, elapsed_time=task_result.elapsed_time) def _on_exec_error(self, task_error): exc_type, exc_value, exc_stack = task_error.exc_type, task_error.exc_value, \ task_error.stack exc_stack = traceback.extract_tb(exc_stack)[self.MAX_STACKTRACE_LENGTH:] if hasattr(exc_value, 'lineno'): lineno = exc_value.lineno + self._code_start_offset elif exc_stack is not None: lineno = exc_stack[-1][1] + self._code_start_offset else: lineno = -1 sys.stderr.write(self._error_formatter.format(exc_type, exc_value, exc_stack) + '\n') self.view.editor.updateProgressMarker(lineno, True) self._finish(success=False, elapsed_time=task_error.elapsed_time) def _finish(self, success, elapsed_time): status = 'successfully' if success else 'with errors' self.view.set_status_message(self._create_status_msg(status, elapsed_time)) self.view.set_editor_readonly(False) self.is_executing = False def _create_status_msg(self, status, elapsed_time): return IDLE_STATUS_MSG + ' ' + \ LAST_JOB_MSG_TEMPLATE.format(status, elapsed_time) def _on_progress_update(self, lineno): """Update progress on the view taking into account if a selection of code is running""" self.view.editor.updateProgressMarker(lineno + self._code_start_offset, False)