Repository: google/google-api-python-client
Pull request #377 (2017-03-31 13:10:35)

ZeroDivisionError when calling 'MediaDownloadProgress.progress'
Applies also for `MediaUploadProgress`.

Resolves: #369


Patch:
diff --git a/googleapiclient/http.py b/googleapiclient/http.py
index 4330f26e7..302e0e70e 100644
--- a/googleapiclient/http.py
+++ b/googleapiclient/http.py
@@ -203,7 +203,7 @@ class MediaUploadProgress(object):
       the percentage complete as a float, returning 0.0 if the total size of
       the upload is unknown.
     """
-    if self.total_size is not None:
+    if self.total_size is not None and self.total_size != 0:
       return float(self.resumable_progress) / float(self.total_size)
     else:
       return 0.0
@@ -229,7 +229,7 @@ class MediaDownloadProgress(object):
       the percentage complete as a float, returning 0.0 if the total size of
       the download is unknown.
     """
-    if self.total_size is not None:
+    if self.total_size is not None and self.total_size != 0:
       return float(self.resumable_progress) / float(self.total_size)
     else:
       return 0.0


Test patch:
diff --git a/tests/test_discovery.py b/tests/test_discovery.py
index 8818f4a30..fd1b9ae93 100644
--- a/tests/test_discovery.py
+++ b/tests/test_discovery.py
@@ -1389,6 +1389,30 @@ class Discovery(unittest.TestCase):
     new_http = new_zoo._http
     self.assertFalse(hasattr(new_http.request, 'credentials'))
 
+  def test_resumable_media_upload_no_content(self):
+    self.http = HttpMock(datafile('zoo.json'), {'status': '200'})
+    zoo = build('zoo', 'v1', http=self.http)
+
+    media_upload = MediaFileUpload(datafile('empty'), resumable=True)
+    request = zoo.animals().insert(media_body=media_upload, body=None)
+
+    self.assertEquals(media_upload, request.resumable)
+    self.assertEquals(request.body, None)
+    self.assertEquals(request.resumable_uri, None)
+
+    http = HttpMockSequence([
+      ({'status': '200',
+        'location': 'http://upload.example.com'}, ''),
+      ({'status': '308',
+        'location': 'http://upload.example.com/2',
+        'range': '0-0'}, ''),
+    ])
+
+    status, body = request.next_chunk(http=http)
+    self.assertEquals(None, body)
+    self.assertTrue(isinstance(status, MediaUploadProgress))
+    self.assertEquals(0, status.progress())
+
 
 class Next(unittest.TestCase):
 
diff --git a/tests/test_http.py b/tests/test_http.py
index 512e8e17b..fe7467263 100644
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -550,6 +550,28 @@ class TestMediaIoBaseDownload(unittest.TestCase):
     self.assertEqual(5, download._progress)
     self.assertEqual(5, download._total_size)
 
+  def test_media_io_base_download_empty_file(self):
+    self.request.http = HttpMockSequence([
+      ({'status': '200',
+        'content-range': '0-0/0'}, b''),
+    ])
+
+    download = MediaIoBaseDownload(
+      fd=self.fd, request=self.request, chunksize=3)
+
+    self.assertEqual(self.fd, download._fd)
+    self.assertEqual(0, download._progress)
+    self.assertEqual(None, download._total_size)
+    self.assertEqual(False, download._done)
+    self.assertEqual(self.request.uri, download._uri)
+
+    status, done = download.next_chunk()
+
+    self.assertEqual(True, done)
+    self.assertEqual(0, download._progress)
+    self.assertEqual(0, download._total_size)
+    self.assertEqual(0, status.progress())
+
 EXPECTED = """POST /someapi/v1/collection/?foo=bar HTTP/1.1
 Content-Type: application/json
 MIME-Version: 1.0