예제 #1
0
 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])
예제 #2
0
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)
예제 #3
0
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()
예제 #4
0
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)
예제 #5
0
    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)
예제 #6
0
    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), ""))
예제 #7
0
 def __init__(self, frame, **kwargs):
     FrameSummary.__init__(self, **kwargs)
     self.tb_frame = frame
예제 #8
0
def _tb(fn, lineno, name, text):
    return FrameSummary(fn, lineno, name)
예제 #9
0
    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()
예제 #10
0
 def __init__(self, frame, **kwargs):
     FrameSummary.__init__(self, **kwargs)
     self.tb_frame = frame
예제 #11
0
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))
예제 #12
0
            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.