code: def on_breakpoints_changed(self, removed=False):
          '''
          When breakpoints change, we have to re-evaluate all the assumptions we've made so far.
          '''
          if not self.ready_to_run:
              # No need to do anything if we're still not running.
              return
  
          self.mtime += 1
          if not removed:
              # When removing breakpoints we can leave tracing as was, but if a breakpoint was added
              # we have to reset the tracing for the existing functions to be re-evaluated.
              self.set_tracing_for_untraced_contexts(f on_breakpoints_changed(self, removed=False):
          '''
          When breakpoints change, we have to re-evaluate all the assumptions we've made so far.
          '''
          if not self.ready_to_run:
              # No need to do anything if we're still not running.
              return
  
          self.mtime += 1
          if not removed:
              # When removing breakpoints we can leave tracing as was, but if a breakpoint was added
              # we have to reset the tracing for the existing functions to be re-evaluated.
              self.set_tracing_for_untraced_contexts()
docs: When breakpoints change, we have to re-evaluate all the assumptions we've made so far.