Skip to content

Commit bb6dc8b

Browse files
committed
debugpy: Add type hints and improve path mapping logic in PDB adapter
Signed-off-by: Jos Verlinde <[email protected]>
1 parent 2eb9cb5 commit bb6dc8b

File tree

2 files changed

+21
-28
lines changed

2 files changed

+21
-28
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def __init__(self, client_socket):
2020
self.debug_logging = False # Initialize first
2121
self.channel = JsonMessageChannel(client_socket, self._debug_print)
2222
self.pdb = PdbAdapter()
23-
self.pdb._debug_session = self # Allow PDB to process messages during wait
23+
self.pdb._debug_session = self # Allow PDB to process messages during wait # type: ignore
2424
self.initialized = False
2525
self.connected = True
2626
self.thread_id = 1 # Simple single-thread model

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

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@
1414
VARREF_GLOBALS_SPECIAL = 4
1515

1616

17+
# Also try checking by basename for path mismatches
18+
def basename(path:str):
19+
return path.split('/')[-1] if '/' in path else path
20+
21+
# Check if this might be a relative path match
22+
def ends_with_path(full_path:str, relative_path:str):
23+
"""Check if full_path ends with relative_path components."""
24+
full_parts = full_path.replace('\\', '/').split('/')
25+
rel_parts = relative_path.replace('\\', '/').split('/')
26+
if len(rel_parts) > len(full_parts):
27+
return False
28+
return full_parts[-len(rel_parts):] == rel_parts
29+
1730
class PdbAdapter:
1831
"""Adapter between DAP protocol and MicroPython's sys.settrace functionality."""
1932

@@ -27,14 +40,14 @@ def __init__(self):
2740
self.continue_event = False
2841
self.variables_cache = {} # frameId -> variables
2942
self.frame_id_counter = 1
30-
self.path_mapping = {} # runtime_path -> vscode_path mapping
43+
self.path_mappings : dict[str,str] = {} # runtime_path -> vscode_path mapping
3144

3245
def _debug_print(self, message):
3346
"""Print debug message only if debug logging is enabled."""
3447
if hasattr(self, '_debug_session') and self._debug_session.debug_logging: # type: ignore
3548
print(message)
3649

37-
def _normalize_path(self, path):
50+
def _normalize_path(self, path:str):
3851
"""Normalize a file path for consistent comparisons."""
3952
# Convert to absolute path if possible
4053
try:
@@ -44,7 +57,6 @@ def _normalize_path(self, path):
4457
path = os.path.realpath(path)
4558
except:
4659
pass
47-
4860
# Ensure consistent separators
4961
path = path.replace('\\', '/')
5062
return path
@@ -80,42 +92,23 @@ def set_breakpoints(self, filename, breakpoints):
8092

8193
return actual_breakpoints
8294

83-
def should_stop(self, frame, event, arg):
95+
def should_stop(self, frame, event:str, arg):
8496
"""Determine if execution should stop at this point."""
8597
self.current_frame = frame
8698
self.hit_breakpoint = False
8799

88100
# Get frame information
89101
filename = frame.f_code.co_filename
90102
lineno = frame.f_lineno
91-
92-
# Debug: print filename and line for debugging
93-
if event == TRACE_LINE and lineno in [20, 21, 22, 23, 24]: # Only log lines near our breakpoints
94-
self._debug_print(f"[PDB] Checking {filename}:{lineno} (event={event})")
95-
self._debug_print(f"[PDB] Available breakpoint files: {list(self.breakpoints.keys())}")
96-
97103
# Check for exact filename match first
98104
if filename in self.breakpoints:
99105
if lineno in self.breakpoints[filename]:
100106
self._debug_print(f"[PDB] HIT BREAKPOINT (exact match) at {filename}:{lineno}")
101107
# Record the path mapping (in this case, they're already the same)
102-
self.path_mapping[filename] = filename
108+
self.path_mappings[filename] = filename
103109
self.hit_breakpoint = True
104110
return True
105111

106-
# Also try checking by basename for path mismatches
107-
def basename(path):
108-
return path.split('/')[-1] if '/' in path else path
109-
110-
# Check if this might be a relative path match
111-
def ends_with_path(full_path, relative_path):
112-
"""Check if full_path ends with relative_path components."""
113-
full_parts = full_path.replace('\\', '/').split('/')
114-
rel_parts = relative_path.replace('\\', '/').split('/')
115-
if len(rel_parts) > len(full_parts):
116-
return False
117-
return full_parts[-len(rel_parts):] == rel_parts
118-
119112
file_basename = basename(filename)
120113
self._debug_print(f"[PDB] Fallback basename match: '{file_basename}' vs available files")
121114
for bp_file in self.breakpoints:
@@ -126,7 +119,7 @@ def ends_with_path(full_path, relative_path):
126119
if lineno in self.breakpoints[bp_file]:
127120
self._debug_print(f"[PDB] HIT BREAKPOINT (fallback basename match) at {filename}:{lineno} -> {bp_file}")
128121
# Record the path mapping so we can report the correct path in stack traces
129-
self.path_mapping[filename] = bp_file
122+
self.path_mappings[filename] = bp_file
130123
self.hit_breakpoint = True
131124
return True
132125

@@ -136,7 +129,7 @@ def ends_with_path(full_path, relative_path):
136129
if lineno in self.breakpoints[bp_file]:
137130
self._debug_print(f"[PDB] HIT BREAKPOINT (relative path match) at {filename}:{lineno} -> {bp_file}")
138131
# Record the path mapping so we can report the correct path in stack traces
139-
self.path_mapping[filename] = bp_file
132+
self.path_mappings[filename] = bp_file
140133
self.hit_breakpoint = True
141134
return True
142135

@@ -223,7 +216,7 @@ def get_stack_trace(self):
223216
hint = 'normal'
224217

225218
# Use the VS Code path if we have a mapping, otherwise use the original path
226-
display_path = self.path_mapping.get(filename, filename)
219+
display_path = self.path_mappings.get(filename, filename)
227220
if filename != display_path:
228221
self._debug_print(f"[PDB] Stack trace path mapping: {filename} -> {display_path}")
229222
# Create StackFrame info

0 commit comments

Comments
 (0)