Skip to content

Commit 84a0b7a

Browse files
authored
Merge pull request #48 from iterative/fix-empty-file
gdrive: download empty file
2 parents 18ec4cf + ba4e05a commit 84a0b7a

File tree

2 files changed

+66
-15
lines changed

2 files changed

+66
-15
lines changed

pydrive2/files.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import io
23
import mimetypes
34
import json
@@ -261,7 +262,9 @@ def SetContentString(self, content, encoding="utf-8"):
261262
:param content: content of the file in string.
262263
:type content: str
263264
"""
264-
self.content = io.BytesIO(content.encode(encoding))
265+
if content:
266+
self.content = io.BytesIO(content.encode(encoding))
267+
265268
if self.get("mimeType") is None:
266269
self["mimeType"] = "text/plain"
267270

@@ -275,7 +278,9 @@ def SetContentFile(self, filename):
275278
:param filename: name of the file to be uploaded.
276279
:type filename: str.
277280
"""
278-
self.content = open(filename, "rb")
281+
if os.path.getsize(filename):
282+
self.content = open(filename, "rb")
283+
279284
if self.get("title") is None:
280285
self["title"] = filename
281286
if self.get("mimeType") is None:
@@ -353,20 +358,32 @@ def download(fd, request):
353358
download(fd, files.get_media(fileId=file_id))
354359
except errors.HttpError as error:
355360
exc = ApiRequestError(error)
356-
if (
357-
exc.error["code"] != 403
358-
or exc.GetField("reason") != "fileNotDownloadable"
359-
):
361+
code = exc.error["code"]
362+
reason = exc.GetField("reason")
363+
if code == 403 and reason == "fileNotDownloadable":
364+
mimetype = mimetype or "text/plain"
365+
fd.seek(0) # just in case `download()` modified `fd`
366+
try:
367+
download(
368+
fd,
369+
files.export_media(
370+
fileId=file_id, mimeType=mimetype
371+
),
372+
)
373+
except errors.HttpError as error:
374+
raise ApiRequestError(error)
375+
elif code == 416 and reason == "requestedRangeNotSatisfiable":
376+
# NOTE: An empty file case. Wasting one API call to make
377+
# absolutely sure. See
378+
# https://github.com/iterative/dvc/issues/4507
379+
try:
380+
self.FetchMetadata(fields="fileSize")
381+
if int(self["fileSize"]) != 0:
382+
raise exc
383+
except errors.HttpError:
384+
raise exc
385+
else:
360386
raise exc
361-
mimetype = mimetype or "text/plain"
362-
fd.seek(0) # just in case `download()` modified `fd`
363-
try:
364-
download(
365-
fd,
366-
files.export_media(fileId=file_id, mimeType=mimetype),
367-
)
368-
except errors.HttpError as error:
369-
raise ApiRequestError(error)
370387

371388
if mimetype == "text/plain" and remove_bom:
372389
fd.seek(0)

pydrive2/test/test_file.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,40 @@ def test_11_Files_Get_Content_Buffer(self):
300300

301301
self.DeleteUploadedFiles(drive, [file1["id"]])
302302

303+
def test_12_Upload_Download_Empty_File(self):
304+
filename = os.path.join(self.tmpdir, str(time()))
305+
create_file(filename, "")
306+
307+
drive = GoogleDrive(self.ga)
308+
file1 = drive.CreateFile()
309+
file1.SetContentFile(filename)
310+
pydrive_retry(file1.Upload)
311+
312+
fileOut1 = self.getTempFile()
313+
pydrive_retry(file1.GetContentFile, fileOut1)
314+
self.assertEqual(os.path.getsize(fileOut1), 0)
315+
316+
self.DeleteUploadedFiles(drive, [file1["id"]])
317+
318+
def test_13_Upload_Download_Empty_String(self):
319+
drive = GoogleDrive(self.ga)
320+
file1 = drive.CreateFile()
321+
file1.SetContentString("")
322+
pydrive_retry(file1.Upload)
323+
324+
self.assertEqual(pydrive_retry(file1.GetContentString), "")
325+
326+
# Force download and double check content
327+
pydrive_retry(file1.FetchContent)
328+
self.assertEqual(file1.GetContentString(), "")
329+
330+
# Download file from id
331+
file2 = drive.CreateFile({"id": file1["id"]})
332+
pydrive_retry(file2.FetchContent)
333+
self.assertEqual(file2.GetContentString(), "")
334+
335+
self.DeleteUploadedFiles(drive, [file1["id"]])
336+
303337
# Tests for Trash/UnTrash/Delete.
304338
# ===============================
305339

0 commit comments

Comments
 (0)