diff sat/plugins/plugin_comp_file_sharing_management.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 0bafdbda7f5f
children 9d0df638c8b4
line wrap: on
line diff
--- a/sat/plugins/plugin_comp_file_sharing_management.py	Wed Jul 31 11:31:22 2019 +0200
+++ b/sat/plugins/plugin_comp_file_sharing_management.py	Tue Aug 13 19:08:41 2019 +0200
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 # SAT plugin to detect language (experimental)
@@ -31,25 +31,25 @@
 
 
 PLUGIN_INFO = {
-    C.PI_NAME: u"File Sharing Management",
-    C.PI_IMPORT_NAME: u"FILE_SHARING_MANAGEMENT",
+    C.PI_NAME: "File Sharing Management",
+    C.PI_IMPORT_NAME: "FILE_SHARING_MANAGEMENT",
     C.PI_MODES: [C.PLUG_MODE_COMPONENT],
-    C.PI_TYPE: u"EXP",
+    C.PI_TYPE: "EXP",
     C.PI_PROTOCOLS: [],
-    C.PI_DEPENDENCIES: [u"XEP-0050", u"XEP-0264"],
+    C.PI_DEPENDENCIES: ["XEP-0050", "XEP-0264"],
     C.PI_RECOMMENDATIONS: [],
-    C.PI_MAIN: u"FileSharingManagement",
-    C.PI_HANDLER: u"no",
+    C.PI_MAIN: "FileSharingManagement",
+    C.PI_HANDLER: "no",
     C.PI_DESCRIPTION: _(
-        u"Experimental handling of file management for file sharing. This plugins allows "
-        u"to change permissions of stored files/directories or remove them."
+        "Experimental handling of file management for file sharing. This plugins allows "
+        "to change permissions of stored files/directories or remove them."
     ),
 }
 
-NS_FILE_MANAGEMENT = u"https://salut-a-toi.org/protocol/file-management:0"
-NS_FILE_MANAGEMENT_PERM = u"https://salut-a-toi.org/protocol/file-management:0#perm"
-NS_FILE_MANAGEMENT_DELETE = u"https://salut-a-toi.org/protocol/file-management:0#delete"
-NS_FILE_MANAGEMENT_THUMB = u"https://salut-a-toi.org/protocol/file-management:0#thumb"
+NS_FILE_MANAGEMENT = "https://salut-a-toi.org/protocol/file-management:0"
+NS_FILE_MANAGEMENT_PERM = "https://salut-a-toi.org/protocol/file-management:0#perm"
+NS_FILE_MANAGEMENT_DELETE = "https://salut-a-toi.org/protocol/file-management:0#delete"
+NS_FILE_MANAGEMENT_THUMB = "https://salut-a-toi.org/protocol/file-management:0#thumb"
 
 
 class WorkflowError(Exception):
@@ -68,7 +68,7 @@
     # syntax?) should be elaborated and proposed as a standard.
 
     def __init__(self, host):
-        log.info(_(u"File Sharing Management plugin initialization"))
+        log.info(_("File Sharing Management plugin initialization"))
         self.host = host
         self._c = host.plugins["XEP-0050"]
         self._t = host.plugins["XEP-0264"]
@@ -76,17 +76,17 @@
 
     def profileConnected(self, client):
         self._c.addAdHocCommand(
-            client, self._onChangeFile, u"Change Permissions of File(s)",
+            client, self._onChangeFile, "Change Permissions of File(s)",
             node=NS_FILE_MANAGEMENT_PERM,
             allowed_magics=C.ENTITY_ALL,
         )
         self._c.addAdHocCommand(
-            client, self._onDeleteFile, u"Delete File(s)",
+            client, self._onDeleteFile, "Delete File(s)",
             node=NS_FILE_MANAGEMENT_DELETE,
             allowed_magics=C.ENTITY_ALL,
         )
         self._c.addAdHocCommand(
-            client, self._onGenThumbnails, u"Generate Thumbnails",
+            client, self._onGenThumbnails, "Generate Thumbnails",
             node=NS_FILE_MANAGEMENT_THUMB,
             allowed_magics=C.ENTITY_ALL,
         )
@@ -109,7 +109,7 @@
         @return (tuple): arguments to use in defer.returnValue
         """
         status = self._c.STATUS.EXECUTING
-        form = data_form.Form("form", title=u"File Management",
+        form = data_form.Form("form", title="File Management",
                               formNamespace=NS_FILE_MANAGEMENT)
 
         field = data_form.Field(
@@ -136,17 +136,17 @@
         """
         fields = command_form.fields
         try:
-            path = fields[u'path'].value.strip()
-            namespace = fields[u'namespace'].value or None
+            path = fields['path'].value.strip()
+            namespace = fields['namespace'].value or None
         except KeyError:
             self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
 
         if not path:
             self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
 
-        requestor = session_data[u'requestor']
+        requestor = session_data['requestor']
         requestor_bare = requestor.userhostJID()
-        path = path.rstrip(u'/')
+        path = path.rstrip('/')
         parent_path, basename = os.path.split(path)
 
         # TODO: if parent_path and basename are empty, we ask for root directory
@@ -158,31 +158,31 @@
                 namespace=namespace)
             found_file = found_files[0]
         except (exceptions.NotFound, IndexError):
-            raise WorkflowError(self._err(_(u"file not found")))
+            raise WorkflowError(self._err(_("file not found")))
         except exceptions.PermissionError:
-            raise WorkflowError(self._err(_(u"forbidden")))
+            raise WorkflowError(self._err(_("forbidden")))
 
         if found_file['owner'] != requestor_bare:
             # only owner can manage files
-            log.warning(_(u"Only owner can manage files"))
-            raise WorkflowError(self._err(_(u"forbidden")))
+            log.warning(_("Only owner can manage files"))
+            raise WorkflowError(self._err(_("forbidden")))
 
-        session_data[u'found_file'] = found_file
-        session_data[u'namespace'] = namespace
+        session_data['found_file'] = found_file
+        session_data['namespace'] = namespace
         defer.returnValue(found_file)
 
     def _updateReadPermission(self, access, allowed_jids):
         if not allowed_jids:
             if C.ACCESS_PERM_READ in access:
                 del access[C.ACCESS_PERM_READ]
-        elif allowed_jids == u'PUBLIC':
+        elif allowed_jids == 'PUBLIC':
             access[C.ACCESS_PERM_READ] = {
-                u"type": C.ACCESS_TYPE_PUBLIC
+                "type": C.ACCESS_TYPE_PUBLIC
             }
         else:
             access[C.ACCESS_PERM_READ] = {
-                u"type": C.ACCESS_TYPE_WHITELIST,
-                u"jids": [j.full() for j in allowed_jids]
+                "type": C.ACCESS_TYPE_WHITELIST,
+                "jids": [j.full() for j in allowed_jids]
             }
 
     @defer.inlineCallbacks
@@ -192,30 +192,30 @@
         @param file_data(dict): metadata of the file
         @param allowed_jids(list[jid.JID]): list of entities allowed to read the file
         """
-        assert file_data[u'type'] == C.FILE_TYPE_DIRECTORY
+        assert file_data['type'] == C.FILE_TYPE_DIRECTORY
         files_data = yield self.host.memory.getFiles(
-            client, requestor, parent=file_data[u'id'], namespace=namespace)
+            client, requestor, parent=file_data['id'], namespace=namespace)
 
         for file_data in files_data:
-            if not file_data[u'access'].get(C.ACCESS_PERM_READ, {}):
-                log.debug(u"setting {perm} read permission for {name}".format(
-                    perm=allowed_jids, name=file_data[u'name']))
+            if not file_data['access'].get(C.ACCESS_PERM_READ, {}):
+                log.debug("setting {perm} read permission for {name}".format(
+                    perm=allowed_jids, name=file_data['name']))
                 yield self.host.memory.fileUpdate(
-                    file_data[u'id'], u'access',
+                    file_data['id'], 'access',
                     partial(self._updateReadPermission, allowed_jids=allowed_jids))
-            if file_data[u'type'] == C.FILE_TYPE_DIRECTORY:
-                yield self._updateDir(client, requestor, namespace, file_data, u'PUBLIC')
+            if file_data['type'] == C.FILE_TYPE_DIRECTORY:
+                yield self._updateDir(client, requestor, namespace, file_data, 'PUBLIC')
 
     @defer.inlineCallbacks
     def _onChangeFile(self, client, command_elt, session_data, action, node):
         try:
-            x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next()
+            x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
             command_form = data_form.Form.fromElement(x_elt)
         except StopIteration:
             command_form = None
 
         found_file = session_data.get('found_file')
-        requestor = session_data[u'requestor']
+        requestor = session_data['requestor']
         requestor_bare = requestor.userhostJID()
 
         if command_form is None or len(command_form.fields) == 0:
@@ -230,31 +230,31 @@
                 defer.returnValue(e.err_args)
 
             # management request
-            if found_file[u'type'] == C.FILE_TYPE_DIRECTORY:
-                instructions = D_(u"Please select permissions for this directory")
+            if found_file['type'] == C.FILE_TYPE_DIRECTORY:
+                instructions = D_("Please select permissions for this directory")
             else:
-                instructions = D_(u"Please select permissions for this file")
+                instructions = D_("Please select permissions for this file")
 
-            form = data_form.Form("form", title=u"File Management",
+            form = data_form.Form("form", title="File Management",
                                   instructions=[instructions],
                                   formNamespace=NS_FILE_MANAGEMENT)
             field = data_form.Field(
                 "text-multi", "read_allowed", required=False,
-                desc=u'list of jids allowed to read this file (beside yourself), or '
-                     u'"PUBLIC" to let a public access'
+                desc='list of jids allowed to read this file (beside yourself), or '
+                     '"PUBLIC" to let a public access'
             )
-            read_access = found_file[u"access"].get(C.ACCESS_PERM_READ, {})
-            access_type = read_access.get(u'type', C.ACCESS_TYPE_WHITELIST)
+            read_access = found_file["access"].get(C.ACCESS_PERM_READ, {})
+            access_type = read_access.get('type', C.ACCESS_TYPE_WHITELIST)
             if access_type == C.ACCESS_TYPE_PUBLIC:
-                field.values = [u'PUBLIC']
+                field.values = ['PUBLIC']
             else:
                 field.values = read_access.get('jids', [])
             form.addField(field)
-            if found_file[u'type'] == C.FILE_TYPE_DIRECTORY:
+            if found_file['type'] == C.FILE_TYPE_DIRECTORY:
                 field = data_form.Field(
                     "boolean", "recursive", value=False, required=False,
-                    desc=u"Files under it will be made public to follow this dir "
-                         u"permission (only if they don't have already a permission set)."
+                    desc="Files under it will be made public to follow this dir "
+                         "permission (only if they don't have already a permission set)."
                 )
                 form.addField(field)
 
@@ -269,22 +269,22 @@
             except KeyError:
                 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
 
-            if read_allowed.value == u'PUBLIC':
-                allowed_jids = u'PUBLIC'
-            elif read_allowed.value.strip() == u'':
+            if read_allowed.value == 'PUBLIC':
+                allowed_jids = 'PUBLIC'
+            elif read_allowed.value.strip() == '':
                 allowed_jids = None
             else:
                 try:
                     allowed_jids = [jid.JID(v.strip()) for v in read_allowed.values
                                     if v.strip()]
                 except RuntimeError as e:
-                    log.warning(_(u"Can't use read_allowed values: {reason}").format(
+                    log.warning(_("Can't use read_allowed values: {reason}").format(
                         reason=e))
                     self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
 
-            if found_file[u'type'] == C.FILE_TYPE_FILE:
+            if found_file['type'] == C.FILE_TYPE_FILE:
                 yield self.host.memory.fileUpdate(
-                    found_file[u'id'], u'access',
+                    found_file['id'], 'access',
                     partial(self._updateReadPermission, allowed_jids=allowed_jids))
             else:
                 try:
@@ -292,32 +292,32 @@
                 except KeyError:
                     self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
                 yield self.host.memory.fileUpdate(
-                    found_file[u'id'], u'access',
+                    found_file['id'], 'access',
                     partial(self._updateReadPermission, allowed_jids=allowed_jids))
                 if recursive:
                     # we set all file under the directory as public (if they haven't
                     # already a permission set), so allowed entities of root directory
                     # can read them.
-                    namespace = session_data[u'namespace']
+                    namespace = session_data['namespace']
                     yield self._updateDir(
-                        client, requestor_bare, namespace, found_file, u'PUBLIC')
+                        client, requestor_bare, namespace, found_file, 'PUBLIC')
 
             # job done, we can end the session
             status = self._c.STATUS.COMPLETED
             payload = None
-            note = (self._c.NOTE.INFO, _(u"management session done"))
+            note = (self._c.NOTE.INFO, _("management session done"))
             defer.returnValue((payload, status, None, note))
 
     @defer.inlineCallbacks
     def _onDeleteFile(self, client, command_elt, session_data, action, node):
         try:
-            x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next()
+            x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
             command_form = data_form.Form.fromElement(x_elt)
         except StopIteration:
             command_form = None
 
         found_file = session_data.get('found_file')
-        requestor = session_data[u'requestor']
+        requestor = session_data['requestor']
         requestor_bare = requestor.userhostJID()
 
         if command_form is None or len(command_form.fields) == 0:
@@ -330,18 +330,18 @@
                 found_file = yield self._getFileData(client, session_data, command_form)
             except WorkflowError as e:
                 defer.returnValue(e.err_args)
-            if found_file[u'type'] == C.FILE_TYPE_DIRECTORY:
-                msg = D_(u"Are you sure to delete directory {name} and all files and "
-                         u"directories under it?").format(name=found_file[u'name'])
+            if found_file['type'] == C.FILE_TYPE_DIRECTORY:
+                msg = D_("Are you sure to delete directory {name} and all files and "
+                         "directories under it?").format(name=found_file['name'])
             else:
-                msg = D_(u"Are you sure to delete file {name}?"
-                    .format(name=found_file[u'name']))
-            form = data_form.Form("form", title=u"File Management",
+                msg = D_("Are you sure to delete file {name}?"
+                    .format(name=found_file['name']))
+            form = data_form.Form("form", title="File Management",
                                   instructions = [msg],
                                   formNamespace=NS_FILE_MANAGEMENT)
             field = data_form.Field(
                 "boolean", "confirm", value=False, required=True,
-                desc=u"check this box to confirm"
+                desc="check this box to confirm"
             )
             form.addField(field)
             status = self._c.STATUS.EXECUTING
@@ -357,10 +357,10 @@
             if not confirmed:
                 note = None
             else:
-                recursive = found_file[u'type'] == C.FILE_TYPE_DIRECTORY
+                recursive = found_file['type'] == C.FILE_TYPE_DIRECTORY
                 yield self.host.memory.fileDelete(
-                    client, requestor_bare, found_file[u'id'], recursive)
-                note = (self._c.NOTE.INFO, _(u"file deleted"))
+                    client, requestor_bare, found_file['id'], recursive)
+                note = (self._c.NOTE.INFO, _("file deleted"))
             status = self._c.STATUS.COMPLETED
             payload = None
             defer.returnValue((payload, status, None, note))
@@ -374,16 +374,16 @@
 
         @param file_data(dict): metadata of the file
         """
-        if file_data[u'type'] == C.FILE_TYPE_DIRECTORY:
+        if file_data['type'] == C.FILE_TYPE_DIRECTORY:
             sub_files_data = yield self.host.memory.getFiles(
-                client, requestor, parent=file_data[u'id'], namespace=namespace)
+                client, requestor, parent=file_data['id'], namespace=namespace)
             for sub_file_data in sub_files_data:
                 yield self._genThumbs(client, requestor, namespace, sub_file_data)
 
-        elif file_data[u'type'] == C.FILE_TYPE_FILE:
-            mime_type = file_data[u'mime_type']
-            file_path = os.path.join(self.files_path, file_data[u'file_hash'])
-            if mime_type is not None and mime_type.startswith(u"image"):
+        elif file_data['type'] == C.FILE_TYPE_FILE:
+            mime_type = file_data['mime_type']
+            file_path = os.path.join(self.files_path, file_data['file_hash'])
+            if mime_type is not None and mime_type.startswith("image"):
                 thumbnails = []
 
                 for max_thumb_size in (self._t.SIZE_SMALL, self._t.SIZE_MEDIUM):
@@ -395,31 +395,31 @@
                             60 * 60 * 24 * 31 * 6,
                         )
                     except Exception as e:
-                        log.warning(_(u"Can't create thumbnail: {reason}")
+                        log.warning(_("Can't create thumbnail: {reason}")
                             .format(reason=e))
                         break
-                    thumbnails.append({u"id": thumb_id, u"size": thumb_size})
+                    thumbnails.append({"id": thumb_id, "size": thumb_size})
 
                 yield self.host.memory.fileUpdate(
-                    file_data[u'id'], u'extra',
+                    file_data['id'], 'extra',
                     partial(self._updateThumbs, thumbnails=thumbnails))
 
-                log.info(u"thumbnails for [{file_name}] generated"
-                    .format(file_name=file_data[u'name']))
+                log.info("thumbnails for [{file_name}] generated"
+                    .format(file_name=file_data['name']))
 
         else:
-            log.warning(u"unmanaged file type: {type_}".format(type_=file_data[u'type']))
+            log.warning("unmanaged file type: {type_}".format(type_=file_data['type']))
 
     @defer.inlineCallbacks
     def _onGenThumbnails(self, client, command_elt, session_data, action, node):
         try:
-            x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next()
+            x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
             command_form = data_form.Form.fromElement(x_elt)
         except StopIteration:
             command_form = None
 
         found_file = session_data.get('found_file')
-        requestor = session_data[u'requestor']
+        requestor = session_data['requestor']
 
         if command_form is None or len(command_form.fields) == 0:
             # root request
@@ -432,11 +432,11 @@
             except WorkflowError as e:
                 defer.returnValue(e.err_args)
 
-            log.info(u"Generating thumbnails as requested")
-            yield self._genThumbs(client, requestor, found_file[u'namespace'], found_file)
+            log.info("Generating thumbnails as requested")
+            yield self._genThumbs(client, requestor, found_file['namespace'], found_file)
 
             # job done, we can end the session
             status = self._c.STATUS.COMPLETED
             payload = None
-            note = (self._c.NOTE.INFO, _(u"thumbnails generated"))
+            note = (self._c.NOTE.INFO, _("thumbnails generated"))
             defer.returnValue((payload, status, None, note))