def _flush(self, finish=False):
    """Internal API to flush.

    Buffer is flushed to GCS only when the total amount of buffered data is at
    least self._blocksize, or to flush the final (incomplete) block of
    the file with finish=True.
    """
    while ((finish and self._buffered >= 0) or
           (not finish and self._buffered >= self._blocksize)):
      tmp_buffer = []
      tmp_buffer_len = 0

      excess = 0
      while self._buffer:
        buf = self._buffer.popleft()
        size = len(buf)
        self._buffered -= size
        tmp_buffer.append(buf)
        tmp_buffer_len += size
        if tmp_buffer_len >= self._maxrequestsize:
          excess = tmp_buffer_len - self._maxrequestsize
          break
        if not finish and (
            tmp_buffer_len % self._blocksize + self._buffered <
            self._blocksize):
          excess = tmp_buffer_len % self._blocksize
          break

      if excess:
        over = tmp_buffer.pop()
        size = len(over)
        assert size >= excess
        tmp_buffer_len -= size
        head, tail = over[:-excess], over[-excess:]
        self._buffer.appendleft(tail)
        self._buffered += len(tail)
        if head:
          tmp_buffer.append(head)
          tmp_buffer_len += len(head)

      data = ''.join(tmp_buffer)
      file_len = '*'
      if finish and not self._buffered:
        file_len = self._written + len(data)
      self._send_data(data, self._written, file_len)
      self._written += len(data)
      if file_len != '*':
        break
Internal API to flush.

    Buffer is flushed to GCS only when the total amount of buffered data is at
    least self._blocksize, or to flush the final (incomplete) block of
    the file with finish=True.