def __post_init__(self, function, test_id): file_frame = FrameSummary( inspect.getfile(function), docs_start_lineno(function) + self.path.line, function.__name__, lookup_line=False, ) dynamic_frame = FrameSummary(test_id, 1, function.__name__, lookup_line=False, line=self.path) self.stack = StackSummary.from_list([file_frame, dynamic_frame])
def format_operator_stack(tb): """ Extract operator stacktrace from traceback """ operator_stack = [] for frame, lineno in walk_tb(tb): code = frame.f_code filename = code.co_filename locals_ = frame.f_locals mod_name = frame.f_globals["__name__"] maybe_op = locals_.get("self", None) if not isinstance(maybe_op, Operator): continue op_name = type(maybe_op).__qualname__ qualname = f"{mod_name}.{op_name}.{code.co_name}" if op_name: operator_stack.append( FrameSummary(filename, lineno, qualname, lookup_line=False, locals=None)) operator_stack.reverse() if operator_stack: return format_list(operator_stack)
def _format_stack(stack, user=False): if len(stack) == 0: return '' if user: stack = [ FrameSummary(os.path.relpath(i.filename), i.lineno, i.name, locals=i.locals, line=i.line) for i in stack ] # Put the newline at the beginning, since this helps our formatting later. return '\n' + ''.join(traceback.format_list(stack)).rstrip()
def construct_user_code_exc(function, lineno, executed_code, exc_type, exc_value, exc_traceback): """ Not generic enough to make it a real class constructor """ exc_traceback = exc_traceback.tb_next.tb_next exc = TracebackException(exc_type, exc_value, exc_traceback) exc.stack[0]._line = executed_code first = FrameSummary( inspect.getfile(function), docs_start_lineno(function) + lineno, function.__name__, lookup_line=False, ) exc.stack.insert(0, first) return UserCodeException(exc)
def emit(self, record): if record.exc_info: if isinstance(record.exc_info[1], SyntaxError): e = record.exc_info[1] record.msg = e.msg # Figure out where to put the caret. text = e.text.expandtabs().rstrip() dedent = len(text) - len(text.lstrip()) offset = 4 - dedent - 1 + e.offset record.full_stack = [ FrameSummary(e.filename, e.lineno, '<module>', line=e.text + '\n' + ' ' * offset + '^') ] else: if not record.msg: record.msg = record.exc_info[0].__name__ elif self.debug: record.msg = '{}: {}'.format(record.exc_info[0].__name__, record.msg) record.full_stack = traceback.extract_tb(record.exc_info[2]) record.exc_info = None pre, stack, post = _filter_stack(record.full_stack) record.stack_pre = _format_stack(pre) record.stack = _format_stack(stack, user=True) record.stack_post = _format_stack(post) if len(stack): record.user_pathname = os.path.relpath(stack[-1][0]) record.user_lineno = stack[-1][1] else: record.user_pathname = record.pathname record.user_lineno = record.lineno if len(stack) or self.debug: return super().emit(record) record.show_stack = False logging.root.handle(record)
def __init__(self, exc_obj, exc_tb, varsSoFar={}, execTime=0): # skip arepl traceback - the user should just see their own error exc_tb = exc_tb.tb_next self.traceback_exception = TracebackException(type(exc_obj), exc_obj, exc_tb) self.friendly_message = "".join(self.traceback_exception.format()) self.varsSoFar = pickle_user_vars(varsSoFar, get_settings().default_filter_vars, get_settings().default_filter_types) self.execTime = execTime # stack is empty in event of a syntax error # This is problematic because frontend has to handle syntax/regular error differently # to make it easier populate stack so frontend can handle them the same way if self.traceback_exception.exc_type is SyntaxError: self.traceback_exception.stack.append( FrameSummary(self.traceback_exception.filename, int(self.traceback_exception.lineno), ""))
def __init__(self, frame, **kwargs): FrameSummary.__init__(self, **kwargs) self.tb_frame = frame
def _tb(fn, lineno, name, text): return FrameSummary(fn, lineno, name)
def load_script(self, script_path: Path, external_args: str = '', reloading=False) -> None: import shlex from traceback import FrameSummary, TracebackException self.toolbars.playback.stop() self.statusbar.label.setText('Evaluating') self.script_path = script_path sys.path.append(str(self.script_path.parent)) # Rewrite args so external args will be forwarded correctly if external_args: self.external_args = shlex.split(external_args) try: argv_orig = sys.argv sys.argv = [script_path.name] + self.external_args except AttributeError: pass try: # pylint: disable=exec-used exec(self.script_path.read_text(encoding='utf-8'), {'__file__': sys.argv[0]}) except Exception as e: # pylint: disable=broad-except self.script_exec_failed = True logging.error(e) te = TracebackException.from_exception(e) # remove the first stack frame, which contains our exec() invocation del te.stack[0] # replace <string> with script path only for the first stack frames # in order to keep intact exec() invocations down the stack # that we're not concerned with for i, frame in enumerate(te.stack): if frame.filename == '<string>': te.stack[i] = FrameSummary(str(self.script_path), frame.lineno, frame.name) else: break print(''.join(te.format())) self.handle_script_error( f'''An error occured while evaluating script: \n{str(e)} \nSee console output for details.''') return finally: sys.argv = argv_orig sys.path.pop() self.script_exec_failed = False if len(vs.get_outputs()) == 0: logging.error('Script has no outputs set.') self.handle_script_error('Script has no outputs set.') return if not reloading: self.toolbars.main.rescan_outputs() for toolbar in self.toolbars: toolbar.on_script_loaded() self.switch_output(self.OUTPUT_INDEX) self.load_storage() else: self.load_storage() for toolbar in self.toolbars: toolbar.on_script_loaded()
def __init__(self, frame, **kwargs): FrameSummary.__init__(self, **kwargs) self.tb_frame = frame
def insertTextToFile(new_block: str, stack_pos: traceback.FrameSummary, figure_id_line: str): """ insert a text block into a file """ figure_id_line = lineToId(figure_id_line) block = None written = False written_end = False lineno_stack = None # open a temporary file with the same name for writing with open(stack_pos.filename + ".tmp", 'w', encoding="utf-8") as fp2: addLineCounter(fp2) # open the current python file for reading with open(stack_pos.filename, 'r', encoding="utf-8") as fp1: # iterate over all lines and line numbers for fp1.lineno, line in enumerate(fp1, start=1): # if we are currently reading a pylustrator block if block is not None: # add the line to the block block.add(line) # and see if we have found the end if line.strip().startswith("#% end:"): block.end() line = "" # if there is a new pylustrator block elif line.strip().startswith("#% start:"): block = Block(line) # if we are currently reading a block, continue with the next line if block is not None and not block.finished: continue # the current block is finished if block is not None: # either it is the block we want to save, then replace the old block with the new if block.id == figure_id_line: # remember that we wrote the new block written = fp2.lineno + 1 # write the new block to the target file instead of the current block indent = block.indent for line_text in new_block: fp2.write(indent + line_text + "\n") written_end = fp2.lineno # or it is another block, then we just write it else: # the we just copy the current block into the new file fp2.write(block.text) # we already handled this block block = None # if we are at the entry point (e.g. plt.show()) if fp1.lineno == stack_pos.lineno: # and if we not have written the new block if not written: written = fp2.lineno + 1 # we write it now to the target file indent = getIndent(line) for line_text in new_block: fp2.write(indent + line_text + "\n") written_end = fp2.lineno # and we store the position where we will write the entry point (e.g. the plt.show()) lineno_stack = fp2.lineno + 1 # transfer the current line to the new file fp2.write(line) # update the position of the entry point, as we have inserted stuff in the new file which can change the position stack_pos.lineno = lineno_stack # now copy the temporary file over the old file with open(stack_pos.filename + ".tmp", 'r', encoding="utf-8") as fp2: with open(stack_pos.filename, 'w', encoding="utf-8") as fp1: for line in fp2: fp1.write(line) print("save", figure_id_line, "to", stack_pos.filename, "line %d-%d" % (written, written_end))
self.fail("No exception raised from extension?!") if raiser is None: skipMsg = "raiser extension not available" test_failureConstructionWithMungedStackSucceeds.skip = skipMsg # On Python 3.5, extract_tb returns "FrameSummary" objects, which are almost # like the old tuples. This being different does not affect the actual tests # as we are testing that the input works, and that extract_tb returns something # reasonable. if sys.version_info < (3, 5): _tb = lambda fn, lineno, name, text: (fn, lineno, name, text) else: from traceback import FrameSummary _tb = lambda fn, lineno, name, text: FrameSummary(fn, lineno, name) class FormattableTracebackTests(SynchronousTestCase): """ Whitebox tests that show that L{failure._Traceback} constructs objects that can be used by L{traceback.extract_tb}. If the objects can be used by L{traceback.extract_tb}, then they can be formatted using L{traceback.format_tb} and friends. """ def test_singleFrame(self): """ A C{_Traceback} object constructed with a single frame should be able to be passed to L{traceback.extract_tb}, and we should get a singleton list containing a (filename, lineno, methodname, line) tuple.