Skip to content

Commit e7ebb14

Browse files
committed
Breaking change: file upload argument must be a bytes type.
- File-like objs are no longer accepted. - Updated to latest Stone.
1 parent 56f2f33 commit e7ebb14

File tree

5 files changed

+43
-10
lines changed

5 files changed

+43
-10
lines changed

dropbox/base.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def files_alpha_upload(self,
9292
larger than 150 MB. Instead, create an upload session with
9393
:meth:`files_upload_session_start`.
9494
95-
:param f: A string or file-like obj of data.
95+
:param bytes f: Contents to upload.
9696
:param Nullable property_groups: List of custom properties to add to
9797
file.
9898
:rtype: :class:`dropbox.files.FileMetadata`
@@ -1190,7 +1190,7 @@ def files_upload(self,
11901190
this to upload a file larger than 150 MB. Instead, create an upload
11911191
session with :meth:`files_upload_session_start`.
11921192
1193-
:param f: A string or file-like obj of data.
1193+
:param bytes f: Contents to upload.
11941194
:param str path: Path in the user's Dropbox to save the file.
11951195
:param mode: Selects what to do if the file already exists.
11961196
:type mode: :class:`dropbox.files.WriteMode`
@@ -1234,7 +1234,7 @@ def files_upload_session_append(self,
12341234
Append more data to an upload session. A single request should not
12351235
upload more than 150 MB of file contents.
12361236
1237-
:param f: A string or file-like obj of data.
1237+
:param bytes f: Contents to upload.
12381238
:param str session_id: The upload session ID (returned by
12391239
:meth:`files_upload_session_start`).
12401240
:param long offset: The amount of data that has been uploaded so far. We
@@ -1269,7 +1269,7 @@ def files_upload_session_append_v2(self,
12691269
this call will close the session. A single request should not upload
12701270
more than 150 MB of file contents.
12711271
1272-
:param f: A string or file-like obj of data.
1272+
:param bytes f: Contents to upload.
12731273
:param cursor: Contains the upload session ID and the offset.
12741274
:type cursor: :class:`dropbox.files.UploadSessionCursor`
12751275
:param bool close: If true, the current session will be closed, at which
@@ -1301,7 +1301,7 @@ def files_upload_session_finish(self,
13011301
path. A single request should not upload more than 150 MB of file
13021302
contents.
13031303
1304-
:param f: A string or file-like obj of data.
1304+
:param bytes f: Contents to upload.
13051305
:param cursor: Contains the upload session ID and the offset.
13061306
:type cursor: :class:`dropbox.files.UploadSessionCursor`
13071307
:param commit: Contains the path and other optional modifiers for the
@@ -1390,7 +1390,7 @@ def files_upload_session_start(self,
13901390
Dropbox. A single request should not upload more than 150 MB of file
13911391
contents.
13921392
1393-
:param f: A string or file-like obj of data.
1393+
:param bytes f: Contents to upload.
13941394
:param bool close: If true, the current session will be closed, at which
13951395
point you won't be able to call
13961396
:meth:`files_upload_session_append_v2` anymore with the current

dropbox/dropbox.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ def request_json_object(self,
291291
:param route_style: The style of the route.
292292
:param str request_arg: A JSON-serializable Python object representing
293293
the argument for the route.
294-
:param request_binary: String or file pointer representing the binary
294+
:param Optional[bytes] request_binary: Bytes representing the binary
295295
payload. Use None if there is no binary payload.
296296
:param Optional[float] timeout: Maximum duration in seconds
297297
that client will wait for any single packet from the
@@ -376,6 +376,14 @@ def request_json_string(self,
376376
if host not in self._host_map:
377377
raise ValueError('Unknown value for host: %r' % host)
378378

379+
if not isinstance(request_binary, (six.binary_type, type(None))):
380+
# Disallow streams and file-like objects even though the underlying
381+
# requests library supports them. This is to prevent incorrect
382+
# behavior when a non-rewindable stream is read from, but the
383+
# request fails and needs to be re-tried at a later time.
384+
raise TypeError('expected request_binary as binary type, got %s' %
385+
type(request_binary))
386+
379387
# Fully qualified hostname
380388
fq_hostname = self._host_map[host]
381389
url = self._get_route_url(fq_hostname, func_name)

dropbox/stone_base.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,20 @@ def __init__(self, tag, value=None):
3434
self._tag = tag
3535
self._value = value
3636

37+
def __eq__(self, other):
38+
# Also need to check if one class is a subclass of another. If one union extends another,
39+
# the common fields should be able to be compared to each other.
40+
return (
41+
isinstance(other, Union) and
42+
(isinstance(self, other.__class__) or isinstance(other, self.__class__)) and
43+
self._tag == other._tag and self._value == other._value
44+
)
45+
46+
def __ne__(self, other):
47+
return not self == other
48+
49+
def __hash__(self):
50+
return hash((self._tag, self._value))
3751

3852
class Route(object):
3953

test/test_dropbox.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
import sys
88
import unittest
99

10+
try:
11+
from StringIO import StringIO as BytesIO
12+
except ImportError:
13+
from io import BytesIO
14+
1015
from dropbox import (
1116
Dropbox,
1217
DropboxTeam,
@@ -45,6 +50,8 @@ def inner(*args, **kwargs):
4550
MALFORMED_TOKEN = 'asdf'
4651
INVALID_TOKEN = 'z' * 62
4752

53+
# Need bytes type for Python3
54+
DUMMY_PAYLOAD = string.ascii_letters.encode('ascii')
4855

4956
class TestDropbox(unittest.TestCase):
5057

@@ -80,16 +87,20 @@ def test_upload_download(self):
8087
timestamp = str(datetime.datetime.utcnow())
8188
random_filename = ''.join(random.sample(string.ascii_letters, 15))
8289
random_path = '/Test/%s/%s' % (timestamp, random_filename)
83-
test_contents = string.ascii_letters
90+
test_contents = DUMMY_PAYLOAD
8491
self.dbx.files_upload(test_contents, random_path)
8592

8693
# Download file
8794
metadata, resp = self.dbx.files_download(random_path)
88-
self.assertEqual(string.ascii_letters, resp.text)
95+
self.assertEqual(DUMMY_PAYLOAD, resp.content)
8996

9097
# Cleanup folder
9198
self.dbx.files_delete('/Test/%s' % timestamp)
9299

100+
def test_bad_upload_types(self):
101+
with self.assertRaises(TypeError):
102+
self.dbx.files_upload(BytesIO(b'test'), '/Test')
103+
93104
@require_team_token
94105
def test_team(self, token):
95106
dbxt = DropboxTeam(token)

0 commit comments

Comments
 (0)