2929from typing import Optional , Tuple
3030
3131import xdis
32- from xdis import IS_PYPY , get_opcode
33- from xdis .version_info import PYTHON_VERSION_TRIPLE
32+ from xdis import get_opcode
33+ from xdis .version_info import PYTHON_IMPLEMENTATION , PYTHON_VERSION_TRIPLE
3434
3535from trepan .lib .bytecode import op_at_frame
3636from trepan .lib .format import (
@@ -77,6 +77,21 @@ def count_frames(frame: FrameType, count_start=0) -> int:
7777 return 1000
7878 return count
7979
80+ def get_column_start (frame : FrameType ) -> int :
81+ """
82+ Given a code frame, return the start column for that
83+ frame. (The line number is found in frame.f_lineno).
84+ If we can't find a column number, return -1.
85+ """
86+ co_positions = frame .f_code .co_positions ()
87+ instruction_number = frame .f_lasti // 2
88+ position_list = list (co_positions )
89+ position_tuple = position_list [instruction_number ]
90+ if position_tuple is not None :
91+ assert position_tuple [0 ] == frame .f_lineno
92+ if position_tuple [2 ] is not None :
93+ return position_tuple [2 ]
94+ return - 1
8095
8196_re_pseudo_file = re .compile (r"^<.+>" )
8297
@@ -193,6 +208,7 @@ def format_function_and_parameters(frame: FrameType, debugger, style: str) -> Tu
193208def format_return_and_location (
194209 frame ,
195210 line_number : int ,
211+ column_number : int ,
196212 debugger ,
197213 is_module : bool ,
198214 include_location : bool ,
@@ -241,21 +257,28 @@ def format_return_and_location(
241257
242258 if add_quotes_around_file :
243259 filename = f"'{ filename } '"
244- s += " %s at line %s" % (
245- format_token (Filename , filename , style = style ),
246- format_token (LineNumber , str (line_number ), style = style ),
247- )
260+ if column_number >= 0 :
261+ s += " %s at line %s, column %s" % (
262+ format_token (Filename , filename , style = style ),
263+ format_token (LineNumber , str (line_number ), style = style ),
264+ format_token (LineNumber , str (column_number ), style = style ),
265+ )
266+ else :
267+ s += " %s at line %s" % (
268+ format_token (Filename , filename , style = style ),
269+ format_token (LineNumber , str (line_number ), style = style ),
270+ )
248271
249272 return s
250273
251274
252275def format_stack_entry (
253- dbg_obj , frame_lineno , lprefix = ": " , include_location = True , style = "none"
276+ dbg_obj , frame_line_col , lprefix = ": " , include_location = True , style = "none"
254277) -> str :
255278 """Format and return a stack entry gdb-style.
256279 Note: lprefix is not used. It is kept for compatibility.
257280 """
258- frame , line_number = frame_lineno
281+ frame , line_number , column_number = frame_line_col
259282
260283 is_module , s = format_function_and_parameters (frame , dbg_obj , style )
261284 args , varargs , varkw , local_vars = inspect .getargvalues (frame )
@@ -266,7 +289,7 @@ def format_stack_entry(
266289 s += "\n "
267290
268291 s += format_return_and_location (
269- frame , line_number , dbg_obj , is_module , include_location , style
292+ frame , line_number , column_number , dbg_obj , is_module , include_location , style
270293 )
271294 return s
272295
@@ -335,7 +358,7 @@ def is_eval_or_exec_stmt(frame) -> Optional[str]:
335358 return None
336359
337360
338- opc = get_opcode (PYTHON_VERSION_TRIPLE , IS_PYPY )
361+ opc = get_opcode (PYTHON_VERSION_TRIPLE , PYTHON_IMPLEMENTATION )
339362
340363
341364def get_call_function_name (frame ) -> Optional [str ]:
@@ -392,20 +415,20 @@ def get_call_function_name(frame) -> Optional[str]:
392415
393416
394417def print_stack_entry (proc_obj , i_stack : int , style = "none" , opts = {}):
395- frame_lineno = proc_obj .stack [len (proc_obj .stack ) - i_stack - 1 ]
396- frame , lineno = frame_lineno
418+ frame_line_column = proc_obj .stack [len (proc_obj .stack ) - i_stack - 1 ]
419+ frame , line_number , _ = frame_line_column
397420 intf = proc_obj .intf [- 1 ]
398421 name = "??"
399422 if frame is proc_obj .curframe :
400423 intf .msg_nocr (format_token (Arrow , "->" , style = style ))
401424 else :
402425 intf .msg_nocr ("##" )
403426 intf .msg (
404- f"{ i_stack } { format_stack_entry (proc_obj .debugger , frame_lineno , style = style )} "
427+ f"{ i_stack } { format_stack_entry (proc_obj .debugger , frame_line_column , style = style )} "
405428 )
406429 if opts .get ("source" , False ):
407430 filename = frame2file (proc_obj .core , frame )
408- line = linecache .getline (filename , lineno , frame .f_globals )
431+ line = linecache .getline (filename , line_number , frame .f_globals )
409432 intf .msg (line )
410433 pass
411434
@@ -551,21 +574,23 @@ def __init__(self):
551574
552575 dd = Trepan ()
553576 my_frame = inspect .currentframe ()
554- dd .core .processor .stack = [(my_frame , 100 )]
577+ dd .core .processor .stack = [(my_frame , 100 , 1 )]
555578 dd .core .processor .curframe = my_frame
556- # print_stack_entry(dd.core.processor, 0, "fruity")
579+ print_stack_entry (dd .core .processor , 0 , "fruity" )
557580
558- # print(format_stack_entry(m, (frame, 10,)))
559581 print (
560582 format_stack_entry (
561583 m ,
562584 (
563585 frame ,
564586 10 ,
587+ 3 ,
565588 ),
566589 style = "tango" ,
567590 )
568591 )
592+ import sys
593+ sys .exit (0 )
569594 # print("frame count: %d" % count_frames(frame))
570595 # print("frame count: %d" % count_frames(frame.f_back))
571596 # print("frame count: %d" % count_frames(frame, 1))
0 commit comments