diff --git a/gcloud/storage/blob.py b/gcloud/storage/blob.py index 5190528115bb..a5e1201ee353 100644 --- a/gcloud/storage/blob.py +++ b/gcloud/storage/blob.py @@ -370,7 +370,8 @@ def upload_from_file(self, file_obj, rewind=False, size=None, :type size: int :param size: The number of bytes to read from the file handle. If not provided, we'll try to guess the size using - :func:`os.fstat` + :func:`os.fstat`. (If the file handle is not from the + filesystem this won't be possible.) :type content_type: string or ``NoneType`` :param content_type: Optional type of content being uploaded. @@ -382,6 +383,9 @@ def upload_from_file(self, file_obj, rewind=False, size=None, ``NoneType`` :param connection: Optional. The connection to use when sending requests. If not provided, falls back to default. + + :raises: :class:`ValueError` if size is not passed in and can not be + determined """ connection = _require_connection(connection) content_type = (content_type or self._properties.get('contentType') or @@ -392,7 +396,13 @@ def upload_from_file(self, file_obj, rewind=False, size=None, file_obj.seek(0, os.SEEK_SET) # Get the basic stats about the file. - total_bytes = size or os.fstat(file_obj.fileno()).st_size + total_bytes = size + if total_bytes is None: + if hasattr(file_obj, 'fileno'): + total_bytes = os.fstat(file_obj.fileno()).st_size + else: + raise ValueError('total bytes could not be determined. Please ' + 'pass an explicit size.') headers = { 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', diff --git a/gcloud/storage/test_blob.py b/gcloud/storage/test_blob.py index 71b508870b4c..6203fb4be4b4 100644 --- a/gcloud/storage/test_blob.py +++ b/gcloud/storage/test_blob.py @@ -410,6 +410,16 @@ def test_download_as_string(self): fetched = blob.download_as_string(connection=connection) self.assertEqual(fetched, b'abcdef') + def test_upload_from_file_size_failure(self): + BLOB_NAME = 'blob-name' + bucket = _Bucket() + blob = self._makeOne(BLOB_NAME, bucket=bucket) + file_obj = object() + connection = _Connection() + with self.assertRaises(ValueError): + blob.upload_from_file(file_obj, size=None, + connection=connection) + def _upload_from_file_simple_test_helper(self, properties=None, content_type_arg=None, expected_content_type=None):