code: def listener(self, frame, event, arg):
      # print("listener", event, ":", frame)
      if event != "line":
          # It seems that we are getting CALL events even for calls in foo() from:
          #   with tsensor.explain(): foo()
          # Must be that we already have a listener and, though we returned None here,
          # somehow the original listener is still getting events. Strange but oh well.
          # We must ignore these.
          return None
      module = frame.f_globals["__name__"]
      info = inspect.getframeinfo(frame)
      filename, line = info.filename, info.lineno
      name = info.function
  
      # Note: always true since L292 above...
      if event == "line":
          self.line_listener(module, name, filename, line, info, frame)
  
      # By returning none, we prevent explain()'ing from descending into
      # invoked functions. In principle, we could allow a certain amount
      # of tracing but I'm not sure that would be super useful.
      return None
  
imports: import os
  import sys
  import traceback
  import inspect
  import hashlib
  from pathlib import Path
  import matplotlib.pyplot
  import tsensor
label_desc: Use image node_id 2 for calling the ExplainTensorTracer obj's underlying member method code with example usage: obj.listener(frame, event, arg) and returns: None, None