Skip to content

Commit

Permalink
Write mode option for Dropbox (#873)
Browse files Browse the repository at this point in the history
* added overwrite option

* added myself as AUTHOR

* Refactored to native feature implementation after comment from package owner

* Make write mode as external option, with default set to overwrite

* Fix order of imports

* added new options description

* fixed import sort issue

* removed redundand option, updated  documentation

* replaced _clean_name by _full_path

* update author change comment

* removed unused import posixpath

Co-authored-by: Taras Petriichuk <taraspetriichuk@TX-N-0432.local>
  • Loading branch information
petriichuk and Taras Petriichuk authored Apr 18, 2020
1 parent 138fce6 commit 42513d4
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 5 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ By order of apparition, thanks:
* Shaung Cheng (S3 docs)
* Andrew Perry (Bug fixes in SFTPStorage)
* Manuel Kaufmann (humitos)
* Taras Petriichuk (Dropbox write_mode option)
* Zoe Liao (S3 docs)


Expand Down
4 changes: 4 additions & 0 deletions docs/backends/dropbox.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,9 @@ To use DropBoxStorage set::
Timeout in seconds for making requests to the API. If ``None``, the client will wait forever.
The default is ``100`` seconds which is the current default in the official SDK.

``DROPBOX_WRITE_MODE`` (optional)
Allow to set Dropbox WriteMode strategy.
Default is ``add``. Read more at https://dropbox-sdk-python.readthedocs.io/en/latest/api/files.html#dropbox.files.CommitInfo.mode

.. _`tutorial`: https://www.dropbox.com/developers/documentation/python#tutorial
.. _`Dropbox SDK for Python`: https://www.dropbox.com/developers/documentation/python#tutorial
23 changes: 18 additions & 5 deletions storages/backends/dropbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@
from django.utils.deconstruct import deconstructible
from dropbox import Dropbox
from dropbox.exceptions import ApiError
from dropbox.files import CommitInfo, FolderMetadata, UploadSessionCursor
from dropbox.files import (
CommitInfo, FolderMetadata, UploadSessionCursor, WriteMode,
)

from storages.utils import setting
from storages.utils import get_available_overwrite_name, setting

_DEFAULT_TIMEOUT = 100
_DEFAULT_MODE = 'add'


class DropBoxStorageException(Exception):
Expand Down Expand Up @@ -69,15 +72,18 @@ class DropBoxStorage(Storage):
location = setting('DROPBOX_ROOT_PATH', '/')
oauth2_access_token = setting('DROPBOX_OAUTH2_TOKEN')
timeout = setting('DROPBOX_TIMEOUT', _DEFAULT_TIMEOUT)
write_mode = setting('DROPBOX_WRITE_MODE', _DEFAULT_MODE)

CHUNK_SIZE = 4 * 1024 * 1024

def __init__(self, oauth2_access_token=oauth2_access_token, root_path=location, timeout=timeout):
def __init__(self, oauth2_access_token=oauth2_access_token, root_path=location, timeout=timeout,
write_mode=write_mode):
if oauth2_access_token is None:
raise ImproperlyConfigured("You must configure an auth token at"
"'settings.DROPBOX_OAUTH2_TOKEN'.")

self.root_path = root_path
self.write_mode = write_mode
self.client = Dropbox(oauth2_access_token, timeout=timeout)

def _full_path(self, name):
Expand Down Expand Up @@ -132,7 +138,7 @@ def _open(self, name, mode='rb'):
def _save(self, name, content):
content.open()
if content.size <= self.CHUNK_SIZE:
self.client.files_upload(content.read(), self._full_path(name))
self.client.files_upload(content.read(), self._full_path(name), mode=WriteMode(self.write_mode))
else:
self._chunked_upload(content, self._full_path(name))
content.close()
Expand All @@ -146,7 +152,7 @@ def _chunked_upload(self, content, dest_path):
session_id=upload_session.session_id,
offset=content.tell()
)
commit = CommitInfo(path=dest_path)
commit = CommitInfo(path=dest_path, mode=WriteMode(self.write_mode))

while content.tell() < content.size:
if (content.size - content.tell()) <= self.CHUNK_SIZE:
Expand All @@ -158,3 +164,10 @@ def _chunked_upload(self, content, dest_path):
content.read(self.CHUNK_SIZE), cursor
)
cursor.offset = content.tell()

def get_available_name(self, name, max_length=None):
"""Overwrite existing file with the same name."""
name = self._full_path(name)
if self.write_mode == 'overwrite':
return get_available_overwrite_name(name, max_length)
return super(DropBoxStorage, self).get_available_name(name, max_length)

0 comments on commit 42513d4

Please sign in to comment.