Skip to content

Commit 448c386

Browse files
committed
bdb: Add initial micropython support.
Requires micropython to be compiled with MICROPY_PY_SYS_SETTRACE. Also requires micropython/micropython#8767
1 parent 1fe75b8 commit 448c386

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

python-stdlib/bdb/bdb.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
"""Debugger basics"""
22

3+
# This is originally from cpython 3.10: https://raw.githubusercontent.com/python/cpython/3.10/Lib/bdb.py
4+
# Patches for micropython have been commented as such.
5+
36
import fnmatch
47
import sys
58
import os
6-
from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR
9+
10+
## MPY: no inspect module avaialble
11+
# from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR
712

813
__all__ = ["BdbQuit", "Bdb", "Breakpoint"]
914

10-
GENERATOR_AND_COROUTINE_FLAGS = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR
15+
## MPY: These flags currently don't exist
16+
# GENERATOR_AND_COROUTINE_FLAGS = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR
1117

1218

1319
class BdbQuit(Exception):
@@ -115,6 +121,12 @@ def dispatch_line(self, frame):
115121
if self.quitting: raise BdbQuit
116122
return self.trace_dispatch
117123

124+
def is_coroutine(self, frame):
125+
## MPY: co_flags attrib not available, compatible method of detecting coroutine TBD
126+
# return frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
127+
return False
128+
129+
118130
def dispatch_call(self, frame, arg):
119131
"""Invoke user function and return trace function for call event.
120132
@@ -131,7 +143,7 @@ def dispatch_call(self, frame, arg):
131143
# No need to trace this function
132144
return # None
133145
# Ignore call events in generator except when stepping.
134-
if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
146+
if self.stopframe and self.is_coroutine(frame):
135147
return self.trace_dispatch
136148
self.user_call(frame, arg)
137149
if self.quitting: raise BdbQuit
@@ -146,7 +158,7 @@ def dispatch_return(self, frame, arg):
146158
"""
147159
if self.stop_here(frame) or frame == self.returnframe:
148160
# Ignore return events in generator except when stepping.
149-
if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
161+
if self.stopframe and self.is_coroutine(frame):
150162
return self.trace_dispatch
151163
try:
152164
self.frame_returning = frame
@@ -170,7 +182,7 @@ def dispatch_exception(self, frame, arg):
170182
# When stepping with next/until/return in a generator frame, skip
171183
# the internal StopIteration exception (with no traceback)
172184
# triggered by a subiterator run with the 'yield from' statement.
173-
if not (frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
185+
if not (self.is_coroutine(frame)
174186
and arg[0] is StopIteration and arg[2] is None):
175187
self.user_exception(frame, arg)
176188
if self.quitting: raise BdbQuit
@@ -179,7 +191,7 @@ def dispatch_exception(self, frame, arg):
179191
# next/until command at the last statement in the generator before the
180192
# exception.
181193
elif (self.stopframe and frame is not self.stopframe
182-
and self.stopframe.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
194+
and self.is_coroutine(self.stopframe)
183195
and arg[0] in (StopIteration, GeneratorExit)):
184196
self.user_exception(frame, arg)
185197
if self.quitting: raise BdbQuit
@@ -315,7 +327,7 @@ def set_next(self, frame):
315327

316328
def set_return(self, frame):
317329
"""Stop when returning from the given frame."""
318-
if frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
330+
if self.is_coroutine(frame):
319331
self._set_stopinfo(frame, None, -1)
320332
else:
321333
self._set_stopinfo(frame.f_back, frame)
@@ -557,7 +569,8 @@ def format_stack_entry(self, frame_lineno, lprefix=': '):
557569
line of code (if it exists).
558570
559571
"""
560-
import linecache, reprlib
572+
## MPY: reprlib not yet available
573+
import linecache #, reprlib
561574
frame, lineno = frame_lineno
562575
filename = self.canonic(frame.f_code.co_filename)
563576
s = '%s(%r)' % (filename, lineno)
@@ -569,7 +582,7 @@ def format_stack_entry(self, frame_lineno, lprefix=': '):
569582
if '__return__' in frame.f_locals:
570583
rv = frame.f_locals['__return__']
571584
s += '->'
572-
s += reprlib.repr(rv)
585+
s += repr(rv)
573586
line = linecache.getline(filename, lineno, frame.f_globals)
574587
if line:
575588
s += lprefix + line.strip()
@@ -628,7 +641,7 @@ def runctx(self, cmd, globals, locals):
628641

629642
# This method is more useful to debug a single function call.
630643

631-
def runcall(self, func, /, *args, **kwds):
644+
def runcall(self, func, *args, **kwds):
632645
"""Debug a single function call.
633646
634647
Return the result of the function call.

0 commit comments

Comments
 (0)