class_docstr: A DirectoryWatcher wraps a loader to load from a sequence of paths.
  
  A loader reads a path and produces some kind of values as an iterator. A
  DirectoryWatcher takes a directory, a factory for loaders, and optionally a
  path filter and watches all the paths inside that directory.
  
  This class is only valid under the assumption that only one path will be
  written to by the data source at a time and that once the source stops writing
  to a path, it will start writing to a new path that's lexicographically
  greater and never come back. It uses some heuristics to check whether this is
  true based on tracking changes to the files' sizes, but the check can have
  false negatives. However, it should have no false positives.
docstr: Internal implementation of Load().
  
  The only difference between this and Load() is that the latter will throw
  DirectoryDeletedError on I/O errors if it thinks that the directory has been
  permanently deleted.
  
  Yields:
    All values that have not been yielded yet.
docstr_tok: ["Internal","implementation","of","Load","(",")",".","The","only","difference","between","this","and","Load","(",")","is","that","the","latter","will","throw","DirectoryDeletedError","on","I\/O","errors","if","it","thinks","that","the","directory","has","been","permanently","deleted",".","Yields",":","All","values","that","have","not","been","yielded","yet","."]
code: def _LoadInternal(self):
      """Internal implementation of Load().
  
      The only difference between this and Load() is that the latter will throw
      DirectoryDeletedError on I/O errors if it thinks that the directory has been
      permanently deleted.
  
      Yields:
        All values that have not been yielded yet.
      """
  
      # If the loader exists, check it for a value.
      if not self._loader:
          self._InitializeLoader()
  
      # If it still doesn't exist, there is no data
      if not self._loader:
          return
  
      while True:
          # Yield all the new events in the path we're currently loading from.
          for event in self._loader.Load():
              yield event
  
          next_path = self._GetNextPath()
          if not next_path:
              logger.info("No path found after %s", self._path)
              # Current path is empty and there are no new paths, so we're done.
              return
  
          # There's a new path, so check to make sure there weren't any events
          # written between when we finished reading the current path and when we
          # checked for the new one. The sequence of events might look something
          # like this:
          #
          # 1. Event #1 written to path #1.
          # 2. We check for events and yield event #1 from path #1
          # 3. We check for events and see that there are no more events in path #1.
          # 4. Event #2 is written to path #1.
          # 5. Event #3 is written to path #2.
          # 6. We check for a new path and see that path #2 exists.
          #
          # Without this loop, we would miss event #2. We're also guaranteed by the
          # loader contract that no more events will be written to path #1 after
          # events start being written to path #2, so we don't have to worry about
          # that.
          for event in self._loader.Load():
              yield event
  
          logger.info(
              "Directory watcher advancing from %s to %s",
              self._path,
              next_path,
          )
  
          # Advance to the next path and start over.
          self._SetPath(next_path)
  
file_path: tensorboard/tensorboard/backend/event_processing/directory_watcher.py
imports: import bisect
  from tensorboard.backend.event_processing import io_wrapper
  from tensorboard.compat import tf
  from tensorboard.util import io_util
  from tensorboard.util import tb_logging
label_desc: Use image node_id 3 for calling the DirectoryWatcher obj's underlying member method code with example usage: obj._LoadInternal() without return types