Skip to content

Commit

Permalink
Fix pycontribs#231: upload_file() fails when file_or_path is open fil…
Browse files Browse the repository at this point in the history
…e larger than 5GB and obj_name is specified
  • Loading branch information
Francis Devereux committed Oct 25, 2013
1 parent f658f30 commit b7bf790
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
6 changes: 3 additions & 3 deletions pyrax/cf_wrapper/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ def upload(fileobj, content_type, etag, headers):
# async design.
for segment in xrange(num_segments):
sequence = str(segment + 1).zfill(digits)
seg_name = "%s.%s" % (fname, sequence)
seg_name = "%s.%s" % (obj_name, sequence)
with utils.SelfDeletingTempfile() as tmpname:
with open(tmpname, "wb") as tmp:
tmp.write(fileobj.read(self.max_file_size))
Expand All @@ -781,8 +781,8 @@ def upload(fileobj, content_type, etag, headers):
etag=etag, headers=headers,
response_dict=extra_info)
# Upload the manifest
headers["X-Object-Meta-Manifest"] = "%s." % fname
return self.connection.put_object(cont.name, fname,
headers["X-Object-Meta-Manifest"] = "%s." % obj_name
return self.connection.put_object(cont.name, obj_name,
contents=None, headers=headers,
response_dict=extra_info)

Expand Down
34 changes: 34 additions & 0 deletions tests/unit/test_cf_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,40 @@ def _test_upload_large_file(self, call_upload_file):
client.get_object.assert_called_once_with(cont, fname)
client.get_object = gobj

@patch('pyrax.cf_wrapper.client.Container', new=FakeContainer)
def test_upload_large_file_from_file_object_with_obj_name(self):
client = self.client
client.connection.head_container = Mock()
client.connection.put_object = Mock()
cont = client.get_container(self.cont_name)
gobj = client.get_object
client.get_object = Mock(return_value=self.fake_object)
with utils.SelfDeletingTempfile() as tmpname:
small_file_contents = "Test Value " * 25
client.max_file_size = len(small_file_contents) - 1
with open(tmpname, "wb") as tmp:
tmp.write(small_file_contents)
fname = os.path.basename(tmpname)
fake_type = "test/test"
obj_name = 'not the same as filename'
with open(tmpname, "rb") as tmp:
client.upload_file(cont, tmp,
obj_name=obj_name, content_type=fake_type)
# Large files require 1 call for manifest, plus one for each
# segment. This should be a 2-segment file upload.
self.assertEqual(client.connection.put_object.call_count, 3)
put_calls = client.connection.put_object.mock_calls
self.assertEqual(put_calls[0][1][1], '%s.1' % obj_name)
self.assertEqual(put_calls[1][1][1], '%s.2' % obj_name)
self.assertEqual(put_calls[2][1][1], obj_name)
self.assertEqual(put_calls[2][2]["headers"]["X-Object-Meta-Manifest"],
obj_name + ".")

# get_object() should be called with the same name that was passed
# to the final put_object() call (to get the object to return)
client.get_object.assert_called_once_with(cont, obj_name)
client.get_object = gobj

@patch('pyrax.cf_wrapper.client.Container', new=FakeContainer)
def test_upload_folder_bad_folder(self):
self.assertRaises(exc.FolderNotFound, self.client.upload_folder,
Expand Down

0 comments on commit b7bf790

Please sign in to comment.