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,17 +52,21 @@ def canonic(self, filename):
4652 """
4753 if filename == "<" + filename [1 :- 1 ] + ">" :
4854 return filename
49- canonic = self .fncache .get (filename )
50- if not canonic :
51- canonic = os .path .abspath (filename )
52- canonic = os .path .normcase (canonic )
53- self .fncache [filename ] = canonic
54- return canonic
55+
56+ ## MPY: os.path module difficult to add as dependency
57+ # canonic = self.fncache.get(filename)
58+ # if not canonic:
59+ # canonic = os.path.abspath(filename)
60+ # canonic = os.path.normcase(canonic)
61+ # self.fncache[filename] = canonic
62+ # return canonic
63+ return filename
5564
5665 def reset (self ):
5766 """Set values of attributes as ready to start debugging."""
58- import linecache
59- linecache .checkcache ()
67+ ## MPY: linecache not yet available
68+ # import linecache
69+ # linecache.checkcache()
6070 self .botframe = None
6171 self ._set_stopinfo (None , None )
6272
@@ -115,6 +125,12 @@ def dispatch_line(self, frame):
115125 if self .quitting : raise BdbQuit
116126 return self .trace_dispatch
117127
128+ def is_coroutine (self , frame ):
129+ ## MPY: co_flags attrib not available, compatible method of detecting coroutine TBD
130+ # return frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
131+ return False
132+
133+
118134 def dispatch_call (self , frame , arg ):
119135 """Invoke user function and return trace function for call event.
120136
@@ -131,7 +147,7 @@ def dispatch_call(self, frame, arg):
131147 # No need to trace this function
132148 return # None
133149 # Ignore call events in generator except when stepping.
134- if self .stopframe and frame . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS :
150+ if self .stopframe and self . is_coroutine ( frame ) :
135151 return self .trace_dispatch
136152 self .user_call (frame , arg )
137153 if self .quitting : raise BdbQuit
@@ -146,7 +162,7 @@ def dispatch_return(self, frame, arg):
146162 """
147163 if self .stop_here (frame ) or frame == self .returnframe :
148164 # Ignore return events in generator except when stepping.
149- if self .stopframe and frame . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS :
165+ if self .stopframe and self . is_coroutine ( frame ) :
150166 return self .trace_dispatch
151167 try :
152168 self .frame_returning = frame
@@ -170,7 +186,7 @@ def dispatch_exception(self, frame, arg):
170186 # When stepping with next/until/return in a generator frame, skip
171187 # the internal StopIteration exception (with no traceback)
172188 # triggered by a subiterator run with the 'yield from' statement.
173- if not (frame . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS
189+ if not (self . is_coroutine ( frame )
174190 and arg [0 ] is StopIteration and arg [2 ] is None ):
175191 self .user_exception (frame , arg )
176192 if self .quitting : raise BdbQuit
@@ -179,7 +195,7 @@ def dispatch_exception(self, frame, arg):
179195 # next/until command at the last statement in the generator before the
180196 # exception.
181197 elif (self .stopframe and frame is not self .stopframe
182- and self .stopframe . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS
198+ and self .is_coroutine ( self . stopframe )
183199 and arg [0 ] in (StopIteration , GeneratorExit )):
184200 self .user_exception (frame , arg )
185201 if self .quitting : raise BdbQuit
@@ -305,8 +321,9 @@ def set_step(self):
305321 # for performance reasons) when returning from the current frame.
306322 if self .frame_returning :
307323 caller_frame = self .frame_returning .f_back
308- if caller_frame and not caller_frame .f_trace :
309- caller_frame .f_trace = self .trace_dispatch
324+ ## MPY: f_trace attrib not yet available
325+ # if caller_frame and not caller_frame.f_trace:
326+ # caller_frame.f_trace = self.trace_dispatch
310327 self ._set_stopinfo (None , None )
311328
312329 def set_next (self , frame ):
@@ -315,7 +332,7 @@ def set_next(self, frame):
315332
316333 def set_return (self , frame ):
317334 """Stop when returning from the given frame."""
318- if frame . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS :
335+ if self . is_coroutine ( frame ) :
319336 self ._set_stopinfo (frame , None , - 1 )
320337 else :
321338 self ._set_stopinfo (frame .f_back , frame )
@@ -326,12 +343,13 @@ def set_trace(self, frame=None):
326343 If frame is not specified, debugging starts from caller's frame.
327344 """
328345 if frame is None :
329- frame = sys ._getframe (). f_back
346+ frame = sys ._getframe (1 )
330347 self .reset ()
331- while frame :
332- frame .f_trace = self .trace_dispatch
333- self .botframe = frame
334- frame = frame .f_back
348+ ## MPY: f_trace attrib not yet available
349+ # while frame:
350+ # frame.f_trace = self.trace_dispatch
351+ # self.botframe = frame
352+ # frame = frame.f_back
335353 self .set_step ()
336354 sys .settrace (self .trace_dispatch )
337355
@@ -345,10 +363,12 @@ def set_continue(self):
345363 if not self .breaks :
346364 # no breakpoints; run without debugger overhead
347365 sys .settrace (None )
348- frame = sys ._getframe ().f_back
349- while frame and frame is not self .botframe :
350- del frame .f_trace
351- frame = frame .f_back
366+ ## MPY: was sys._getframe().f_back but f_back missing when inside trace dispatch functions
367+ frame = sys ._getframe (1 )
368+ ## MPY: f_trace attrib not yet available
369+ # while frame and frame is not self.botframe:
370+ # del frame.f_trace
371+ # frame = frame.f_back
352372
353373 def set_quit (self ):
354374 """Set quitting attribute to True.
@@ -381,10 +401,11 @@ def set_break(self, filename, lineno, temporary=False, cond=None,
381401 The filename should be in canonical form.
382402 """
383403 filename = self .canonic (filename )
384- import linecache # Import as late as possible
385- line = linecache .getline (filename , lineno )
386- if not line :
387- return 'Line %s:%d does not exist' % (filename , lineno )
404+ ## MPY: linecache not yet available
405+ # import linecache # Import as late as possible
406+ # line = linecache.getline(filename, lineno)
407+ # if not line:
408+ # return 'Line %s:%d does not exist' % (filename, lineno)
388409 self ._add_to_breaks (filename , lineno )
389410 bp = Breakpoint (filename , lineno , temporary , cond , funcname )
390411 return None
@@ -557,23 +578,26 @@ def format_stack_entry(self, frame_lineno, lprefix=': '):
557578 line of code (if it exists).
558579
559580 """
560- import linecache , reprlib
561581 frame , lineno = frame_lineno
562- filename = self .canonic (frame .f_code .co_filename )
563- s = '%s(%r)' % (filename , lineno )
564- if frame .f_code .co_name :
565- s += frame .f_code .co_name
566- else :
567- s += "<lambda>"
568- s += '()'
569- if '__return__' in frame .f_locals :
570- rv = frame .f_locals ['__return__' ]
571- s += '->'
572- s += reprlib .repr (rv )
573- line = linecache .getline (filename , lineno , frame .f_globals )
574- if line :
575- s += lprefix + line .strip ()
576- return s
582+ return repr (frame .f_code )
583+ ## MPY: linecache, reprlib, f_locals not yet available
584+ # import linecache, reprlib
585+ # frame, lineno = frame_lineno
586+ # filename = self.canonic(frame.f_code.co_filename)
587+ # s = '%s(%r)' % (filename, lineno)
588+ # if frame.f_code.co_name:
589+ # s += frame.f_code.co_name
590+ # else:
591+ # s += "<lambda>"
592+ # s += '()'
593+ # if '__return__' in frame.f_locals:
594+ # rv = frame.f_locals['__return__']
595+ # s += '->'
596+ # s += reprlib.repr(rv)
597+ # line = linecache.getline(filename, lineno, frame.f_globals)
598+ # if line:
599+ # s += lprefix + line.strip()
600+ # return s
577601
578602 # The following methods can be called by clients to use
579603 # a debugger to debug a statement or an expression.
@@ -628,7 +652,7 @@ def runctx(self, cmd, globals, locals):
628652
629653 # This method is more useful to debug a single function call.
630654
631- def runcall (self , func , / , * args , ** kwds ):
655+ def runcall (self , func , * args , ** kwds ):
632656 """Debug a single function call.
633657
634658 Return the result of the function call.
0 commit comments