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
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
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
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
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
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