Skip to content

Commit 817f5ec

Browse files
committed
debugpy: Refactor breakpoint storage to use sets for improved efficiency
Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
1 parent 14b2e27 commit 817f5ec

1 file changed

Lines changed: 20 additions & 26 deletions

File tree

python-ecosys/debugpy/debugpy/server/pdb_adapter.py

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
VARREF_LOCALS_SPECIAL = 3
1414
VARREF_GLOBALS_SPECIAL = 4
1515

16+
DEBUG = False
1617

1718
# Also try checking by basename for path mismatches
1819
def basename(path:str):
@@ -31,7 +32,7 @@ class PdbAdapter:
3132
"""Adapter between DAP protocol and MicroPython's sys.settrace functionality."""
3233

3334
def __init__(self):
34-
self.breakpoints : dict[str,dict[int,dict]] = {} # filename -> {line_no: breakpoint_info} # todo - simplify - reduce info stored
35+
self.breakpoints : dict[str,set[int]] = {} # .breakpoints[filename] -> set of line numbers
3536
self.current_frame = None
3637
self.step_mode = None # None, 'over', 'into', 'out'
3738
self.step_frame = None
@@ -40,8 +41,8 @@ def __init__(self):
4041
self.continue_event = False
4142
self.variables_cache = {} # frameId -> variables
4243
self.frame_id_counter = 1
43-
self.path_mappings : list[tuple[str,str]] = [] # runtime_path -> vscode_path mapping # todo: move to session level
44-
self.file_mappings : dict[str,str] = {} # runtime_path -> vscode_path mapping # todo : merge with .breakpoints
44+
self.path_mappings : list[tuple[str,str]] = [] # runtime_path -> vscode_path mapping
45+
self.file_mappings : dict[str,str] = {} # runtime_path -> vscode_path mapping # todo : ? merge with .breakpoints
4546

4647
def _debug_print(self, message):
4748
"""Print debug message only if debug logging is enabled."""
@@ -107,7 +108,7 @@ def _filename_as_debugger(self, path:str):
107108

108109
def set_breakpoints(self, filename:str, breakpoints:list[dict]):
109110
"""Set breakpoints for a file."""
110-
self.breakpoints[filename] = {}
111+
self.breakpoints[filename] = set()
111112
local_name = self._filename_as_debugee(filename)
112113
self.file_mappings[local_name] = filename
113114
actual_breakpoints = []
@@ -117,18 +118,11 @@ def set_breakpoints(self, filename:str, breakpoints:list[dict]):
117118
line = bp.get("line")
118119
if line:
119120
if local_name != filename:
120-
self.breakpoints[local_name] = {}
121+
self.breakpoints[local_name] = set()
121122
self._debug_print(f"[>>>] Setting breakpoints for local: {local_name}:{line}")
122-
self.breakpoints[local_name][line] = {
123-
"line": line,
124-
"verified": True,
125-
"source": {"path": filename}
126-
}
127-
self.breakpoints[filename][line] = {
128-
"line": line,
129-
"verified": True,
130-
"source": {"path": filename}
131-
}
123+
self.breakpoints[local_name].add(line)
124+
125+
self.breakpoints[filename].add(line)
132126
actual_breakpoints.append({
133127
"line": line,
134128
"verified": True,
@@ -148,19 +142,19 @@ def should_stop(self, frame, event:str, arg):
148142
filename = frame.f_code.co_filename
149143
lineno = frame.f_lineno
150144
# Check for exact filename match first
151-
if filename in self.breakpoints:
152-
if lineno in self.breakpoints[filename]:
145+
if filename in self.breakpoints and lineno in self.breakpoints[filename]:
153146
self._debug_print(f"[PDB] HIT BREAKPOINT (exact match) at {filename}:{lineno}")
154147
# Record the path mapping (in this case, they're already the same)
155-
self.file_mappings[filename] = self._filename_as_debugger(filename)
148+
# self.file_mappings[filename] = self._filename_as_debugger(filename)
156149
self.hit_breakpoint = True
157150
return True
158151
# path/file.py matched - but not the line number - keep running
159152
else:
160153
# file not (yet) matched - this is slow so we do not want to do this often.
161154
# TODO: use builins - sys.path method to find the file
162-
# if we have a path match , but no breakpoints - add it to the file_mappings dict avoid this check
163-
self.breakpoints[filename] = {} # Ensure the filename is in the breakpoints dict
155+
# if we have a path match , but no breakpoints - add it to the file_mappings dict simplify this check
156+
if not filename in self.breakpoints:
157+
self.breakpoints[filename] = set() # Ensure the filename is in the breakpoints dict
164158
if not filename in self.file_mappings:
165159
self.file_mappings[filename] = self._filename_as_debugger(filename)
166160
self._debug_print(f"[PDB] add mapping for :'{filename}' -> '{self.file_mappings[filename]}'")
@@ -238,6 +232,12 @@ def get_stack_trace(self):
238232
frame = self.current_frame
239233
frame_id = 0
240234

235+
self._debug_print("=" * 40 )
236+
self._debug_print(f"[PDB] file mappings: {repr(self.file_mappings)} " )
237+
self._debug_print(f"[PDB] path mappings: {repr(self.path_mappings)}" )
238+
self._debug_print(f"[PDB] breakpoints: {repr(self.breakpoints)}" )
239+
self._debug_print("=" * 40 )
240+
241241
while frame:
242242
filename = frame.f_code.co_filename
243243
name = frame.f_code.co_name
@@ -247,15 +247,9 @@ def get_stack_trace(self):
247247
else :
248248
hint = 'normal'
249249

250-
# self._debug_print("=" * 40 )
251-
# self._debug_print(f"[PDB] file mappings: {repr(self.file_mappings)} " )
252-
# self._debug_print(f"[PDB] path mappings: {repr(self.path_mappings)}" )
253-
# self._debug_print("=" * 40 )
254250

255251
# Use the VS Code path if we have a mapping, otherwise use the original path
256252
debugger_path = self._filename_as_debugger(filename)
257-
if filename != debugger_path:
258-
self._debug_print(f"[PDB] Stack trace path mapping: {filename} -> {debugger_path}")
259253
# Create StackFrame info
260254
frames.append({
261255
"id": frame_id,

0 commit comments

Comments
 (0)