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+
36import fnmatch
47import sys
58import 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
1319class BdbQuit (Exception ):
@@ -46,11 +52,12 @@ def canonic(self, filename):
4652 """
4753 if filename == "<" + filename [1 :- 1 ] + ">" :
4854 return filename
55+
4956 canonic = self .fncache .get (filename )
5057 if not canonic :
5158 canonic = os .path .abspath (filename )
5259 canonic = os .path .normcase (canonic )
53- self .fncache [filename ] = canonic
60+ self .fncache [filename ] = canonic
5461 return canonic
5562
5663 def reset (self ):
@@ -115,6 +122,12 @@ def dispatch_line(self, frame):
115122 if self .quitting : raise BdbQuit
116123 return self .trace_dispatch
117124
125+ def is_coroutine (self , frame ):
126+ ## MPY: co_flags attrib not available, compatible method of detecting coroutine TBD
127+ # return frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
128+ return False
129+
130+
118131 def dispatch_call (self , frame , arg ):
119132 """Invoke user function and return trace function for call event.
120133
@@ -131,7 +144,7 @@ def dispatch_call(self, frame, arg):
131144 # No need to trace this function
132145 return # None
133146 # Ignore call events in generator except when stepping.
134- if self .stopframe and frame . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS :
147+ if self .stopframe and self . is_coroutine ( frame ) :
135148 return self .trace_dispatch
136149 self .user_call (frame , arg )
137150 if self .quitting : raise BdbQuit
@@ -146,7 +159,7 @@ def dispatch_return(self, frame, arg):
146159 """
147160 if self .stop_here (frame ) or frame == self .returnframe :
148161 # Ignore return events in generator except when stepping.
149- if self .stopframe and frame . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS :
162+ if self .stopframe and self . is_coroutine ( frame ) :
150163 return self .trace_dispatch
151164 try :
152165 self .frame_returning = frame
@@ -170,7 +183,7 @@ def dispatch_exception(self, frame, arg):
170183 # When stepping with next/until/return in a generator frame, skip
171184 # the internal StopIteration exception (with no traceback)
172185 # triggered by a subiterator run with the 'yield from' statement.
173- if not (frame . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS
186+ if not (self . is_coroutine ( frame )
174187 and arg [0 ] is StopIteration and arg [2 ] is None ):
175188 self .user_exception (frame , arg )
176189 if self .quitting : raise BdbQuit
@@ -179,7 +192,7 @@ def dispatch_exception(self, frame, arg):
179192 # next/until command at the last statement in the generator before the
180193 # exception.
181194 elif (self .stopframe and frame is not self .stopframe
182- and self .stopframe . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS
195+ and self .is_coroutine ( self . stopframe )
183196 and arg [0 ] in (StopIteration , GeneratorExit )):
184197 self .user_exception (frame , arg )
185198 if self .quitting : raise BdbQuit
@@ -315,7 +328,7 @@ def set_next(self, frame):
315328
316329 def set_return (self , frame ):
317330 """Stop when returning from the given frame."""
318- if frame . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS :
331+ if self . is_coroutine ( frame ) :
319332 self ._set_stopinfo (frame , None , - 1 )
320333 else :
321334 self ._set_stopinfo (frame .f_back , frame )
@@ -326,7 +339,7 @@ def set_trace(self, frame=None):
326339 If frame is not specified, debugging starts from caller's frame.
327340 """
328341 if frame is None :
329- frame = sys ._getframe (). f_back
342+ frame = sys ._getframe (1 )
330343 self .reset ()
331344 while frame :
332345 frame .f_trace = self .trace_dispatch
@@ -345,7 +358,8 @@ def set_continue(self):
345358 if not self .breaks :
346359 # no breakpoints; run without debugger overhead
347360 sys .settrace (None )
348- frame = sys ._getframe ().f_back
361+ ## MPY: was sys._getframe().f_back but f_back missing when inside trace dispatch functions
362+ frame = sys ._getframe (1 )
349363 while frame and frame is not self .botframe :
350364 del frame .f_trace
351365 frame = frame .f_back
@@ -557,7 +571,11 @@ def format_stack_entry(self, frame_lineno, lprefix=': '):
557571 line of code (if it exists).
558572
559573 """
560- import linecache , reprlib
574+ # frame, lineno = frame_lineno
575+ # return repr(frame.f_code)
576+ ## MPY: linecache, reprlib, f_locals not yet available
577+ # import linecache, reprlib
578+ import linecache
561579 frame , lineno = frame_lineno
562580 filename = self .canonic (frame .f_code .co_filename )
563581 s = '%s(%r)' % (filename , lineno )
@@ -569,7 +587,7 @@ def format_stack_entry(self, frame_lineno, lprefix=': '):
569587 if '__return__' in frame .f_locals :
570588 rv = frame .f_locals ['__return__' ]
571589 s += '->'
572- s += reprlib . repr (rv )
590+ s += repr (rv )
573591 line = linecache .getline (filename , lineno , frame .f_globals )
574592 if line :
575593 s += lprefix + line .strip ()
@@ -628,7 +646,7 @@ def runctx(self, cmd, globals, locals):
628646
629647 # This method is more useful to debug a single function call.
630648
631- def runcall (self , func , / , * args , ** kwds ):
649+ def runcall (self , func , * args , ** kwds ):
632650 """Debug a single function call.
633651
634652 Return the result of the function call.
0 commit comments