plone.resourceeditor/master: Fix all tests for the FileManagerAction class and add the do

Oshane Bailey <jenkins-z4DKO/[email protected]>
Newsgroups gmane.comp.web.zope.plone.cvs
Message-ID <[email protected]>
Repository: plone.resourceeditor
Branch: refs/heads/master
Date: 2017-07-06T17:34:59Z
Author: Oshane Bailey (b4oshany) <[email protected]>
Commit: https://github.com/plone/plone.resourceeditor/commit/31fc4aedf219e63c6e74c59575323cc5867d634f

Fix all tests for the FileManagerAction class and add the download endpoint to it.

Files changed:
M CHANGES.rst
M plone/resourceeditor/browser.py
M plone/resourceeditor/tests/test_file_manager_action.py

diff --git a/CHANGES.rst b/CHANGES.rst
index 7cfe5d7..80fedab 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -11,7 +11,7 @@ Incompatibilities:
 New:
 
 - *add item here*
-- Add the move API endpoint to the FileManagerActions class
+- Add the download and move endpoint to the FileManagerActions class
   [b4oshany]
 - Add test cases for FileManagerAction
   [b4oshany]
diff --git a/plone/resourceeditor/browser.py b/plone/resourceeditor/browser.py
index 4445ba6..3563cdb 100644
--- a/plone/resourceeditor/browser.py
+++ b/plone/resourceeditor/browser.py
@@ -69,6 +69,43 @@ def getExtension(self, obj=None, path=None):
         ext = ext[1:].lower()
         return ext
 
+    def getFolder(self, path):
+        """Returns a dict of file and folder objects representing the
+        contents of the given directory (indicated by a "path" parameter). The
+        values are dicts as returned by getInfo().
+
+        A boolean parameter "getsizes" indicates whether image dimensions
+        should be returned for each item. Folders should always be returned
+        before files.
+
+        Optionally a "type" parameter can be specified to restrict returned
+        files (depending on the connector). If a "type" parameter is given for
+        the HTML document, the same parameter value is reused and passed
+        to getFolder(). This can be used for example to only show image files
+        in a file system tree.
+        """
+
+        path = path.encode('utf-8')
+
+        folders = []
+        files = []
+
+        path = self.normalizePath(path)
+        folder = self.getObject(path)
+
+        for name in folder.listDirectory():
+            if IResourceDirectory.providedBy(folder[name]):
+                folders.append(self.getInfo(
+                    folder[name],
+                    path='/{0}/{1}/'.format(path, name)
+                ))
+            else:
+                files.append(self.getInfo(
+                    folder[name],
+                    path='/{0}/{1}'.format(path, name)
+                ))
+        return folders + files
+
     def getFile(self, path):
         path = self.normalizePath(path.encode('utf-8'))
         ext = self.getExtension(path=path)
@@ -124,7 +161,6 @@ def getInfo(self, obj, path='/'):
         indicates whether the dimensions of the file (if an image) should be
         returned.
         """
-
         filename = obj.__name__
 
         properties = {
@@ -137,7 +173,12 @@ def getInfo(self, obj, path='/'):
             properties['dateModified'] = DateTime(obj._p_mtime).strftime('%c')
             size = obj.get_size() / 1024
 
-        fileType = self.getExtension(obj)
+        if IResourceDirectory.providedBy(obj):
+            fileType = "dir"
+            is_folder = True
+        else:
+            fileType = self.getExtension(obj)
+            is_folder = False
         if isinstance(obj, FilesystemFile):
             stats = os.stat(obj.path)
             modified = localtime(stats.st_mtime)
@@ -166,7 +207,7 @@ def getInfo(self, obj, path='/'):
             'filesystem': isinstance(obj, FilesystemFile),
             'properties': properties,
             'path': path,
-            'folder': False
+            'folder': is_folder
         }
 
     def saveFile(self, path, value):
@@ -297,6 +338,7 @@ def addFile(self, path, name):
             'name': name,
             'error': error,
             'code': code,
+            'path': path
         })
 
     def delete(self, path):
@@ -402,11 +444,11 @@ def move(self, path, directory):
                               default=u'Parent folder not found.'),
                               context=self.request)
             code = 1
-            return {
+            return json.dumps({
                 'code': code,
                 'error': error,
                 'newPath': self.normalizeReturnPath(newCanonicalPath),
-            }
+            })
 
         try:
             target = self.getObject(newParentPath)
@@ -415,11 +457,11 @@ def move(self, path, directory):
                               default=u'Destination folder not found.'),
                               context=self.request)
             code = 1
-            return {
+            return json.dumps({
                 'code': code,
                 'error': error,
                 'newPath': self.normalizeReturnPath(newCanonicalPath),
-            }
+            })
 
         if filename not in parent:
             error = translate(_(u'filemanager_error_file_not_found',
@@ -436,11 +478,11 @@ def move(self, path, directory):
             del parent[filename]
             target[filename] = obj
 
-        return {
+        return json.dumps({
             'code': code,
             'error': error,
             'newPath': self.normalizeReturnPath(newCanonicalPath),
-        }
+        })
 
     def do_action(self, action):
         if action == 'dataTree':
@@ -500,6 +542,28 @@ def getDirectory(folder, relpath=''):
             des_path = self.request.get('destination', '')
             return self.move(src_path, des_path)
 
+    def download(self, path):
+        """Serve the requested file to the user
+        """
+
+        path = path.encode('utf-8')
+
+        npath = self.normalizePath(path)
+        parentPath = '/'.join(npath.split('/')[:-1])
+        name = npath.split('/')[-1]
+
+        parent = self.getObject(parentPath)
+
+        self.request.response.setHeader('Content-Type',
+                                        'application/octet-stream')
+        self.request.response.setHeader(
+            'Content-Disposition',
+            'attachment; filename="{0}"'.format(name)
+        )
+
+        # TODO: Use streams here if we can
+        return parent.readFile(name)
+
     def __call__(self):
         action = self.request.get('action')
         return self.do_action(action)
diff --git a/plone/resourceeditor/tests/test_file_manager_action.py b/plone/resourceeditor/tests/test_file_manager_action.py
index 4fac66c..3d5dfda 100644
--- a/plone/resourceeditor/tests/test_file_manager_action.py
+++ b/plone/resourceeditor/tests/test_file_manager_action.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 from plone.resourceeditor.testing import PLONE_RESOURCE_EDITOR_INTEGRATION_TESTING  # noqa
-
+import json
 import unittest
 
 
@@ -23,15 +23,13 @@ def test_getinfo(self):
         r = self._make_directory()
 
         r.writeFile('test.txt', 'A text file')
-
         view = FileManagerActions(r, self.layer['request'])
-        info = view.getInfo('/test.txt')
-
-        self.assertEqual(info['code'], 0)
-        self.assertEqual(info['error'], '')
+        info = view.getInfo(r["test.txt"])
+        
+        
         self.assertEqual(info['fileType'], 'txt')
         self.assertEqual(info['filename'], 'test.txt')
-        self.assertEqual(info['path'], '/test.txt')
+        self.assertEqual(info['path'], '/')
 
     def test_getfolder(self):
         from plone.resourceeditor.browser import FileManagerActions
@@ -46,15 +44,10 @@ def test_getfolder(self):
         info = view.getFolder('/alpha')
 
         self.assertEqual(len(info), 2)
-
-        self.assertEqual(info[0]['code'], 0)
-        self.assertEqual(info[0]['error'], '')
         self.assertEqual(info[0]['fileType'], 'dir')
         self.assertEqual(info[0]['filename'], 'delta')
-        self.assertEqual(info[0]['path'], '/alpha/delta')
+        self.assertEqual(info[0]['path'], '/alpha/delta/')
 
-        self.assertEqual(info[1]['code'], 0)
-        self.assertEqual(info[1]['error'], '')
         self.assertEqual(info[1]['fileType'], 'txt')
         self.assertEqual(info[1]['filename'], 'beta.txt')
         self.assertEqual(info[1]['path'], '/alpha/beta.txt')
@@ -65,14 +58,16 @@ def test_addfolder(self):
 
         view = FileManagerActions(r, self.layer['request'])
 
-        info = view.addFolder('/', 'alpha')
+        info_str = view.addFolder('/', 'alpha')
+        info = json.loads(info_str)
 
         self.assertEqual(info['code'], 0)
         self.assertEqual(info['error'], '')
         self.assertEqual(info['parent'], '/')
         self.assertEqual(info['name'], 'alpha')
 
-        info = view.addFolder('/alpha', 'beta')
+        info_str = view.addFolder('/alpha', 'beta')
+        info = json.loads(info_str)
 
         self.assertEqual(info['code'], 0)
         self.assertEqual(info['error'], '')
@@ -86,7 +81,8 @@ def test_addfolder_exists(self):
 
         view = FileManagerActions(r, self.layer['request'])
 
-        info = view.addFolder('/', 'alpha')
+        info_str = view.addFolder('/', 'alpha')
+        info = json.loads(info_str)
 
         self.assertEqual(info['code'], 1)
         self.assertNotEqual(info['error'], '')
@@ -102,6 +98,7 @@ def test_addfolder_invalid_name(self):
 
         for char in '\\/:*?"<>':
             info = view.addFolder('/', 'foo' + char)
+            info = json.loads(info)
 
             self.assertEqual(info['code'], 1)
             self.assertNotEqual(info['error'], '')
@@ -115,6 +112,7 @@ def test_addfolder_invalid_parent(self):
         view = FileManagerActions(r, self.layer['request'])
 
         info = view.addFolder('/alpha', 'beta')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 1)
         self.assertNotEqual(info['error'], '')
@@ -128,10 +126,10 @@ def test_add(self):
 
         view = FileManagerActions(r, self.layer['request'])
 
-        d = StringIO('foo')
-        d.filename = 'test.txt'
+        d = 'test.txt'
 
-        info = view.add('/', d)
+        info = view.addFile('/', d)
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 0)
         self.assertEqual(info['error'], '')
@@ -147,10 +145,10 @@ def test_add_subfolder(self):
 
         view = FileManagerActions(r, self.layer['request'])
 
-        d = StringIO('foo')
-        d.filename = 'test.txt'
+        d = 'test.txt'
 
-        info = view.add('/alpha', d)
+        info = view.addFile('/alpha', d)
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 0)
         self.assertEqual(info['error'], '')
@@ -166,66 +164,16 @@ def test_add_exists(self):
 
         view = FileManagerActions(r, self.layer['request'])
 
-        d = StringIO('foo')
-        d.filename = 'test.txt'
+        d = 'test.txt'
 
-        info = view.add('/', d)
+        info = view.addFile('/', d)
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 1)
         self.assertNotEqual(info['error'], '')
 
         self.assertEqual(r.readFile('test.txt'), 'boo')
 
-    def test_add_replace(self):
-        from plone.resourceeditor.browser import FileManagerActions
-        from StringIO import StringIO
-        r = self._make_directory()
-        r.writeFile('test.txt', 'boo')
-
-        view = FileManagerActions(r, self.layer['request'])
-
-        d = StringIO('foo')
-        d.filename = 'test.txt'
-
-        info = view.add('/', d, '/test.txt')
-
-        self.assertEqual(info['code'], 0)
-        self.assertEqual(info['error'], '')
-        self.assertEqual(info['name'], 'test.txt')
-        self.assertEqual(info['path'], '/')
-        self.assertEqual(info['parent'], '/')
-
-        self.assertEqual(r.readFile('test.txt'), 'foo')
-
-    def test_addnew(self):
-        from plone.resourceeditor.browser import FileManagerActions
-        r = self._make_directory()
-
-        view = FileManagerActions(r, self.layer['request'])
-
-        info = view.addNew('/', 'test.txt')
-
-        self.assertEqual(info['code'], 0)
-        self.assertEqual(info['error'], '')
-        self.assertEqual(info['name'], 'test.txt')
-        self.assertEqual(info['parent'], '/')
-
-        self.assertEqual(r.readFile('test.txt'), '')
-
-    def test_addnew_exists(self):
-        from plone.resourceeditor.browser import FileManagerActions
-        r = self._make_directory()
-        r.writeFile('test.txt', 'foo')
-
-        view = FileManagerActions(r, self.layer['request'])
-
-        info = view.addNew('/', 'test.txt')
-
-        self.assertEqual(info['code'], 1)
-        self.assertNotEqual(info['error'], '')
-
-        self.assertEqual(r.readFile('test.txt'), 'foo')
-
     def test_addnew_invalidname(self):
         from plone.resourceeditor.browser import FileManagerActions
         r = self._make_directory()
@@ -233,7 +181,8 @@ def test_addnew_invalidname(self):
         view = FileManagerActions(r, self.layer['request'])
 
         for char in '\\/:*?"<>':
-            info = view.addNew('/', 'foo' + char)
+            info = view.addFile('/', 'foo' + char)
+            info = json.loads(info)
             self.assertEqual(info['code'], 1)
             self.assertNotEqual(info['error'], '')
 
@@ -244,7 +193,8 @@ def test_rename(self):
 
         view = FileManagerActions(r, self.layer['request'])
 
-        info = view.rename('/test.txt', 'foo.txt')
+        info = view.renameFile('/test.txt', 'foo.txt')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 0)
         self.assertEqual(info['error'], '')
@@ -263,7 +213,8 @@ def test_rename_subfolder(self):
 
         view = FileManagerActions(r, self.layer['request'])
 
-        info = view.rename('/alpha/test.txt', 'foo.txt')
+        info = view.renameFile('/alpha/test.txt', 'foo.txt')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 0)
         self.assertEqual(info['error'], '')
@@ -282,7 +233,8 @@ def test_rename_exists(self):
 
         view = FileManagerActions(r, self.layer['request'])
 
-        info = view.rename('/test.txt', 'foo.txt')
+        info = view.renameFile('/test.txt', 'foo.txt')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 1)
         self.assertNotEqual(info['error'], '')
@@ -301,6 +253,7 @@ def test_delete(self):
         view = FileManagerActions(r, self.layer['request'])
 
         info = view.delete('/test.txt')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 0)
         self.assertEqual(info['error'], '')
@@ -317,6 +270,7 @@ def test_delete_subfolder(self):
         view = FileManagerActions(r, self.layer['request'])
 
         info = view.delete('/alpha/test.txt')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 0)
         self.assertEqual(info['error'], '')
@@ -331,6 +285,7 @@ def test_delete_notfound(self):
         view = FileManagerActions(r, self.layer['request'])
 
         info = view.delete('/test.txt')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 1)
         self.assertNotEqual(info['error'], '')
@@ -345,6 +300,7 @@ def test_move(self):
         view = FileManagerActions(r, self.layer['request'])
 
         info = view.move('/test.txt', '/alpha')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 0)
         self.assertEqual(info['error'], '')
@@ -363,6 +319,7 @@ def test_move_exists(self):
         view = FileManagerActions(r, self.layer['request'])
 
         info = view.move('/test.txt', '/alpha')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 1)
         self.assertNotEqual(info['error'], '')
@@ -379,6 +336,7 @@ def test_move_invalid_parent(self):
         view = FileManagerActions(r, self.layer['request'])
 
         info = view.move('/test.txt', '/alpha')
+        info = json.loads(info)
 
         self.assertEqual(info['code'], 1)
         self.assertNotEqual(info['error'], '')



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.