Skip to content

Commit

Permalink
Removing using of Blob.connection in all Blob.upload* methods.
Browse files Browse the repository at this point in the history
Allowing the default connection to be used as fallback or takes
an explicit connection argument.
  • Loading branch information
dhermes committed Apr 15, 2015
1 parent 8a16e39 commit a54b630
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 23 deletions.
52 changes: 35 additions & 17 deletions gcloud/storage/blob.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ def download_as_string(self, connection=None):
return string_buffer.getvalue()

def upload_from_file(self, file_obj, rewind=False, size=None,
content_type=None, num_retries=6):
content_type=None, num_retries=6, connection=None):
"""Upload the contents of this blob from a file-like object.
The content type of the upload will either be
Expand Down Expand Up @@ -367,7 +367,13 @@ def upload_from_file(self, file_obj, rewind=False, size=None,
:type num_retries: integer
:param num_retries: Number of upload retries. Defaults to 6.
:type connection: :class:`gcloud.storage.connection.Connection` or
``NoneType``
:param connection: Optional. The connection to use when sending
requests. If not provided, falls back to default.
"""
connection = _require_connection(connection)
content_type = (content_type or self._properties.get('contentType') or
'application/octet-stream')

Expand All @@ -377,11 +383,10 @@ def upload_from_file(self, file_obj, rewind=False, size=None,

# Get the basic stats about the file.
total_bytes = size or os.fstat(file_obj.fileno()).st_size
conn = self.connection
headers = {
'Accept': 'application/json',
'Accept-Encoding': 'gzip, deflate',
'User-Agent': conn.USER_AGENT,
'User-Agent': connection.USER_AGENT,
}

upload = transfer.Upload(file_obj, content_type, total_bytes,
Expand All @@ -393,20 +398,20 @@ def upload_from_file(self, file_obj, rewind=False, size=None,
upload_config = _UploadConfig()

# Temporary URL, until we know simple vs. resumable.
base_url = conn.API_BASE_URL + '/upload'
upload_url = conn.build_api_url(api_base_url=base_url,
path=self.bucket.path + '/o')
base_url = connection.API_BASE_URL + '/upload'
upload_url = connection.build_api_url(api_base_url=base_url,
path=self.bucket.path + '/o')

# Use apitools 'Upload' facility.
request = http_wrapper.Request(upload_url, 'POST', headers)

upload.ConfigureRequest(upload_config, request, url_builder)
query_params = url_builder.query_params
base_url = conn.API_BASE_URL + '/upload'
request.url = conn.build_api_url(api_base_url=base_url,
path=self.bucket.path + '/o',
query_params=query_params)
upload.InitializeUpload(request, conn.http)
base_url = connection.API_BASE_URL + '/upload'
request.url = connection.build_api_url(api_base_url=base_url,
path=self.bucket.path + '/o',
query_params=query_params)
upload.InitializeUpload(request, connection.http)

# Should we be passing callbacks through from caller? We can't
# pass them as None, because apitools wants to print to the console
Expand All @@ -416,15 +421,16 @@ def upload_from_file(self, file_obj, rewind=False, size=None,
callback=lambda *args: None,
finish_callback=lambda *args: None)
else:
http_response = http_wrapper.MakeRequest(conn.http, request,
http_response = http_wrapper.MakeRequest(connection.http, request,
retries=num_retries)
response_content = http_response.content
if not isinstance(response_content,
six.string_types): # pragma: NO COVER Python3
response_content = response_content.decode('utf-8')
self._set_properties(json.loads(response_content))

def upload_from_filename(self, filename, content_type=None):
def upload_from_filename(self, filename, content_type=None,
connection=None):
"""Upload this blob's contents from the content of a named file.
The content type of the upload will either be
Expand All @@ -448,15 +454,22 @@ def upload_from_filename(self, filename, content_type=None):
:type content_type: string or ``NoneType``
:param content_type: Optional type of content being uploaded.
:type connection: :class:`gcloud.storage.connection.Connection` or
``NoneType``
:param connection: Optional. The connection to use when sending
requests. If not provided, falls back to default.
"""
content_type = content_type or self._properties.get('contentType')
if content_type is None:
content_type, _ = mimetypes.guess_type(filename)

with open(filename, 'rb') as file_obj:
self.upload_from_file(file_obj, content_type=content_type)
self.upload_from_file(file_obj, content_type=content_type,
connection=connection)

def upload_from_string(self, data, content_type='text/plain'):
def upload_from_string(self, data, content_type='text/plain',
connection=None):
"""Upload contents of this blob from the provided string.
.. note::
Expand All @@ -473,14 +486,19 @@ def upload_from_string(self, data, content_type='text/plain'):
:type data: bytes or text
:param data: The data to store in this blob. If the value is
text, it will be encoded as UTF-8.
:type connection: :class:`gcloud.storage.connection.Connection` or
``NoneType``
:param connection: Optional. The connection to use when sending
requests. If not provided, falls back to default.
"""
if isinstance(data, six.text_type):
data = data.encode('utf-8')
string_buffer = BytesIO()
string_buffer.write(data)
self.upload_from_file(file_obj=string_buffer, rewind=True,
size=len(data),
content_type=content_type)
size=len(data), content_type=content_type,
connection=connection)

def make_public(self):
"""Make this blob public giving all users read access."""
Expand Down
14 changes: 8 additions & 6 deletions gcloud/storage/test_blob.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,8 @@ def _upload_from_file_simple_test_helper(self, properties=None,
fh.write(DATA)
fh.flush()
blob.upload_from_file(fh, rewind=True,
content_type=content_type_arg)
content_type=content_type_arg,
connection=connection)
rq = connection.http._requested
self.assertEqual(len(rq), 1)
self.assertEqual(rq[0]['method'], 'POST')
Expand Down Expand Up @@ -479,7 +480,7 @@ def test_upload_from_file_resumable(self):
with NamedTemporaryFile() as fh:
fh.write(DATA)
fh.flush()
blob.upload_from_file(fh, rewind=True)
blob.upload_from_file(fh, rewind=True, connection=connection)
rq = connection.http._requested
self.assertEqual(len(rq), 3)
self.assertEqual(rq[0]['method'], 'POST')
Expand Down Expand Up @@ -535,7 +536,7 @@ def test_upload_from_file_w_slash_in_name(self):
with NamedTemporaryFile() as fh:
fh.write(DATA)
fh.flush()
blob.upload_from_file(fh, rewind=True)
blob.upload_from_file(fh, rewind=True, connection=connection)
self.assertEqual(fh.tell(), len(DATA))
rq = connection.http._requested
self.assertEqual(len(rq), 1)
Expand Down Expand Up @@ -583,7 +584,8 @@ def _upload_from_filename_test_helper(self, properties=None,
with NamedTemporaryFile(suffix='.jpeg') as fh:
fh.write(DATA)
fh.flush()
blob.upload_from_filename(fh.name, content_type=content_type_arg)
blob.upload_from_filename(fh.name, content_type=content_type_arg,
connection=connection)
rq = connection.http._requested
self.assertEqual(len(rq), 1)
self.assertEqual(rq[0]['method'], 'POST')
Expand Down Expand Up @@ -644,7 +646,7 @@ def test_upload_from_string_w_bytes(self):
blob = self._makeOne(BLOB_NAME, bucket=bucket)
blob._CHUNK_SIZE_MULTIPLE = 1
blob.chunk_size = 5
blob.upload_from_string(DATA)
blob.upload_from_string(DATA, connection=connection)
rq = connection.http._requested
self.assertEqual(len(rq), 1)
self.assertEqual(rq[0]['method'], 'POST')
Expand Down Expand Up @@ -683,7 +685,7 @@ def test_upload_from_string_w_text(self):
blob = self._makeOne(BLOB_NAME, bucket=bucket)
blob._CHUNK_SIZE_MULTIPLE = 1
blob.chunk_size = 5
blob.upload_from_string(DATA)
blob.upload_from_string(DATA, connection=connection)
rq = connection.http._requested
self.assertEqual(len(rq), 1)
self.assertEqual(rq[0]['method'], 'POST')
Expand Down

0 comments on commit a54b630

Please sign in to comment.