Skip to content

Commit 4ecb2fb

Browse files
committed
Update API, more column info showing
1 parent 8522f91 commit 4ecb2fb

5 files changed

Lines changed: 63 additions & 34 deletions

File tree

trepan/lib/stack.py

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
from typing import Optional, Tuple
3030

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

3535
from trepan.lib.bytecode import op_at_frame
3636
from 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
193208
def 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

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

341364
def get_call_function_name(frame) -> Optional[str]:
@@ -392,20 +415,20 @@ def get_call_function_name(frame) -> Optional[str]:
392415

393416

394417
def 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))

trepan/processor/cmdbreak.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import inspect
1818
from dis import findlinestarts
19-
from pyficache import code_line_info, code_offset_info
19+
from pyficache import code_line_info
2020
from trepan.misc import wrapped_lines, pretty_modfunc_name
2121
from trepan.processor.parse.semantics import build_bp_expr
2222
from trepan.processor.parse.parser import LocationError
@@ -71,7 +71,7 @@ def set_break(
7171

7272
else:
7373
assert offset is not None
74-
line_number = code_offset_info(filename, offset)
74+
line_number = code_line_info(filename, offset)
7575
if line_number is None:
7676
part1 = f"File {cmd_obj.core.filename(filename)}"
7777
msg = wrapped_lines(

trepan/processor/command/disassemble.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def run(self, args):
204204
_timestamp,
205205
_magic_int,
206206
obj,
207-
_is_pypy,
207+
_python_implementation,
208208
_source_size,
209209
_sip_hash,
210210
_save_offsets,

trepan/processor/command/info_subcmd/threads.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22
#
3-
# Copyright (C) 2009, 2014, 2023-2024 Rocky Bernstein <rocky@gnu.org>
3+
# Copyright (C) 2009, 2014, 2023-2025 Rocky Bernstein <rocky@gnu.org>
44
#
55
# This program is free software: you can redistribute it and/or modify
66
# it under the terms of the GNU General Public License as published by
@@ -17,7 +17,8 @@
1717
import sys
1818
import threading
1919

20-
from trepan.lib import stack as Mstack, thred as Mthread
20+
from trepan.lib.stack import format_stack_entry, get_column_start
21+
from trepan.lib import thred as Mthread
2122

2223
# Our local modules
2324
from trepan.processor.command import base_subcmd as Mbase_subcmd
@@ -55,17 +56,18 @@ def __init__(self, cmd):
5556
self.name2id = {}
5657
return
5758

58-
def stack_trace(self, f):
59+
def stack_trace(self, frame):
5960
"""A mini stack trace routine for threads."""
60-
while f:
61+
while frame:
6162
if (
62-
not self.core.ignore_filter.is_included(f)
63+
self.core.ignore_filter.is_excluded(frame)
6364
or self.settings["dbg_trepan"]
6465
):
65-
s = Mstack.format_stack_entry(self, (f, f.f_lineno))
66+
column_start = get_column_start(frame)
67+
s = format_stack_entry(self, (frame, frame.f_lineno, column_start))
6668
self.msg(" " * 4 + s)
6769
pass
68-
f = f.f_back
70+
frame = frame.f_back
6971
pass
7072
return
7173

@@ -128,13 +130,12 @@ def run(self, args):
128130
thread_name = args[0]
129131
if thread_name == ".":
130132
thread_name = self.thread_name
131-
try:
132-
thread_id = int(thread_name)
133+
if thread_id := name2id.get(thread_name):
133134
if thread_id not in list(threading._active.keys()):
134-
self.errmsg(f"Don't know about thread number {thread_name}")
135+
self.errmsg(f"Don't know about thread number {thread_id}")
135136
self.info_thread_terse(name2id)
136137
return
137-
except ValueError:
138+
else:
138139
if thread_name not in list(self.name2id.keys()):
139140
self.errmsg(f"Don't know about thread {thread_name}")
140141
self.info_thread_terse(name2id)
@@ -176,8 +177,11 @@ def run(self, args):
176177
s += " thread id: %d" % thread_id
177178
pass
178179
s += "\n "
179-
s += Mstack.format_stack_entry(
180-
self, (frame, frame.f_lineno), style=self.settings["style"]
180+
column_start = get_column_start(frame)
181+
s += format_stack_entry(
182+
self,
183+
(frame, frame.f_lineno, column_start),
184+
style=self.settings["style"],
181185
)
182186
self.section("-" * 40)
183187
self.msg(s)

trepan/processor/command/list.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def run(self, args):
149149
break
150150
else:
151151
if is_pyasm:
152-
self.msg_nocr(line)
152+
self.msg(line)
153153
proc.list_lineno = lineno
154154
continue
155155

0 commit comments

Comments
 (0)