def __init__(self, blob: Blob, chunk_size: int = default_chunk_size, async_queue: Optional[AsyncQueue] = None): assert chunk_size >= 1 if blob.size is None: blob.reload() if blob.chunk_size is None: # Induce google.cloud.storage.blob to use either google.resumable_media.requests.ChunkedDownload or # google.resumable_media.requests.RawChunkedDownload, which do not attempt to perform data-integrity checks # for chunk downloads (checksum headers are not available for chunks). blob.chunk_size = ceil( chunk_size / _BLOB_CHUNK_SIZE_UNIT) * _BLOB_CHUNK_SIZE_UNIT self.blob = blob self.chunk_size = chunk_size self._buffer = bytearray() self._pos = 0 self.number_of_chunks = ceil( self.blob.size / self.chunk_size) if 0 < self.blob.size else 1 self._unfetched_chunks = [i for i in range(self.number_of_chunks)] self.future_chunk_downloads: Optional[AsyncQueue] if async_queue is not None: self.future_chunk_downloads = async_queue for chunk_number in self._unfetched_chunks: self.future_chunk_downloads.put(self._fetch_chunk, chunk_number) else: self.future_chunk_downloads = None