docs: def iterable_func(self):
          """
          An internal function which has generator semantics. Defined using the
          `yield` syntax.
          Used to grab the first element during class initialization, and
          subsequently on calls to `next()` to get the remaining elements.
          We rely on the implicit StopIteration built into this type of function
          to propagate through the final `next()` call.
          """
          # BFS is not done until the queue is empty
          while self.queue:
              logger.debug(
                  (
                      "recursive_operation_ls BFS queue not empty, "
                      "getting next path now."
                  )
              )
  
              # rate limit based on number of ls calls we have made
              self.ls_count += 1
              if self.ls_count % SLEEP_FREQUENCY == 0:
                  logger.debug(
                      (
                          "recursive_operation_ls sleeping {} seconds to "
                          "rate limit itself.".format(SLEEP_LEN)
                      )
                  )
                  time.sleep(SLEEP_LEN)
  
              # get path and current depth from the queue
              abs_path, rel_path, depth = self.queue.pop()
  
              # set the target path to the popped absolute path if it exists
              if abs_path:
                  self.ls_params["path"] = abs_path
  
              # if filter_after_first is False, stop filtering after the first
              # ls call has been made
              if not self.filter_after_first:
                  if self.filtering:
                      self.filtering = False
                  else:
                      try:
                          self.ls_params.pop("filter")
                      except KeyError:
                          pass
  
              # do the operation_ls with the updated params
              res = self.client.operation_ls(self.endpoint_id, **self.ls_params)
              res_data = res["DATA"]
  
              # if we aren't at the depth limit, add dir entries to the queue.
              # including the dir's name in the absolute and relative paths
              # and increase the depth by one.
              # data is reversed to maintain any "orderby" ordering
              if depth < self.max_depth:
                  self.queue.extend(
                      [
                          (
                              res["path"] + item["name"],
                              (rel_path + "/" if rel_path else "") + item["name"],
                              depth + 1,
                          )
                          for item in reversed(res_data)
                          if item["type"] == "dir"
                      ]
                  )
  
              # for each item in the response data update the item's name with
              # the relative path popped from the queue, and yield the item
              for item in res_data:
                  item["name"] = (rel_path + "/" if rel_path else "") + item["name"]
                  yield GlobusResponse(item)