docs: def _log(level, message, frame_depth=2, **kwargs):
      """
      Log the given message with the given log level using a logger named based 
      on the scope of the calling code.  This saves you time because you will be 
      able to see where all your log messages are being generated from without 
      having to type anything.  This function is meant to be called by one or 
      more wrapper functions, so the `frame_depth` argument is provided to 
      specify which scope should be used to name the logger.
      """
      import inspect
  
      try:
          # Inspect variables two frames up from where we currently are (by 
          # default).  One frame up is assumed to be one of the helper methods 
          # defined in this module, so we aren't interested in that.  Two frames 
          # up should be the frame that's actually trying to log something.
  
          frame = inspect.stack()[frame_depth][0]
          frame_below = inspect.stack()[frame_depth-1][0]
          
          # Collect all the variables in the scope of the calling code, so they 
          # can be substituted into the message.
  
          scope = {}
          scope.update(frame.f_globals)
          scope.update(frame.f_locals)
  
          # If the calling frame is inside a class (deduced based on the presence 
          # of a 'self' variable), name the logger after that class.  Otherwise 
          # if the calling frame is inside a function, name the logger after that 
          # function.  Otherwise name it after the module of the calling scope.
  
          self = frame.f_locals.get('self')
          function = inspect.getframeinfo(frame).function
          module = frame.f_globals['__name__']
  
          if self is not None:
              name = '.'.join([
                      self.__class__.__module__,
                      self.__class__.__name__
              ])
  
          elif function != '<module>':
              name = '.'.join([module, function])
  
          else:
              name = module
  
          # Trick the logging module into reading file names and line numbers 
          # from the correct frame by monkey-patching logging.currentframe() with 
          # a function that returns the frame below the real calling frame (this 
          # indirection is necessary because the logging module will look one 
          # frame above whatever this function returns).  Undo all this after 
          # logging our message, to avoid interfering with other loggers.
  
          with _temporarily_set_logging_frame(frame_below):
              logger = logging.getLogger(name)
              logger.log(level, message.format(**scope), **kwargs)
  
      finally:
          try: del frame
          except UnboundLocalError: pass