Skip to content

Commit fb12d27

Browse files
author
rllin
authored
[BACKEND-829] fix content length (#30)
* package data for upload properly to fix content length being incorrect for file uploads * basename -> filename * yapf * fix mypy * yapf * test coverage for video uploads * test video * clear parens
1 parent 0937d0e commit fb12d27

File tree

4 files changed

+50
-8
lines changed

4 files changed

+50
-8
lines changed

labelbox/client.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import logging
44
import mimetypes
55
import os
6+
from typing import Tuple
67

78
import requests
89
import requests.exceptions
@@ -176,7 +177,7 @@ def check_errors(keywords, *path):
176177

177178
return response["data"]
178179

179-
def upload_file(self, path):
180+
def upload_file(self, path: str) -> str:
180181
"""Uploads given path to local file.
181182
182183
Also includes best guess at the content type of the file.
@@ -190,26 +191,36 @@ def upload_file(self, path):
190191
191192
"""
192193
content_type, _ = mimetypes.guess_type(path)
193-
basename = os.path.basename(path)
194+
filename = os.path.basename(path)
194195
with open(path, "rb") as f:
195-
return self.upload_data(data=(basename, f.read(), content_type))
196-
197-
def upload_data(self, data):
196+
return self.upload_data(content=f.read(),
197+
filename=filename,
198+
content_type=content_type)
199+
200+
def upload_data(self,
201+
content: bytes,
202+
filename: str = None,
203+
content_type: str = None) -> str:
198204
""" Uploads the given data (bytes) to Labelbox.
199205
200206
Args:
201-
data (bytes): The data to upload.
207+
content: bytestring to upload
208+
filename: name of the upload
209+
content_type: content type of data uploaded
210+
202211
Returns:
203212
str, the URL of uploaded data.
213+
204214
Raises:
205215
labelbox.exceptions.LabelboxError: If upload failed.
206216
"""
217+
207218
request_data = {
208219
"operations":
209220
json.dumps({
210221
"variables": {
211222
"file": None,
212-
"contentLength": len(data),
223+
"contentLength": len(content),
213224
"sign": False
214225
},
215226
"query":
@@ -224,7 +235,10 @@ def upload_data(self, data):
224235
self.endpoint,
225236
headers={"authorization": "Bearer %s" % self.api_key},
226237
data=request_data,
227-
files={"1": data})
238+
files={
239+
"1": (filename, content, content_type) if
240+
(filename and content_type) else content
241+
})
228242

229243
try:
230244
file_data = response.json().get("data", None)

tests/integration/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,10 @@ def iframe_url(environ) -> str:
108108
Environ.PROD: 'https://editor.labelbox.com',
109109
Environ.STAGING: 'https://staging-editor.labelbox.com',
110110
}[environ]
111+
112+
113+
@pytest.fixture
114+
def sample_video() -> str:
115+
path_to_video = 'tests/integration/media/cat.mp4'
116+
assert os.path.exists(path_to_video)
117+
return path_to_video

tests/integration/media/cat.mp4

71.9 KB
Binary file not shown.

tests/integration/test_dataset.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pytest
2+
import requests
23

34
from labelbox import Dataset
45
from labelbox.exceptions import ResourceNotFoundError
@@ -78,3 +79,23 @@ def test_get_data_row_for_external_id(dataset, rand_gen):
7879

7980
with pytest.raises(ResourceNotFoundError):
8081
data_row = dataset.data_row_for_external_id(external_id)
82+
83+
84+
def test_upload_video_file(dataset, sample_video: str) -> None:
85+
"""
86+
Tests that a mp4 video can be uploaded and preserve content length
87+
and content type.
88+
89+
"""
90+
dataset.create_data_row(row_data=sample_video)
91+
task = dataset.create_data_rows([sample_video, sample_video])
92+
task.wait_till_done()
93+
94+
with open(sample_video, 'rb') as video_f:
95+
content_length = len(video_f.read())
96+
97+
for data_row in dataset.data_rows():
98+
url = data_row.row_data
99+
response = requests.head(url, allow_redirects=True)
100+
assert int(response.headers['Content-Length']) == content_length
101+
assert response.headers['Content-Type'] == 'video/mp4'

0 commit comments

Comments
 (0)