1
1
"""Debugger basics"""
2
2
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
+
3
6
import fnmatch
4
7
import sys
5
8
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
7
12
8
13
__all__ = ["BdbQuit" , "Bdb" , "Breakpoint" ]
9
14
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
11
17
12
18
13
19
class BdbQuit (Exception ):
@@ -46,11 +52,12 @@ def canonic(self, filename):
46
52
"""
47
53
if filename == "<" + filename [1 :- 1 ] + ">" :
48
54
return filename
55
+
49
56
canonic = self .fncache .get (filename )
50
57
if not canonic :
51
58
canonic = os .path .abspath (filename )
52
59
canonic = os .path .normcase (canonic )
53
- self .fncache [filename ] = canonic
60
+ self .fncache [filename ] = canonic
54
61
return canonic
55
62
56
63
def reset (self ):
@@ -115,6 +122,12 @@ def dispatch_line(self, frame):
115
122
if self .quitting : raise BdbQuit
116
123
return self .trace_dispatch
117
124
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
+
118
131
def dispatch_call (self , frame , arg ):
119
132
"""Invoke user function and return trace function for call event.
120
133
@@ -131,7 +144,7 @@ def dispatch_call(self, frame, arg):
131
144
# No need to trace this function
132
145
return # None
133
146
# 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 ) :
135
148
return self .trace_dispatch
136
149
self .user_call (frame , arg )
137
150
if self .quitting : raise BdbQuit
@@ -146,7 +159,7 @@ def dispatch_return(self, frame, arg):
146
159
"""
147
160
if self .stop_here (frame ) or frame == self .returnframe :
148
161
# 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 ) :
150
163
return self .trace_dispatch
151
164
try :
152
165
self .frame_returning = frame
@@ -170,7 +183,7 @@ def dispatch_exception(self, frame, arg):
170
183
# When stepping with next/until/return in a generator frame, skip
171
184
# the internal StopIteration exception (with no traceback)
172
185
# 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 )
174
187
and arg [0 ] is StopIteration and arg [2 ] is None ):
175
188
self .user_exception (frame , arg )
176
189
if self .quitting : raise BdbQuit
@@ -179,7 +192,7 @@ def dispatch_exception(self, frame, arg):
179
192
# next/until command at the last statement in the generator before the
180
193
# exception.
181
194
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 )
183
196
and arg [0 ] in (StopIteration , GeneratorExit )):
184
197
self .user_exception (frame , arg )
185
198
if self .quitting : raise BdbQuit
@@ -315,7 +328,7 @@ def set_next(self, frame):
315
328
316
329
def set_return (self , frame ):
317
330
"""Stop when returning from the given frame."""
318
- if frame . f_code . co_flags & GENERATOR_AND_COROUTINE_FLAGS :
331
+ if self . is_coroutine ( frame ) :
319
332
self ._set_stopinfo (frame , None , - 1 )
320
333
else :
321
334
self ._set_stopinfo (frame .f_back , frame )
@@ -326,7 +339,7 @@ def set_trace(self, frame=None):
326
339
If frame is not specified, debugging starts from caller's frame.
327
340
"""
328
341
if frame is None :
329
- frame = sys ._getframe (). f_back
342
+ frame = sys ._getframe (1 )
330
343
self .reset ()
331
344
while frame :
332
345
frame .f_trace = self .trace_dispatch
@@ -345,7 +358,8 @@ def set_continue(self):
345
358
if not self .breaks :
346
359
# no breakpoints; run without debugger overhead
347
360
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 )
349
363
while frame and frame is not self .botframe :
350
364
del frame .f_trace
351
365
frame = frame .f_back
@@ -557,7 +571,11 @@ def format_stack_entry(self, frame_lineno, lprefix=': '):
557
571
line of code (if it exists).
558
572
559
573
"""
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
561
579
frame , lineno = frame_lineno
562
580
filename = self .canonic (frame .f_code .co_filename )
563
581
s = '%s(%r)' % (filename , lineno )
@@ -569,7 +587,7 @@ def format_stack_entry(self, frame_lineno, lprefix=': '):
569
587
if '__return__' in frame .f_locals :
570
588
rv = frame .f_locals ['__return__' ]
571
589
s += '->'
572
- s += reprlib . repr (rv )
590
+ s += repr (rv )
573
591
line = linecache .getline (filename , lineno , frame .f_globals )
574
592
if line :
575
593
s += lprefix + line .strip ()
@@ -628,7 +646,7 @@ def runctx(self, cmd, globals, locals):
628
646
629
647
# This method is more useful to debug a single function call.
630
648
631
- def runcall (self , func , / , * args , ** kwds ):
649
+ def runcall (self , func , * args , ** kwds ):
632
650
"""Debug a single function call.
633
651
634
652
Return the result of the function call.
0 commit comments