code: def _next_batch(self) -> Optional[Batch]:
          
          if self._epoch_limit_reached():
              self._batch_count = 0
              return None
          try:
              batch = next(self._get_stream())
              self._batch_count += 1
              return batch
          except StopIteration:
              self._stream = None  # yield a new iterator next time
              if self._epoch_size > 0:  # underlying stream ended but our fixed size epoch did not
                  batch = next(self._get_stream())  # get another stream and return its 1st batch
                  self._batch_count += 1
                  return batch
              else:
                  self._batch_count = 0
                  return None
docs: Return a single batch or ``None`` signaling epoch end.
  
          .. note::
              Signal the epoch end with ``None``.
  
          Stop when:
          - stream ends and epoch size is not set
          - specified number of batches is returned
  
          :return: a single batch or ``None`` signaling epoch end