diff --git a/.gitignore b/.gitignore index 4d8f39b..994aaf8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ *.pyc *.eggs/ *.egg-info +.idea mezzanine-git/ diff --git a/filebrowser_safe/base.py b/filebrowser_safe/base.py index 6955f91..7c2a0ac 100644 --- a/filebrowser_safe/base.py +++ b/filebrowser_safe/base.py @@ -23,7 +23,8 @@ class FileObjectAPI(object): """ A mixin class providing file properties. """ - def __init__(self, path): + def __init__(self, path, is_folder=None): + self._is_folder = is_folder self.head = os.path.dirname(path) self.filename = os.path.basename(path) self.filename_lower = self.filename.lower() @@ -94,6 +95,8 @@ def folder(self): @cached_property def is_folder(self): + if self._is_folder is not None: + return self._is_folder return default_storage.isdir(self.path) @property @@ -121,9 +124,9 @@ class FileObject(FileObjectAPI): where path is a relative path to a storage location. """ - def __init__(self, path): + def __init__(self, path, *args, **kwargs): self.path = path - super(FileObject, self).__init__(path) + super(FileObject, self).__init__(path, *args, **kwargs) @property def name(self): diff --git a/filebrowser_safe/locale/cs/LC_MESSAGES/django.po b/filebrowser_safe/locale/cs/LC_MESSAGES/django.po index ca8b3fc..fb66196 100644 --- a/filebrowser_safe/locale/cs/LC_MESSAGES/django.po +++ b/filebrowser_safe/locale/cs/LC_MESSAGES/django.po @@ -322,7 +322,7 @@ msgstr[1] "%(counter) výsledky" #: templates/filebrowser/include/toolbar.html:9 #, python-format msgid "%(full_result_count)s total" -msgstr "%(full_result_count) celkem" +msgstr "%(full_result_count)s celkem" #: templates/filebrowser/include/search.html:5 msgid "Clear Restrictions" diff --git a/filebrowser_safe/storage.py b/filebrowser_safe/storage.py index 8a312c2..aa5b790 100644 --- a/filebrowser_safe/storage.py +++ b/filebrowser_safe/storage.py @@ -4,6 +4,7 @@ # PYTHON IMPORTS import os import shutil +import posixpath # DJANGO IMPORTS from django.core.files.move import file_move_safe @@ -112,9 +113,13 @@ def makedirs(self, name): def rmtree(self, name): name = self._normalize_name(self._clean_name(name)) - dirlist = self.listdir(self._encode_name(name)) - for item in dirlist: - item.delete() + directories, files = self.listdir(self._encode_name(name)) + + for key in files: + self.delete('/'.join([name, key])) + + for dirname in directories: + self.rmtree('/'.join([name, dirname])) class GoogleStorageMixin(StorageMixin): @@ -133,7 +138,7 @@ def isdir(self, name): return False name = self._normalize_name(self._clean_name(name)) - dirlist = self.bucket.list(self._encode_name(name)) + dirlist = self.listdir(self._encode_name(name)) # Check whether the iterator is empty for item in dirlist: @@ -163,6 +168,32 @@ def makedirs(self, name): def rmtree(self, name): name = self._normalize_name(self._clean_name(name)) - dirlist = self.bucket.list(self._encode_name(name)) + dirlist = self.listdir(self._encode_name(name)) for item in dirlist: item.delete() + + def _clean_name(self, name): + """ + Cleans the name so that Windows style paths work + """ + return clean_name(name) + + +def clean_name(name): + """ + Cleans the name so that Windows style paths work + """ + # Normalize Windows style paths + clean_name = posixpath.normpath(name).replace('\\', '/') + + # os.path.normpath() can strip trailing slashes so we implement + # a workaround here. + if name.endswith('/') and not clean_name.endswith('/'): + # Add a trailing slash as it was stripped. + clean_name = clean_name + '/' + + # Given an empty string, os.path.normpath() will return ., which we don't want + if clean_name == '.': + clean_name = '' + + return clean_name diff --git a/filebrowser_safe/views.py b/filebrowser_safe/views.py index 69bf1d1..2c595a4 100644 --- a/filebrowser_safe/views.py +++ b/filebrowser_safe/views.py @@ -122,7 +122,7 @@ def browse(request): # CREATE FILEOBJECT url_path = "/".join([s.strip("/") for s in [get_directory(), path.replace("\\", "/"), file] if s.strip("/")]) - fileobject = FileObject(url_path) + fileobject = FileObject(url_path, is_folder=file in dir_list) # FILTER / SEARCH