177 lines
5.4 KiB
Python
177 lines
5.4 KiB
Python
# coding: utf-8
|
|
|
|
import os
|
|
import shutil
|
|
|
|
from django.core.files.move import file_move_safe
|
|
from django.utils.encoding import smart_str
|
|
|
|
from filebrowser.base import FileObject
|
|
from filebrowser.settings import DEFAULT_PERMISSIONS
|
|
|
|
|
|
class StorageMixin(object):
|
|
"""
|
|
Adds some useful methods to the Storage class.
|
|
"""
|
|
|
|
def isdir(self, name):
|
|
"""
|
|
Returns true if name exists and is a directory.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def isfile(self, name):
|
|
"""
|
|
Returns true if name exists and is a regular file.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def move(self, old_file_name, new_file_name, allow_overwrite=False):
|
|
"""
|
|
Moves safely a file from one location to another.
|
|
|
|
If allow_ovewrite==False and new_file_name exists, raises an exception.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def makedirs(self, name):
|
|
"""
|
|
Creates all missing directories specified by name. Analogue to os.mkdirs().
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def rmtree(self, name):
|
|
"""
|
|
Deletes a directory and everything it contains. Analogue to shutil.rmtree().
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def setpermission(self, name):
|
|
"""
|
|
Sets file permission
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
|
|
class FileSystemStorageMixin(StorageMixin):
|
|
|
|
def isdir(self, name):
|
|
return os.path.isdir(self.path(name))
|
|
|
|
def isfile(self, name):
|
|
return os.path.isfile(self.path(name))
|
|
|
|
def move(self, old_file_name, new_file_name, allow_overwrite=False):
|
|
file_move_safe(self.path(old_file_name), self.path(new_file_name), allow_overwrite=True)
|
|
|
|
def makedirs(self, name):
|
|
os.makedirs(self.path(name))
|
|
|
|
def rmtree(self, name):
|
|
shutil.rmtree(self.path(name))
|
|
|
|
def setpermission(self, name):
|
|
full_path = FileObject(smart_str(name), site=self).path_full
|
|
os.chmod(full_path, DEFAULT_PERMISSIONS)
|
|
|
|
|
|
class S3BotoStorageMixin(StorageMixin):
|
|
|
|
def isfile(self, name):
|
|
return self.exists(name)
|
|
|
|
def isdir(self, name):
|
|
# That's some inefficient implementation...
|
|
# If there are some files having 'name' as their prefix, then
|
|
# the name is considered to be a directory
|
|
if not name: # Empty name is a directory
|
|
return True
|
|
|
|
if self.isfile(name):
|
|
return False
|
|
|
|
name = self._normalize_name(self._clean_name(name))
|
|
dirlist = self.bucket.list(self._encode_name(name))
|
|
|
|
# Check whether the iterator is empty
|
|
for item in dirlist:
|
|
return True
|
|
return False
|
|
|
|
def move(self, old_file_name, new_file_name, allow_overwrite=False):
|
|
|
|
if self.exists(new_file_name):
|
|
if allow_overwrite:
|
|
self.delete(new_file_name)
|
|
else:
|
|
raise "The destination file '%s' exists and allow_overwrite is False" % new_file_name
|
|
|
|
old_key_name = self._encode_name(self._normalize_name(self._clean_name(old_file_name)))
|
|
new_key_name = self._encode_name(self._normalize_name(self._clean_name(new_file_name)))
|
|
|
|
k = self.bucket.copy_key(new_key_name, self.bucket.name, old_key_name)
|
|
|
|
if not k:
|
|
raise "Couldn't copy '%s' to '%s'" % (old_file_name, new_file_name)
|
|
|
|
self.delete(old_file_name)
|
|
|
|
def makedirs(self, name):
|
|
pass
|
|
|
|
def rmtree(self, name):
|
|
name = self._normalize_name(self._clean_name(name))
|
|
dirlist = self.bucket.list(self._encode_name(name))
|
|
for item in dirlist:
|
|
item.delete()
|
|
|
|
def setpermission(self, name):
|
|
# Permissions for S3 uploads with django-storages
|
|
# is set in settings.py with AWS_DEFAULT_ACL.
|
|
# More info: http://django-common-configs.readthedocs.org/en/latest/configs/storage.html
|
|
pass
|
|
|
|
|
|
class DropBoxStorageMixin(StorageMixin):
|
|
|
|
def isdir(self, name):
|
|
# NOTE: We are importing inside the function to not to require
|
|
# the dropbox library if DropBoxStorageMixin is not used
|
|
# This could changed if storage module is broken down
|
|
# into one module for each storage Mixin?
|
|
from dropbox.exceptions import ApiError
|
|
from dropbox.files import FileMetadata, FolderMetadata
|
|
try:
|
|
metadata = self.client.files_get_metadata(self._full_path(name))
|
|
return isinstance(metadata, FolderMetadata)
|
|
except ApiError:
|
|
return False
|
|
|
|
def isfile(self, name):
|
|
from dropbox.exceptions import ApiError
|
|
from dropbox.files import FileMetadata, FolderMetadata
|
|
try:
|
|
metadata = self.client.files_get_metadata(self._full_path(name))
|
|
return isinstance(metadata, FileMetadata)
|
|
except ApiError:
|
|
return False
|
|
|
|
def move(self, old_file_name, new_file_name, allow_overwrite=False):
|
|
if self.exists(new_file_name):
|
|
if allow_overwrite:
|
|
self.delete(new_file_name)
|
|
else:
|
|
raise "The destination file '%s' exists and allow_overwrite is False" % new_file_name
|
|
|
|
self.client.files_move(old_file_name, new_file_name)
|
|
|
|
def makedirs(self, name):
|
|
self.client.files_create_folder(self._full_path(name))
|
|
|
|
def rmtree(self, name):
|
|
self.client.files_delete(self._full_path(name))
|
|
|
|
def setpermission(self, name):
|
|
pass
|