5656 "ignore_filter" : None , # But see debugger.py
5757}
5858
59+
5960class TrepanCore :
60- def __init__ (self , debugger , opts : InitOptions = DEFAULT_INIT_OPTS ):
61+ def __init__ (self , debugger , opts : InitOptions = DEFAULT_INIT_OPTS ):
6162 """Create a debugger object. But depending on the value of
6263 key 'start' inside hash `opts', we may or may not initially
6364 start tracing events (i.e. enter the debugger).
@@ -197,7 +198,7 @@ def canonic_filename(self, frame: Optional[FrameType]) -> str:
197198
198199 filename = frame .f_code .co_filename
199200 if "<string>" == filename :
200- if ( new_filename := pyficache .main .code2tempfile .get (frame .f_code ) ):
201+ if new_filename := pyficache .main .code2tempfile .get (frame .f_code ):
201202 filename = new_filename
202203 return self .canonic (filename )
203204
@@ -231,7 +232,7 @@ def remove_ignore(self, frame_or_fn):
231232 be debugged"""
232233 return self .ignore_filter .remove (frame_or_fn )
233234
234- def start (self , opts : InitOptions = DEFAULT_INIT_OPTS ):
235+ def start (self , opts : InitOptions = DEFAULT_INIT_OPTS ):
235236 """We've already created a debugger object, but here we start
236237 debugging in earnest. We can also turn off debugging (but have
237238 the hooks suspended or not) using 'stop'.
@@ -292,32 +293,12 @@ def get_option(key: str) -> Any:
292293
293294 def is_break_here (self , frame ):
294295 filename = self .canonic (frame .f_code .co_filename )
295- if "call" == self .event :
296- find_name = frame .f_code
297- # Could check code object or decide not to
298- # The below could be done as a list comprehension, but
299- # I'm feeling in Fortran mood right now.
300- for fn in self .bpmgr .code_list :
301- if fn == find_name :
302- bp_fn = self .bpmgr .code_list .get (fn )
303- if not bp_fn :
304- return False
305- bp = bp_fn [0 ]
306- if bp .offset is not None and bp .offset != frame .f_lasti :
307- # print(f"XXXX core: have breakpoint, but offsets mismatch {bp.offset} vs {frame.f_lasti}")
308- return False
309- self .current_bp = bp
310- if bp .temporary :
311- msg = "temporary "
312- self .bpmgr .delete_breakpoint (bp )
313- else :
314- msg = ""
315- pass
316- self .stop_reason = f"at { msg } call breakpoint { bp .number } "
317- self .event = "brkpt"
318- return True
319- pass
320- pass
296+ code_object = frame .f_code
297+ brkpts_in_code = self .bpmgr .code2position_brkpts .get (code_object )
298+
299+ if brkpts_in_code is None :
300+ return False
301+
321302 if (filename , frame .f_lineno ) in list (self .bpmgr .bplist .keys ()):
322303 (bp , clear_bp ) = self .bpmgr .find_bp (filename , frame .f_lineno , frame )
323304 if bp :
@@ -339,6 +320,25 @@ def is_break_here(self, frame):
339320 return False
340321 return False
341322
323+ def is_call_break_here (self , frame ):
324+ code_object = frame .f_code
325+ brkpts_in_code = self .bpmgr .codecall_brkpts .get (code_object )
326+
327+ if brkpts_in_code is None :
328+ return False
329+ for bp in brkpts_in_code :
330+ self .current_bp = bp
331+ if bp .temporary :
332+ msg = "temporary "
333+ self .bpmgr .delete_breakpoint (bp )
334+ else :
335+ msg = ""
336+ pass
337+ self .stop_reason = f"at { msg } call breakpoint { bp .number } "
338+ self .event = "brkpt"
339+ return True
340+ return False
341+
342342 def matches_condition (self , frame ):
343343 # Conditional bp.
344344 # Ignore count applies only to those bpt hits where the
@@ -450,19 +450,25 @@ def trace_dispatch(self, frame, event: str, arg):
450450 # for breakpoints in a kind of slow way of checking all events.
451451
452452 remove_frame_on_return = False
453+ is_call_breakpoint = False
453454 # FIXME:
454455 # instead of self.bpmgr.bplist == 0, we should be counting on
455456 # per breakpoints in code object.
456457 if event == "call" :
457- if (self .last_frame != frame
458+ if (
459+ self .last_frame != frame
458460 and len (self .bpmgr .bplist ) == 0
459461 and self .stop_level is not None
460462 and self .stop_level < count_frames (frame )
461463 and self .current_thread == threading .current_thread ()
462- ):
464+ ):
463465 # We are "finish"ing or "next"ing and should not be tracing into this call
464466 # or any other calls from this. Return None to not trace further.
465- # print("""XXX+ trace_dispatch: "finish"ing or "next"ing from call event""")
467+
468+ # print(
469+ # """XXX+ trace_dispatch: "finish"ing or "next"ing from call event"""
470+ # )
471+
466472 frame .f_trace = None
467473 return None
468474
@@ -474,7 +480,11 @@ def trace_dispatch(self, frame, event: str, arg):
474480 # this function. In this case we need to ignore this stop, but
475481 # make sure we don't turn off breakpoints inside this function which
476482 # we do by returning "self".
477- return self
483+ if self .is_call_break_here (frame ):
484+ is_call_breakpoint = True
485+ else :
486+ # print("XXX+ trace_dispatch: is_stop_here() return")
487+ return self
478488
479489 elif event == "return" and frame in FrameInfo :
480490 remove_frame_on_return = True
@@ -535,7 +545,11 @@ def trace_dispatch(self, frame, event: str, arg):
535545 # user's standpoint to test for breaks before steps. In
536546 # this case we will need to factor out the counting
537547 # updates.
538- if self .is_stop_here (frame , event ) or self .is_break_here (frame ):
548+ if (
549+ self .is_stop_here (frame , event )
550+ or self .is_break_here (frame )
551+ or is_call_breakpoint
552+ ):
539553 # Run the event processor
540554 return self .processor .event_processor (frame , self .event , arg )
541555 # else:
@@ -549,6 +563,7 @@ def trace_dispatch(self, frame, event: str, arg):
549563 pass
550564 if remove_frame_on_return :
551565 del FrameInfo [frame ]
566+
552567 pass
553568
554569
0 commit comments