1""" 2Support for downloading objects from the object service, following best 3practices for that service. 4 5Downloaded data is written to a "writer" provided by a "writer factory". A 6writer has a `write` method which writes the entire passed buffer to storage. 7A writer factory is a callable which returns a fresh writer, ready to write the 8first byte of the object. When downloads are retried, the writer factory may 9be called more than once. 10 11This module provides several pre-defined writers and writer factories for 12common cases. 13""" 14import functools 15import six 16 17if six.PY2: 18 raise ImportError("download is only supported in Python 3") 19 20from .aio import download as aio_download 21from .aio.asyncutils import ensureCoro, runAsync 22 23 24def downloadToBuf(**kwargs): 25 """ 26 Convenience method to download data to an in-memory buffer and return the 27 downloaded data. Arguments are the same as `download`, except that 28 `writerFactory` should not be supplied. Returns a tuple (buffer, contentType). 29 """ 30 return runAsync(aio_download.downloadToBuf(**kwargs)) 31 32 33def downloadToFile(file, **kwargs): 34 """ 35 Convenience method to download data to a file object. The file must be 36 writeable, in binary mode, seekable (`f.seek`), and truncatable 37 (`f.truncate`) to support retries. Arguments are the same as `download`, 38 except that `writerFactory` should not be supplied. Returns the content-type. 39 """ 40 return runAsync(aio_download.downloadToFile(file=file, **kwargs)) 41 42 43def download(*, writerFactory, **kwargs): 44 """ 45 Download the named object from the object service, using a writer returned 46 from `writerFactory` to write the data. The `maxRetries` parameter has 47 the same meaning as for service clients. The `objectService` parameter is 48 an instance of the Object class, configured with credentials for the 49 upload. Returns the content-type. 50 """ 51 wrappedWriterFactory = _wrapSyncWriterFactory(writerFactory) 52 return runAsync(aio_download.download(writerFactory=wrappedWriterFactory, **kwargs)) 53 54 55def downloadArtifactToBuf(**kwargs): 56 """ 57 Convenience method to download an artifact to an in-memory buffer and return the 58 downloaded data. Arguments are the same as `downloadArtifact`, except that 59 `writerFactory` should not be supplied. Returns a tuple (buffer, contentType). 60 """ 61 return runAsync(aio_download.downloadArtifactToBuf(**kwargs)) 62 63 64def downloadArtifactToFile(file, **kwargs): 65 """ 66 Convenience method to download an artifact to a file object. The file must be 67 writeable, in binary mode, seekable (`f.seek`), and truncatable 68 (`f.truncate`) to support retries. Arguments are the same as `downloadArtifac`, 69 except that `writerFactory` should not be supplied. Returns the content-type. 70 """ 71 return runAsync(aio_download.downloadArtifactToFile(file=file, **kwargs)) 72 73 74def downloadArtifact(*, writerFactory, **kwargs): 75 """ 76 Download the named artifact with the appropriate storageType, using a writer returned 77 from `writerFactory` to write the data. The `maxRetries` parameter has 78 the same meaning as for service clients. The `queueService` parameter is 79 an instance of the Queue class, configured with credentials for the 80 download. Returns the content-type. 81 """ 82 wrappedWriterFactory = _wrapSyncWriterFactory(writerFactory) 83 return runAsync(aio_download.downloadArtifact(writerFactory=wrappedWriterFactory, **kwargs)) 84 85 86def _wrapSyncWriterFactory(writerFactory): 87 """Modify the reader returned by readerFactory to have an async read.""" 88 @functools.wraps(writerFactory) 89 async def wrappedFactory(): 90 writer = writerFactory() 91 writer.write = ensureCoro(writer.write) 92 return writer 93 94 return wrappedFactory 95