예제 #1
0
    def run(self, args):
        co = self.proc.curframe.f_code
        name = co.co_name

        try:
            opts, args = getopt(args[1:], "hpPAto:O", [
                "help", "parent", "pretty", "AST", 'tree', "offset=", "offsets"
            ])
        except GetoptError as err:
            # print help information and exit:
            print(str(
                err))  # will print something like "option -a not recognized"
            return

        show_parent = False
        show_ast = False
        offset = None
        show_offsets = False
        for o, a in opts:
            if o in ("-h", "--help"):
                self.proc.commands['help'].run(['help', 'deparse'])
                return
            elif o in ("-O", "--offsets"):
                show_offsets = True
            elif o in ("-p", "--parent"):
                show_parent = True
            elif o in ("-A", "--tree", '--AST'):
                show_ast = True
            elif o in ("-o", '--offset'):
                offset = a
            else:
                self.errmsg("unhandled option '%s'" % o)
            pass
        pass
        nodeInfo = None

        try:
            float_version = sysinfo2float()
        except:
            self.errmsg(sys.exc_info()[1])
            return
        if len(args) >= 1 and args[0] == '.':
            temp_filename, name_for_code = deparse_and_cache(co, self.errmsg)
            if not temp_filename:
                return
            self.print_text(''.join(getlines(temp_filename)))
            return
        elif show_offsets:
            deparsed = deparse_code(float_version, co, is_pypy=IS_PYPY)
            self.section("Offsets known:")
            m = self.columnize_commands(
                list(sorted(deparsed.offsets.keys(), key=lambda x: str(x[0]))))
            self.msg_nocr(m)
            return
        elif offset is not None:
            mess = ("The 'deparse' command when given an argument requires an"
                    " instruction offset. Got: '%s'" % offset)
            last_i = self.proc.get_an_int(offset, mess)
            if last_i is None:
                return
        else:
            last_i = self.proc.curframe.f_lasti
            if last_i == -1: last_i = 0

        try:
            deparsed = deparse_code(float_version, co, is_pypy=IS_PYPY)
            nodeInfo = deparsed_find((name, last_i), deparsed, co)
            if not nodeInfo:
                self.errmsg(
                    "Can't find exact offset %d; giving inexact results" %
                    last_i)
                deparsed = deparse_code_around_offset(co.co_name,
                                                      last_i,
                                                      float_version,
                                                      co,
                                                      is_pypy=IS_PYPY)
        except:
            self.errmsg(sys.exc_info()[1])
            self.errmsg("error in deparsing code at offset %d" % last_i)
            return
        if not nodeInfo:
            nodeInfo = deparsed_find((name, last_i), deparsed, co)
        if nodeInfo:
            extractInfo = deparsed.extract_node_info(nodeInfo)
            parentInfo = None
            # print extractInfo
            if show_ast:
                p = deparsed.ast
                if show_parent:
                    parentInfo, p = deparsed.extract_parent_info(nodeInfo.node)
                self.msg(p)
            if extractInfo:
                self.rst_msg("*instruction:* %s" % (nodeInfo.node))
                self.print_text(extractInfo.selectedLine)
                self.msg(extractInfo.markerLine)
                if show_parent:
                    if not parentInfo:
                        parentInfo, p = deparsed.extract_parent_info(
                            nodeInfo.node)
                    if parentInfo:
                        self.section("Contained in...")
                        self.rst_msg("\t*Grammar Symbol:* %s" % p.kind)
                        self.print_text(parentInfo.selectedLine)
                        self.msg(parentInfo.markerLine)
                    pass
                pass
            pass
        elif last_i == -1:
            if name:
                self.msg("At beginning of %s " % name)
            elif self.core.filename(None):
                self.msg("At beginning of program %s" %
                         self.core.filename(None))
            else:
                self.msg("At beginning")
        else:
            self.errmsg(
                "haven't recorded info for offset %d. Offsets I know are:" %
                last_i)
            m = self.columnize_commands(
                list(sorted(deparsed.offsets.keys(), key=lambda x: str(x[0]))))
            self.msg_nocr(m)
        return
예제 #2
0
    def run(self, args):
        proc = self.proc
        dbg_obj  = self.core.debugger
        listsize = dbg_obj.settings['listsize']
        filename, first, last = parse_list_cmd(proc, args, listsize)
        curframe = proc.curframe

        if filename is None: return

        # Sometimes such as due to decompilation we might not really
        # have an idea based on the listing where we really are.
        # Setting "show_marks" to false will disable marking breakpoint
        # and current line numbers.
        show_marks = True

        filename = pyficache.unmap_file(pyficache.pyc2py(filename))

        if filename == "<string>" and proc.curframe.f_code:
            # Deparse the code object into a temp file and remap the line from code
            # into the corresponding line of the tempfile
            co = proc.curframe.f_code
            temp_filename, name_for_code = deparse_and_cache(co, proc.errmsg)
            if temp_filename:
                filename = temp_filename
                show_marks = False
            pass

        # We now have range information. Do the listing.
        max_line = pyficache.size(filename)
        if max_line is None:
            self.errmsg('No file %s found; using "deparse" command instead to show source' %
                        filename)
            proc.commands['deparse'].run(['deparse'])
            return

        canonic_filename = os.path.realpath(os.path.normcase(filename))

        if first > max_line:
            self.errmsg('Bad start line %d - file "%s" has only %d lines'
                        % (first, filename, max_line))
            return

        if last > max_line:
            self.msg('End position changed to last line %d ' % max_line)
            last = max_line

        bplist = self.core.bpmgr.bplist
        opts = {
            'reload_on_change' : self.settings['reload'],
            'output'           : self.settings['highlight'],
            'strip_nl'         : False,
            }

        if 'style' in self.settings:
            opts['style'] = self.settings['style']

        if first <= 0:
            first = 1
        try:
            for lineno in range(first, last+1):
                line = pyficache.getline(filename, lineno, opts)
                if line is None:
                    line = linecache.getline(filename, lineno,
                                             proc.frame.f_globals)
                    pass
                if line is None:
                    self.msg('[EOF]')
                    break
                else:
                    line = line.rstrip('\n')
                    s = proc._saferepr(lineno).rjust(3)
                    if len(s) < 5: s += ' '
                    if (show_marks and
                        (canonic_filename, lineno,) in list(bplist.keys())):
                        bp    = bplist[(canonic_filename, lineno,)][0]
                        a_pad = '%02d' % bp.number
                        s    += bp.icon_char()
                    else:
                        s    += ' '
                        a_pad = '  '
                        pass
                    if (curframe and lineno == inspect.getlineno(curframe)
                        and show_marks):
                        s += '->'
                        if 'plain' != self.settings['highlight']:
                            s = colorize('bold', s)
                    else:
                        s += a_pad
                        pass
                    self.msg(s + '\t' + line)
                    proc.list_lineno = lineno
                    pass
                pass
            pass
        except KeyboardInterrupt:
            pass
        return False
예제 #3
0
def print_location(proc_obj):
    """Show where we are. GUI's and front-end interfaces often
    use this to update displays. So it is helpful to make sure
    we give at least some place that's located in a file.
    """
    i_stack = proc_obj.curindex
    if i_stack is None or proc_obj.stack is None:
        return False
    core_obj = proc_obj.core
    dbgr_obj = proc_obj.debugger
    intf_obj = dbgr_obj.intf[-1]

    # Evaluation routines like "exec" don't show useful location
    # info. In these cases, we will use the position before that in
    # the stack.  Hence the looping below which in practices loops
    # once and sometimes twice.
    remapped_file = None
    source_text = None
    while i_stack >= 0:
        frame_lineno = proc_obj.stack[i_stack]
        i_stack -= 1
        frame, lineno = frame_lineno

        #         # Next check to see that local variable breadcrumb exists and
        #         # has the magic dynamic value.
        #         # If so, it's us and we don't normally show this.a
        #         if 'breadcrumb' in frame.f_locals:
        #             if self.run == frame.f_locals['breadcrumb']:
        #                 break

        filename = Mstack.frame2file(core_obj, frame, canonic=False)
        if '<string>' == filename and dbgr_obj.eval_string:
            remapped_file = filename
            filename = pyficache.unmap_file(filename)
            if '<string>' == filename:
                remapped = cmdfns.source_tempfile_remap(
                    'eval_string', dbgr_obj.eval_string)
                pyficache.remap_file(filename, remapped)
                filename = remapped
                lineno = pyficache.unmap_file_line(filename, lineno)
                pass
            pass
        elif '<string>' == filename:
            source_text = deparse_fn(frame.f_code)
            filename = "<string: '%s'>" % source_text
            pass
        else:
            m = re.search('^<frozen (.*)>', filename)
            if m and m.group(1) in pyficache.file2file_remap:
                remapped_file = pyficache.file2file_remap[m.group(1)]
                pass
            elif filename in pyficache.file2file_remap:
                remapped_file = pyficache.unmap_file(filename)
                # FIXME: a remapped_file shouldn't be the same as its unmapped version
                if remapped_file == filename:
                    remapped_file = None
                    pass
                pass
            elif m and m.group(1) in sys.modules:
                remapped_file = m.group(1)
                pyficache.remap_file(filename, remapped_file)
            pass

        opts = {
            'reload_on_change': proc_obj.settings('reload'),
            'output': proc_obj.settings('highlight')
        }

        if 'style' in proc_obj.debugger.settings:
            opts['style'] = proc_obj.settings('style')

        pyficache.update_cache(filename)
        line = pyficache.getline(filename, lineno, opts)
        if not line:
            if (not source_text and filename.startswith("<string: ")
                    and proc_obj.curframe.f_code):
                # Deparse the code object into a temp file and remap the line from code
                # into the corresponding line of the tempfile
                co = proc_obj.curframe.f_code
                temp_filename, name_for_code = deparse_and_cache(
                    co, proc_obj.errmsg)
                lineno = 1
                # _, lineno = pyficache.unmap_file_line(temp_filename, lineno, True)
                if temp_filename:
                    filename = temp_filename
                pass

            else:
                # FIXME:
                if source_text:
                    lines = source_text.split("\n")
                    temp_name = 'string-'
                else:
                    # try with good ol linecache and consider fixing pyficache
                    lines = linecache.getlines(filename)
                    temp_name = filename
                if lines:
                    # FIXME: DRY code with version in cmdproc.py print_location
                    prefix = os.path.basename(temp_name).split('.')[0]
                    fd = tempfile.NamedTemporaryFile(suffix='.py',
                                                     prefix=prefix,
                                                     delete=False)
                    with fd:
                        fd.write(''.join(lines))
                        remapped_file = fd.name
                        pyficache.remap_file(remapped_file, filename)
                    fd.close()
                    pass
            line = linecache.getline(filename, lineno,
                                     proc_obj.curframe.f_globals)
            if not line:
                m = re.search('^<frozen (.*)>', filename)
                if m and m.group(1):
                    remapped_file = m.group(1)
                    try_module = sys.modules.get(remapped_file)
                    if (try_module and inspect.ismodule(try_module)
                            and hasattr(try_module, '__file__')):
                        remapped_file = sys.modules[remapped_file].__file__
                        pyficache.remap_file(filename, remapped_file)
                        line = linecache.getline(remapped_file, lineno,
                                                 proc_obj.curframe.f_globals)
                    else:
                        remapped_file = m.group(1)
                        code = proc_obj.curframe.f_code
                        filename, line = cmdfns.deparse_getline(
                            code, remapped_file, lineno, opts)
                    pass
            pass

        try:
            match, reason = Mstack.check_path_with_frame(frame, filename)
            if not match:
                if filename not in warned_file_mismatches:
                    proc_obj.errmsg(reason)
                    warned_file_mismatches.add(filename)
        except:
            pass

        fn_name = frame.f_code.co_name
        last_i = frame.f_lasti
        print_source_location_info(intf_obj.msg,
                                   filename,
                                   lineno,
                                   fn_name,
                                   remapped_file=remapped_file,
                                   f_lasti=last_i)
        if line and len(line.strip()) != 0:
            if proc_obj.event:
                print_source_line(intf_obj.msg, lineno, line,
                                  proc_obj.event2short[proc_obj.event])
            pass
        if '<string>' != filename: break
        pass

    if proc_obj.event in ['return', 'exception']:
        val = proc_obj.event_arg
        intf_obj.msg('R=> %s' % proc_obj._saferepr(val))
        pass
    return True
예제 #4
0
def print_location(proc_obj):
    """Show where we are. GUI's and front-end interfaces often
    use this to update displays. So it is helpful to make sure
    we give at least some place that's located in a file.
    """
    i_stack = proc_obj.curindex
    if i_stack is None or proc_obj.stack is None:
        return False
    core_obj = proc_obj.core
    dbgr_obj = proc_obj.debugger
    intf_obj = dbgr_obj.intf[-1]

    # Evaluation routines like "exec" don't show useful location
    # info. In these cases, we will use the position before that in
    # the stack.  Hence the looping below which in practices loops
    # once and sometimes twice.
    remapped_file = None
    source_text = None
    while i_stack >= 0:
        frame_lineno = proc_obj.stack[i_stack]
        i_stack -= 1
        frame, lineno = frame_lineno

#         # Next check to see that local variable breadcrumb exists and
#         # has the magic dynamic value.
#         # If so, it's us and we don't normally show this.a
#         if 'breadcrumb' in frame.f_locals:
#             if self.run == frame.f_locals['breadcrumb']:
#                 break

        filename = Mstack.frame2file(core_obj, frame, canonic=False)
        if '<string>' == filename and dbgr_obj.eval_string:
            remapped_file = filename
            filename = pyficache.unmap_file(filename)
            if '<string>' == filename:
                remapped = source_tempfile_remap('eval_string',
                                                 dbgr_obj.eval_string)
                pyficache.remap_file(filename, remapped)
                filename = remapped
                lineno = pyficache.unmap_file_line(filename, lineno)
                pass
            pass
        elif '<string>' == filename:
            source_text = deparse_fn(frame.f_code)
            filename = "<string: '%s'>" % source_text
            pass
        else:
            if filename in pyficache.file2file_remap:
                remapped_file = pyficache.unmap_file(filename)
                # FIXME: a remapped_file shouldn't be the same as its unmapped version
                if remapped_file == filename:
                    remapped_file = None
                    pass
                pass
            pass

        opts = {
            'reload_on_change' : proc_obj.settings('reload'),
            'output'           : proc_obj.settings('highlight')
            }

        if 'style' in proc_obj.debugger.settings:
            opts['style'] = proc_obj.settings('style')

        pyficache.update_cache(filename)
        line = pyficache.getline(filename, lineno, opts)
        if not line:
            if (not source_text and
                filename.startswith("<string: ") and proc_obj.curframe.f_code):
                # Deparse the code object into a temp file and remap the line from code
                # into the corresponding line of the tempfile
                co = proc_obj.curframe.f_code
                temp_filename, name_for_code = deparse_and_cache(co, proc_obj.errmsg)
                lineno = 1
                # _, lineno = pyficache.unmap_file_line(temp_filename, lineno, True)
                if temp_filename:
                    filename = temp_filename
                pass

            else:
                # FIXME:
                if source_text:
                    lines = source_text.split("\n")
                    temp_name='string-'
                else:
                    # try with good ol linecache and consider fixing pyficache
                    lines = linecache.getlines(filename)
                    temp_name = filename
                if lines:
                    # FIXME: DRY code with version in cmdproc.py print_location
                    prefix = os.path.basename(temp_name).split('.')[0]
                    fd = tempfile.NamedTemporaryFile(suffix='.py',
                                                     prefix=prefix,
                                                     delete=False)
                    with fd:
                        fd.write(''.join(lines))
                        remapped_file = fd.name
                        pyficache.remap_file(remapped_file, filename)
                    fd.close()
                    pass
                line = linecache.getline(filename, lineno,
                                         proc_obj.curframe.f_globals)
            pass

        fn_name = frame.f_code.co_name
        last_i  = frame.f_lasti
        print_source_location_info(intf_obj.msg, filename, lineno, fn_name,
                                   remapped_file = remapped_file,
                                   f_lasti = last_i)
        if line and len(line.strip()) != 0:
            if proc_obj.event:
                print_source_line(intf_obj.msg, lineno, line,
                                  proc_obj.event2short[proc_obj.event])
            pass
        if '<string>' != filename: break
        pass

    if proc_obj.event in ['return', 'exception']:
        val = proc_obj.event_arg
        intf_obj.msg('R=> %s' % proc_obj._saferepr(val))
        pass
    return True
예제 #5
0
    def run(self, args):
        if sys.version_info[:2] > (3, 8):
            self.errmsg("Deparsing for Python greater than 3.8 not impemented")
            return
        co = self.proc.curframe.f_code
        name = co.co_name

        try:
            opts, args = getopt(
                args[1:],
                "hpPto:O",
                ["help", "parent", "pretty", "tree", "offset=", "offsets"],
            )
        except GetoptError as err:
            # print help information and exit:
            self.errmsg(str(
                err))  # will print something like "option -a not recognized"
            return

        show_parent = False
        show_tree = False
        offset = None
        show_offsets = False
        for o, a in opts:
            if o in ("-h", "--help"):
                self.proc.commands["help"].run(["help", "deparse"])
                return
            elif o in ("-O", "--offsets"):
                show_offsets = True
            elif o in ("-p", "--parent"):
                show_parent = True
            elif o in (
                    "-t",
                    "--tree",
            ):
                show_tree = True
            elif o in ("-o", "--offset"):
                offset = a
            else:
                self.errmsg("unhandled option '%s'" % o)
            pass
        pass
        nodeInfo = None

        if len(args) >= 1 and args[0] == ".":
            temp_filename, name_for_code = deparse_and_cache(
                co, self.errmsg, tempdir=self.settings["tempdir"])
            if not temp_filename:
                return
            self.print_text("".join(getlines(temp_filename)))
            return
        elif show_offsets:
            deparsed = code_deparse(co)
            self.section("Offsets known:")
            m = self.columnize_commands(
                list(sorted(deparsed.offsets.keys(), key=lambda x: str(x[0]))))
            self.msg_nocr(m)
            return
        elif offset is not None:
            mess = ("The 'deparse' command when given an argument requires an"
                    " instruction offset. Got: '%s'" % offset)
            last_i = self.proc.get_an_int(offset, mess)
            if last_i is None:
                return
        else:
            last_i = self.proc.curframe.f_lasti
            if last_i == -1:
                last_i = 0

        deparsed, nodeInfo = deparse_offset(co, name, last_i, self.errmsg)
        if not deparsed:
            return

        if nodeInfo:
            extractInfo = deparsed.extract_node_info(nodeInfo)
            parentInfo = None
            # print extractInfo
            if show_tree:
                p = deparsed.ast
                if show_parent:
                    parentInfo, p = deparsed.extract_parent_info(nodeInfo.node)
                self.msg(p)
            if extractInfo:
                self.rst_msg("*instruction:* %s" % (nodeInfo.node))
                self.print_text(extractInfo.selectedLine)
                self.msg(extractInfo.markerLine)
                if show_parent:
                    if not parentInfo:
                        parentInfo, p = deparsed.extract_parent_info(
                            nodeInfo.node)
                    if parentInfo:
                        self.section("Contained in...")
                        self.rst_msg("\t*Grammar Symbol:* %s" % p.kind)
                        self.print_text(parentInfo.selectedLine)
                        self.msg(parentInfo.markerLine)
                    pass
                pass
            pass
        elif last_i == -1:
            if name:
                self.msg("At beginning of %s " % name)
            elif self.core.filename(None):
                self.msg("At beginning of program %s" %
                         self.core.filename(None))
            else:
                self.msg("At beginning")
        else:
            self.errmsg(
                "haven't recorded info for offset %d. Offsets I know are:" %
                last_i)
            offsets = [
                key[1] for key in deparsed.offsets.keys()
                if isinstance(key[1], int)
            ]
            m = self.columnize_commands(list(sorted(offsets)))
            self.msg_nocr(m)
        return
예제 #6
0
def print_location(proc_obj):
    """Show where we are. GUI's and front-end interfaces often
    use this to update displays. So it is helpful to make sure
    we give at least some place that's located in a file.
    """
    i_stack = proc_obj.curindex
    if i_stack is None or proc_obj.stack is None:
        return False
    core_obj = proc_obj.core
    dbgr_obj = proc_obj.debugger
    intf_obj = dbgr_obj.intf[-1]

    # Evaluation routines like "exec" don't show useful location
    # info. In these cases, we will use the position before that in
    # the stack.  Hence the looping below which in practices loops
    # once and sometimes twice.
    remapped_file = None
    source_text = None
    while i_stack >= 0:
        frame_lineno = proc_obj.stack[i_stack]
        i_stack -= 1
        frame, lineno = frame_lineno

        #         # Next check to see that local variable breadcrumb exists and
        #         # has the magic dynamic value.
        #         # If so, it's us and we don't normally show this.a
        #         if 'breadcrumb' in frame.f_locals:
        #             if self.run == frame.f_locals['breadcrumb']:
        #                 break

        filename = Mstack.frame2file(core_obj, frame, canonic=False)
        if "<string>" == filename and dbgr_obj.eval_string:
            remapped_file = filename
            filename = pyficache.unmap_file(filename)
            if "<string>" == filename:
                remapped = source_tempfile_remap(
                    "eval_string",
                    dbgr_obj.eval_string,
                    tempdir=proc_obj.settings("tempdir"))
                pyficache.remap_file(filename, remapped)
                filename = remapped
                lineno = pyficache.unmap_file_line(filename, lineno)
                pass
            pass
        elif "<string>" == filename:
            source_text = deparse_fn(frame.f_code)
            filename = "<string: '%s'>" % source_text
            pass
        elif filename in proc_obj.file2file_remap:
            remapped_file = proc_obj.file2file_remap[filename]
        elif filename in pyficache.file2file_remap:
            remapped_file = pyficache.unmap_file(filename)
            # FIXME: a remapped_file shouldn't be the same as its unmapped version
            if remapped_file == filename:
                remapped_file = None
                pass
            pass
        elif pyficache.main.remap_re_hash:
            remapped_file = pyficache.remap_file_pat(
                filename, pyficache.main.remap_re_hash)

        opts = {
            "reload_on_change": proc_obj.settings("reload"),
            "output": proc_obj.settings("highlight"),
        }

        if "style" in proc_obj.debugger.settings:
            opts["style"] = proc_obj.settings("style")

        pyficache.update_cache(filename)
        line = pyficache.getline(filename, lineno, opts)
        if not line:
            if (not source_text and filename.startswith("<string: ")
                    and proc_obj.curframe.f_code):
                # Deparse the code object into a temp file and remap the line from code
                # into the corresponding line of the tempfile
                co = proc_obj.curframe.f_code
                tempdir = proc_obj.settings("tempdir")
                temp_filename, name_for_code = deparse_and_cache(
                    co, proc_obj.errmsg, tempdir=tempdir)
                lineno = 1
                # _, lineno = pyficache.unmap_file_line(temp_filename, lineno, True)
                if temp_filename:
                    filename = temp_filename
                pass

            else:
                # FIXME:
                if source_text:
                    lines = source_text.split("\n")
                    temp_name = "string-"
                else:
                    # try with good ol linecache and consider fixing pyficache
                    lines = linecache.getlines(filename)
                    temp_name = filename
                if lines:
                    # FIXME: DRY code with version in cmdproc.py print_location
                    prefix = osp.basename(temp_name).split(".")[0]
                    fd = tempfile.NamedTemporaryFile(
                        suffix=".py",
                        prefix=prefix,
                        delete=False,
                        dir=proc_obj.settings("tempdir"),
                    )
                    with fd:
                        fd.write("".join(lines))
                        remapped_file = fd.name
                        pyficache.remap_file(remapped_file, filename)
                    fd.close()
                    pass
                line = linecache.getline(filename, lineno,
                                         proc_obj.curframe.f_globals)
            pass

        fn_name = frame.f_code.co_name
        last_i = frame.f_lasti
        print_source_location_info(
            intf_obj.msg,
            filename,
            lineno,
            fn_name,
            remapped_file=remapped_file,
            f_lasti=last_i,
        )
        if line and len(line.strip()) != 0:
            if proc_obj.event:
                print_source_line(intf_obj.msg, lineno, line,
                                  proc_obj.event2short[proc_obj.event])
            pass
        if "<string>" != filename:
            break
        pass

    if proc_obj.event in ["return", "exception"]:
        val = proc_obj.event_arg
        intf_obj.msg("R=> %s" % proc_obj._saferepr(val))
        pass
    return True