code: def read(self, size=-1):
          
          self._ensure_file()
  
          remainder = int(self.length) - self.__position
          if size < 0 or size > remainder:
              size = remainder
  
          if size == 0:
              return EMPTY
  
          received = 0
          data = StringIO()
          while received < size:
              chunk_data = self.readchunk()
              received += len(chunk_data)
              data.write(chunk_data)
  
          # Detect extra chunks after reading the entire file.
          if size == remainder and self.__chunk_iter:
              try:
                  self.__chunk_iter.next()
              except StopIteration:
                  pass
  
          self.__position -= received - size
  
          # Return 'size' bytes and store the rest.
          data.seek(size)
          self.__buffer = data.read()
          data.seek(0)
          return data.read(size)
docs: Read at most `size` bytes from the file (less if there
          isn't enough data).
  
          The bytes are returned as an instance of :class:`str` (:class:`bytes`
          in python 3). If `size` is negative or omitted all data is read.
  
          :Parameters:
            - `size` (optional): the number of bytes to read
  
          .. versionchanged:: 3.8
             This method now only checks for extra chunks after reading the
             entire file. Previously, this method would check for extra chunks
             on every call.