Skip to content

Commit 4406778

Browse files
danielxJon Wayne Parrott
authored andcommitted
Handle unknown media length (#406)
Some media download APIs does not support partial downloads and do not return a 'Content-length' or 'Content-range' header and is therefore never considered done. This change is to consider responses where the media length is unknown to be done. This commit could potentially break media downloads where the API supports partial download and only returns a 'Content-length' header when the entire file has been served/read. This commit fixes issue #15
1 parent 90ffb85 commit 4406778

File tree

4 files changed

+30
-7
lines changed

4 files changed

+30
-7
lines changed

docs/epy/googleapiclient.http-pysrc.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@ <h1 class="epydoc">Source Code for <a href="googleapiclient.http-module.html">Mo
844844
<a name="L655"></a><tt class="py-lineno"> 655</tt> <tt class="py-line"><tt class="py-docstring"> Returns:</tt> </tt>
845845
<a name="L656"></a><tt class="py-lineno"> 656</tt> <tt class="py-line"><tt class="py-docstring"> (status, done): (MediaDownloadStatus, boolean)</tt> </tt>
846846
<a name="L657"></a><tt class="py-lineno"> 657</tt> <tt class="py-line"><tt class="py-docstring"> The value of 'done' will be True when the media has been fully</tt> </tt>
847-
<a name="L658"></a><tt class="py-lineno"> 658</tt> <tt class="py-line"><tt class="py-docstring"> downloaded.</tt> </tt>
847+
<a name="L658"></a><tt class="py-lineno"> 658</tt> <tt class="py-line"><tt class="py-docstring"> downloaded or the total size of the media is unknown.</tt> </tt>
848848
<a name="L659"></a><tt class="py-lineno"> 659</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
849849
<a name="L660"></a><tt class="py-lineno"> 660</tt> <tt class="py-line"><tt class="py-docstring"> Raises:</tt> </tt>
850850
<a name="L661"></a><tt class="py-lineno"> 661</tt> <tt class="py-line"><tt class="py-docstring"> googleapiclient.errors.HttpError if the response was not a 2xx.</tt> </tt>
@@ -873,7 +873,7 @@ <h1 class="epydoc">Source Code for <a href="googleapiclient.http-module.html">Mo
873873
<a name="L684"></a><tt class="py-lineno"> 684</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-string">'content-length'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">resp</tt><tt class="py-op">:</tt> </tt>
874874
<a name="L685"></a><tt class="py-lineno"> 685</tt> <tt class="py-line"> <tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_total_size</tt> <tt class="py-op">=</tt> <tt class="py-name">int</tt><tt class="py-op">(</tt><tt class="py-name">resp</tt><tt class="py-op">[</tt><tt class="py-string">'content-length'</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> </tt>
875875
<a name="L686"></a><tt class="py-lineno"> 686</tt> <tt class="py-line"> </tt>
876-
<a name="L687"></a><tt class="py-lineno"> 687</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_progress</tt> <tt class="py-op">==</tt> <tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_total_size</tt><tt class="py-op">:</tt> </tt>
876+
<a name="L687"></a><tt class="py-lineno"> 687</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_total_size</tt> <tt class="py-keyword">is</tt> <tt class="py-name">None</tt> <tt class="py-keyword">or</tt> <tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_progress</tt> <tt class="py-op">==</tt> <tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_total_size</tt><tt class="py-op">:</tt> </tt>
877877
<a name="L688"></a><tt class="py-lineno"> 688</tt> <tt class="py-line"> <tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_done</tt> <tt class="py-op">=</tt> <tt class="py-name">True</tt> </tt>
878878
<a name="L689"></a><tt class="py-lineno"> 689</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt id="link-86" class="py-name" targets="Class googleapiclient.http.MediaDownloadProgress=googleapiclient.http.MediaDownloadProgress-class.html"><a title="googleapiclient.http.MediaDownloadProgress" class="py-name" href="#" onclick="return doclink('link-86', 'MediaDownloadProgress', 'link-86');">MediaDownloadProgress</a></tt><tt class="py-op">(</tt><tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_progress</tt><tt class="py-op">,</tt> <tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_total_size</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> <tt class="py-name">self</tt><tt class="py-op">.</tt><tt class="py-name">_done</tt> </tt>
879879
<a name="L690"></a><tt class="py-lineno"> 690</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
@@ -2189,7 +2189,7 @@ <h1 class="epydoc">Source Code for <a href="googleapiclient.http-module.html">Mo
21892189
<table border="0" cellpadding="0" cellspacing="0" width="100%%">
21902190
<tr>
21912191
<td align="left" class="footer">
2192-
Generated by Epydoc 3.0.1 on Mon Jun 5 13:38:40 2017
2192+
Generated by Epydoc 3.0.1 on Wed Jun 14 20:18:21 2017
21932193
</td>
21942194
<td align="right" class="footer">
21952195
<a target="mainFrame" href="http://epydoc.sourceforge.net"

docs/epy/googleapiclient.http.MediaIoBaseDownload-class.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ <h3 class="epydoc"><span class="sig"><span class="sig-name">next_chunk</span>(<s
266266
Returns:
267267
(status, done): (MediaDownloadStatus, boolean)
268268
The value of 'done' will be True when the media has been fully
269-
downloaded.
269+
downloaded or the total size of the media is unknown.
270270

271271
Raises:
272272
googleapiclient.errors.HttpError if the response was not a 2xx.
@@ -308,7 +308,7 @@ <h3 class="epydoc"><span class="sig"><span class="sig-name">next_chunk</span>(<s
308308
<table border="0" cellpadding="0" cellspacing="0" width="100%%">
309309
<tr>
310310
<td align="left" class="footer">
311-
Generated by Epydoc 3.0.1 on Mon Jun 5 13:38:40 2017
311+
Generated by Epydoc 3.0.1 on Wed Jun 14 20:18:20 2017
312312
</td>
313313
<td align="right" class="footer">
314314
<a target="mainFrame" href="http://epydoc.sourceforge.net"

googleapiclient/http.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ def next_chunk(self, num_retries=0):
658658
Returns:
659659
(status, done): (MediaDownloadProgress, boolean)
660660
The value of 'done' will be True when the media has been fully
661-
downloaded.
661+
downloaded or the total size of the media is unknown.
662662
663663
Raises:
664664
googleapiclient.errors.HttpError if the response was not a 2xx.
@@ -687,7 +687,7 @@ def next_chunk(self, num_retries=0):
687687
elif 'content-length' in resp:
688688
self._total_size = int(resp['content-length'])
689689

690-
if self._progress == self._total_size:
690+
if self._total_size is None or self._progress == self._total_size:
691691
self._done = True
692692
return MediaDownloadProgress(self._progress, self._total_size), self._done
693693
else:

tests/test_http.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,29 @@ def test_media_io_base_download_empty_file(self):
576576
self.assertEqual(0, download._total_size)
577577
self.assertEqual(0, status.progress())
578578

579+
def test_media_io_base_download_unknown_media_size(self):
580+
self.request.http = HttpMockSequence([
581+
({'status': '200'}, b'123')
582+
])
583+
584+
download = MediaIoBaseDownload(
585+
fd=self.fd, request=self.request, chunksize=3)
586+
587+
self.assertEqual(self.fd, download._fd)
588+
self.assertEqual(0, download._progress)
589+
self.assertEqual(None, download._total_size)
590+
self.assertEqual(False, download._done)
591+
self.assertEqual(self.request.uri, download._uri)
592+
593+
status, done = download.next_chunk()
594+
595+
self.assertEqual(self.fd.getvalue(), b'123')
596+
self.assertEqual(True, done)
597+
self.assertEqual(3, download._progress)
598+
self.assertEqual(None, download._total_size)
599+
self.assertEqual(0, status.progress())
600+
601+
579602
EXPECTED = """POST /someapi/v1/collection/?foo=bar HTTP/1.1
580603
Content-Type: application/json
581604
MIME-Version: 1.0

0 commit comments

Comments
 (0)