def _put_object(self, path, content, chunk=None, content_type=None, content_encoding=None, headers=None): # ReadableToIterable supports both file-like objects yielding str or bytes, # and will try utf-8 encode the result if it is a string. # The following assertion make sure that the content is either some bytes or # a file-like stream of bytes, for consistency across all storage implementations. assert isinstance(content, bytes) or issubclass( type(content), (IOBase, GeneratorFile, ReadableToIterable, filelike.BaseStreamFilelike)) path = self._normalize_path(path) headers = headers or {} if content_encoding is not None: headers["Content-Encoding"] = content_encoding is_filelike = hasattr(content, "read") if is_filelike: content = ReadableToIterable(content, md5=True) try: etag = self._get_connection().put_object( self._swift_container, path, content, chunk_size=chunk, content_type=content_type, headers=headers, ) except ClientException: # We re-raise client exception here so that validation of config during setup can see # the client exception messages. raise # If we wrapped the content in a ReadableToIterable, compare its MD5 to the etag returned. If # they don't match, raise an IOError indicating a write failure. if is_filelike: if etag != content.get_md5sum(): logger.error( "Got mismatch in md5 etag for path %s: Expected %s, but server has %s", path, content.get_md5sum(), etag, ) raise IOError("upload verification failed for path {0}:" "md5 mismatch, local {1} != remote {2}".format( path, content.get_md5sum(), etag))
def _put_object(self, path, content, chunk=None, content_type=None, content_encoding=None, headers=None): path = self._normalize_path(path) headers = headers or {} if content_encoding is not None: headers["Content-Encoding"] = content_encoding is_filelike = hasattr(content, "read") if is_filelike: content = ReadableToIterable(content, md5=True) try: etag = self._get_connection().put_object( self._swift_container, path, content, chunk_size=chunk, content_type=content_type, headers=headers, ) except ClientException: # We re-raise client exception here so that validation of config during setup can see # the client exception messages. raise # If we wrapped the content in a ReadableToIterable, compare its MD5 to the etag returned. If # they don't match, raise an IOError indicating a write failure. if is_filelike: if etag != content.get_md5sum(): logger.error( "Got mismatch in md5 etag for path %s: Expected %s, but server has %s", path, content.get_md5sum(), etag, ) raise IOError("upload verification failed for path {0}:" "md5 mismatch, local {1} != remote {2}".format( path, content.get_md5sum(), etag))
def test_simple_put_get(): swift = FakeSwiftStorage(**base_args) assert not swift.exists("somepath") swift.put_content("somepath", b"hello world!") assert swift.exists("somepath") assert swift.get_content("somepath") == b"hello world!" swift.put_content("someotherpath", LimitedStream(io.BytesIO(b"hello world2"), 12)) assert swift.exists("someotherpath") assert swift.get_content("someotherpath") == b"hello world2" swift.put_content("yetsomeotherpath", ReadableToIterable(b"hello world3")) assert swift.exists("yetsomeotherpath") assert swift.get_content("yetsomeotherpath") == b"hello world3" swift.put_content("againsomeotherpath", io.BytesIO(b"hello world4")) assert swift.exists("againsomeotherpath") assert swift.get_content("againsomeotherpath") == b"hello world4"