Mercurial > libervia-backend
diff sat_frontends/jp/cmd_file.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 | 18a98a541f7a |
children | fee60f17ebac |
line wrap: on
line diff
--- a/sat_frontends/jp/cmd_file.py Wed Jul 31 11:31:22 2019 +0200 +++ b/sat_frontends/jp/cmd_file.py Tue Aug 13 19:08:41 2019 +0200 @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. -import base +from . import base import sys import os import os.path @@ -50,32 +50,29 @@ def add_parser_options(self): self.parser.add_argument( - "files", type=str, nargs="+", metavar="file", help=_(u"a list of file") + "files", type=str, nargs="+", metavar="file", help=_("a list of file") ) self.parser.add_argument( - "jid", type=base.unicode_decoder, help=_(u"the destination jid") + "jid", help=_("the destination jid") ) self.parser.add_argument( - "-b", "--bz2", action="store_true", help=_(u"make a bzip2 tarball") + "-b", "--bz2", action="store_true", help=_("make a bzip2 tarball") ) self.parser.add_argument( "-d", "--path", - type=base.unicode_decoder, - help=(u"path to the directory where the file must be stored"), + help=("path to the directory where the file must be stored"), ) self.parser.add_argument( "-N", "--namespace", - type=base.unicode_decoder, - help=(u"namespace of the file"), + help=("namespace of the file"), ) self.parser.add_argument( "-n", "--name", - type=base.unicode_decoder, - default=u"", - help=(u"name to use (DEFAULT: use source file name)"), + default="", + help=("name to use (DEFAULT: use source file name)"), ) def start(self): @@ -83,16 +80,16 @@ self.send_files() def onProgressStarted(self, metadata): - self.disp(_(u"File copy started"), 2) + self.disp(_("File copy started"), 2) def onProgressFinished(self, metadata): - self.disp(_(u"File sent successfully"), 2) + self.disp(_("File sent successfully"), 2) def onProgressError(self, error_msg): if error_msg == C.PROGRESS_ERROR_DECLINED: - self.disp(_(u"The file has been refused by your contact")) + self.disp(_("The file has been refused by your contact")) else: - self.disp(_(u"Error while sending file: {}").format(error_msg), error=True) + self.disp(_("Error while sending file: {}").format(error_msg), error=True) def gotId(self, data, file_): """Called when a progress id has been received @@ -101,13 +98,13 @@ @param file_(str): file path """ # FIXME: this show progress only for last progress_id - self.disp(_(u"File request sent to {jid}".format(jid=self.full_dest_jid)), 1) + self.disp(_("File request sent to {jid}".format(jid=self.full_dest_jid)), 1) try: self.progress_id = data["progress"] except KeyError: # TODO: if 'xmlui' key is present, manage xmlui message display self.disp( - _(u"Can't send file to {jid}".format(jid=self.full_dest_jid)), error=True + _("Can't send file to {jid}".format(jid=self.full_dest_jid)), error=True ) self.host.quit(2) @@ -121,12 +118,12 @@ def send_files(self): for file_ in self.args.files: if not os.path.exists(file_): - self.disp(_(u"file [{}] doesn't exist !").format(file_), error=True) + self.disp(_("file [{}] doesn't exist !").format(file_), error=True) self.host.quit(1) if not self.args.bz2 and os.path.isdir(file_): self.disp( _( - u"[{}] is a dir ! Please send files inside or use compression" + "[{}] is a dir ! Please send files inside or use compression" ).format(file_) ) self.host.quit(1) @@ -134,26 +131,26 @@ self.full_dest_jid = self.host.get_full_jid(self.args.jid) extra = {} if self.args.path: - extra[u"path"] = self.args.path + extra["path"] = self.args.path if self.args.namespace: - extra[u"namespace"] = self.args.namespace + extra["namespace"] = self.args.namespace if self.args.bz2: with tempfile.NamedTemporaryFile("wb", delete=False) as buf: self.host.addOnQuitCallback(os.unlink, buf.name) - self.disp(_(u"bz2 is an experimental option, use with caution")) + self.disp(_("bz2 is an experimental option, use with caution")) # FIXME: check free space - self.disp(_(u"Starting compression, please wait...")) + self.disp(_("Starting compression, please wait...")) sys.stdout.flush() bz2 = tarfile.open(mode="w:bz2", fileobj=buf) - archive_name = u"{}.tar.bz2".format( - os.path.basename(self.args.files[0]) or u"compressed_files" + archive_name = "{}.tar.bz2".format( + os.path.basename(self.args.files[0]) or "compressed_files" ) for file_ in self.args.files: - self.disp(_(u"Adding {}").format(file_), 1) + self.disp(_("Adding {}").format(file_), 1) bz2.add(file_) bz2.close() - self.disp(_(u"Done !"), 1) + self.disp(_("Done !"), 1) self.host.bridge.fileSend( self.full_dest_jid, @@ -193,71 +190,65 @@ @property def filename(self): - return self.args.name or self.args.hash or u"output" + return self.args.name or self.args.hash or "output" def add_parser_options(self): self.parser.add_argument( - "jid", type=base.unicode_decoder, help=_(u"the destination jid") + "jid", help=_("the destination jid") ) self.parser.add_argument( "-D", "--dest", - type=base.unicode_decoder, help=_( - u"destination path where the file will be saved (default: [current_dir]/[name|hash])" + "destination path where the file will be saved (default: [current_dir]/[name|hash])" ), ) self.parser.add_argument( "-n", "--name", - type=base.unicode_decoder, - default=u"", - help=_(u"name of the file"), + default="", + help=_("name of the file"), ) self.parser.add_argument( "-H", "--hash", - type=base.unicode_decoder, - default=u"", - help=_(u"hash of the file"), + default="", + help=_("hash of the file"), ) self.parser.add_argument( "-a", "--hash-algo", - type=base.unicode_decoder, - default=u"sha-256", - help=_(u"hash algorithm use for --hash (default: sha-256)"), + default="sha-256", + help=_("hash algorithm use for --hash (default: sha-256)"), ) self.parser.add_argument( "-d", "--path", - type=base.unicode_decoder, - help=(u"path to the directory containing the file"), + help=("path to the directory containing the file"), ) self.parser.add_argument( "-N", "--namespace", - type=base.unicode_decoder, - help=(u"namespace of the file"), + help=("namespace of the file"), ) self.parser.add_argument( "-f", "--force", action="store_true", - help=_(u"overwrite existing file without confirmation"), + help=_("overwrite existing file without confirmation"), ) def onProgressStarted(self, metadata): - self.disp(_(u"File copy started"), 2) + self.disp(_("File copy started"), 2) def onProgressFinished(self, metadata): - self.disp(_(u"File received successfully"), 2) + self.disp(_("File received successfully"), 2) def onProgressError(self, error_msg): if error_msg == C.PROGRESS_ERROR_DECLINED: - self.disp(_(u"The file request has been refused")) + self.disp(_("The file request has been refused")) else: - self.disp(_(u"Error while requesting file: {}").format(error_msg), error=True) + self.disp(_("Error while requesting file: {}").format(error_msg), error=True) def gotId(self, progress_id): """Called when a progress id has been received @@ -275,7 +266,7 @@ def start(self): if not self.args.name and not self.args.hash: - self.parser.error(_(u"at least one of --name or --hash must be provided")) + self.parser.error(_("at least one of --name or --hash must be provided")) # extra = dict(self.args.extra) if self.args.dest: path = os.path.abspath(os.path.expanduser(self.args.dest)) @@ -285,32 +276,32 @@ path = os.path.abspath(self.filename) if os.path.exists(path) and not self.args.force: - message = _(u"File {path} already exists! Do you want to overwrite?").format( + message = _("File {path} already exists! Do you want to overwrite?").format( path=path ) - confirm = raw_input(u"{} (y/N) ".format(message).encode("utf-8")) - if confirm not in (u"y", u"Y"): - self.disp(_(u"file request cancelled")) + confirm = input("{} (y/N) ".format(message).encode("utf-8")) + if confirm not in ("y", "Y"): + self.disp(_("file request cancelled")) self.host.quit(2) self.full_dest_jid = self.host.get_full_jid(self.args.jid) extra = {} if self.args.path: - extra[u"path"] = self.args.path + extra["path"] = self.args.path if self.args.namespace: - extra[u"namespace"] = self.args.namespace + extra["namespace"] = self.args.namespace self.host.bridge.fileJingleRequest( self.full_dest_jid, path, self.args.name, self.args.hash, - self.args.hash_algo if self.args.hash else u"", + self.args.hash_algo if self.args.hash else "", extra, self.profile, callback=self.gotId, errback=partial( self.errback, - msg=_(u"can't request file: {}"), + msg=_("can't request file: {}"), exit_code=C.EXIT_BRIDGE_ERRBACK, ), ) @@ -332,25 +323,25 @@ } def onProgressStarted(self, metadata): - self.disp(_(u"File copy started"), 2) + self.disp(_("File copy started"), 2) def onProgressFinished(self, metadata): - self.disp(_(u"File received successfully"), 2) + self.disp(_("File received successfully"), 2) if metadata.get("hash_verified", False): try: self.disp( - _(u"hash checked: {algo}:{checksum}").format( + _("hash checked: {algo}:{checksum}").format( algo=metadata["hash_algo"], checksum=metadata["hash"] ), 1, ) except KeyError: - self.disp(_(u"hash is checked but hash value is missing", 1), error=True) + self.disp(_("hash is checked but hash value is missing", 1), error=True) else: - self.disp(_(u"hash can't be verified"), 1) + self.disp(_("hash can't be verified"), 1) def onProgressError(self, error_msg): - self.disp(_(u"Error while receiving file: {}").format(error_msg), error=True) + self.disp(_("Error while receiving file: {}").format(error_msg), error=True) def getXmluiId(self, action_data): # FIXME: we temporarily use ElementTree, but a real XMLUI managing module @@ -359,12 +350,12 @@ try: xml_ui = action_data["xmlui"] except KeyError: - self.disp(_(u"Action has no XMLUI"), 1) + self.disp(_("Action has no XMLUI"), 1) else: ui = ET.fromstring(xml_ui.encode("utf-8")) xmlui_id = ui.get("submit") if not xmlui_id: - self.disp(_(u"Invalid XMLUI received"), error=True) + self.disp(_("Invalid XMLUI received"), error=True) return xmlui_id def onFileAction(self, action_data, action_id, security_limit, profile): @@ -374,17 +365,17 @@ try: from_jid = jid.JID(action_data["meta_from_jid"]) except KeyError: - self.disp(_(u"Ignoring action without from_jid data"), 1) + self.disp(_("Ignoring action without from_jid data"), 1) return try: progress_id = action_data["meta_progress_id"] except KeyError: - self.disp(_(u"ignoring action without progress id"), 1) + self.disp(_("ignoring action without progress id"), 1) return if not self.bare_jids or from_jid.bare in self.bare_jids: if self._overwrite_refused: - self.disp(_(u"File refused because overwrite is needed"), error=True) + self.disp(_("File refused because overwrite is needed"), error=True) self.host.bridge.launchAction( xmlui_id, {"cancelled": C.BOOL_TRUE}, profile_key=profile ) @@ -400,15 +391,15 @@ try: progress_id = action_data["meta_progress_id"] except KeyError: - self.disp(_(u"ignoring action without progress id"), 1) + self.disp(_("ignoring action without progress id"), 1) return - self.disp(_(u"Overwriting needed"), 1) + self.disp(_("Overwriting needed"), 1) if progress_id == self.progress_id: if self.args.force: - self.disp(_(u"Overwrite accepted"), 2) + self.disp(_("Overwrite accepted"), 2) else: - self.disp(_(u"Refused to overwrite"), 2) + self.disp(_("Refused to overwrite"), 2) self._overwrite_refused = True xmlui_data = {"answer": C.boolConst(self.args.force)} @@ -417,40 +408,39 @@ def add_parser_options(self): self.parser.add_argument( "jids", - type=base.unicode_decoder, nargs="*", - help=_(u"jids accepted (accept everything if none is specified)"), + help=_("jids accepted (accept everything if none is specified)"), ) self.parser.add_argument( "-m", "--multiple", action="store_true", - help=_(u"accept multiple files (you'll have to stop manually)"), + help=_("accept multiple files (you'll have to stop manually)"), ) self.parser.add_argument( "-f", "--force", action="store_true", help=_( - u"force overwritting of existing files (/!\\ name is choosed by sender)" + "force overwritting of existing files (/!\\ name is choosed by sender)" ), ) self.parser.add_argument( "--path", default=".", metavar="DIR", - help=_(u"destination path (default: working directory)"), + help=_("destination path (default: working directory)"), ) def start(self): self.bare_jids = [jid.JID(jid_).bare for jid_ in self.args.jids] self.path = os.path.abspath(self.args.path) if not os.path.isdir(self.path): - self.disp(_(u"Given path is not a directory !", error=True)) + self.disp(_("Given path is not a directory !", error=True)) self.host.quit(2) if self.args.multiple: self.host.quit_on_progress_end = False - self.disp(_(u"waiting for incoming file request"), 2) + self.disp(_("waiting for incoming file request"), 2) class Upload(base.CommandBase): @@ -464,7 +454,6 @@ self.parser.add_argument("file", type=str, help=_("file to upload")) self.parser.add_argument( "jid", - type=base.unicode_decoder, nargs="?", help=_("jid of upload component (nothing to autodetect)"), ) @@ -475,21 +464,21 @@ ) def onProgressStarted(self, metadata): - self.disp(_(u"File upload started"), 2) + self.disp(_("File upload started"), 2) def onProgressFinished(self, metadata): - self.disp(_(u"File uploaded successfully"), 2) + self.disp(_("File uploaded successfully"), 2) try: url = metadata["url"] except KeyError: - self.disp(u"download URL not found in metadata") + self.disp("download URL not found in metadata") else: - self.disp(_(u"URL to retrieve the file:"), 1) + self.disp(_("URL to retrieve the file:"), 1) # XXX: url is display alone on a line to make parsing easier self.disp(url) def onProgressError(self, error_msg): - self.disp(_(u"Error while uploading file: {}").format(error_msg), error=True) + self.disp(_("Error while uploading file: {}").format(error_msg), error=True) def gotId(self, data, file_): """Called when a progress id has been received @@ -501,7 +490,7 @@ self.progress_id = data["progress"] except KeyError: # TODO: if 'xmlui' key is present, manage xmlui message display - self.disp(_(u"Can't upload file"), error=True) + self.disp(_("Can't upload file"), error=True) self.host.quit(2) def error(self, failure): @@ -514,10 +503,10 @@ def start(self): file_ = self.args.file if not os.path.exists(file_): - self.disp(_(u"file [{}] doesn't exist !").format(file_), error=True) + self.disp(_("file [{}] doesn't exist !").format(file_), error=True) self.host.quit(1) if os.path.isdir(file_): - self.disp(_(u"[{}] is a dir! Can't upload a dir").format(file_)) + self.disp(_("[{}] is a dir! Can't upload a dir").format(file_)) self.host.quit(1) self.full_dest_jid = ( @@ -547,7 +536,7 @@ "list", use_output=C.OUTPUT_LIST_DICT, extra_outputs=extra_outputs, - help=_(u"retrieve files shared by an entity"), + help=_("retrieve files shared by an entity"), use_verbose=True, ) self.need_loop = True @@ -556,12 +545,11 @@ self.parser.add_argument( "-d", "--path", - default=u"", - help=_(u"path to the directory containing the files"), + default="", + help=_("path to the directory containing the files"), ) self.parser.add_argument( "jid", - type=base.unicode_decoder, nargs="?", default="", help=_("jid of sharing entity (nothing to check our own jid)"), @@ -569,9 +557,9 @@ def file_gen(self, files_data): for file_data in files_data: - yield file_data[u"name"] - yield file_data.get(u"size", "") - yield file_data.get(u"hash", "") + yield file_data["name"] + yield file_data.get("size", "") + yield file_data.get("hash", "") def _name_filter(self, name, row): if row.type == C.FILE_TYPE_DIRECTORY: @@ -579,39 +567,39 @@ elif row.type == C.FILE_TYPE_FILE: return A.color(C.A_FILE, name) else: - self.disp(_(u"unknown file type: {type}").format(type=row.type), error=True) + self.disp(_("unknown file type: {type}").format(type=row.type), error=True) return name def _size_filter(self, size, row): if not size: - return u"" + return "" size = int(size) # cf. https://stackoverflow.com/a/1094933 (thanks) - suffix = u"o" - for unit in [u"", u"Ki", u"Mi", u"Gi", u"Ti", u"Pi", u"Ei", u"Zi"]: + suffix = "o" + for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: if abs(size) < 1024.0: - return A.color(A.BOLD, u"{:.2f}".format(size), unit, suffix) + return A.color(A.BOLD, "{:.2f}".format(size), unit, suffix) size /= 1024.0 - return A.color(A.BOLD, u"{:.2f}".format(size), u"Yi", suffix) + return A.color(A.BOLD, "{:.2f}".format(size), "Yi", suffix) def default_output(self, files_data): """display files a way similar to ls""" files_data.sort(key=lambda d: d["name"].lower()) show_header = False if self.verbosity == 0: - headers = (u"name", u"type") + headers = ("name", "type") elif self.verbosity == 1: - headers = (u"name", u"type", u"size") + headers = ("name", "type", "size") elif self.verbosity > 1: show_header = True - headers = (u"name", u"type", u"size", u"hash") + headers = ("name", "type", "size", "hash") table = common.Table.fromDict( self.host, files_data, headers, - filters={u"name": self._name_filter, u"size": self._size_filter}, - defaults={u"size": u"", u"hash": u""}, + filters={"name": self._name_filter, "size": self._size_filter}, + defaults={"size": "", "hash": ""}, ) table.display_blank(show_header=show_header, hide_cols=["type"]) @@ -628,7 +616,7 @@ callback=self._FISListCb, errback=partial( self.errback, - msg=_(u"can't retrieve shared files: {}"), + msg=_("can't retrieve shared files: {}"), exit_code=C.EXIT_BRIDGE_ERRBACK, ), ) @@ -637,7 +625,7 @@ class SharePath(base.CommandBase): def __init__(self, host): super(SharePath, self).__init__( - host, "path", help=_(u"share a file or directory"), use_verbose=True + host, "path", help=_("share a file or directory"), use_verbose=True ) self.need_loop = True @@ -645,47 +633,44 @@ self.parser.add_argument( "-n", "--name", - type=base.unicode_decoder, - default=u"", - help=_(u"virtual name to use (default: use directory/file name)"), + default="", + help=_("virtual name to use (default: use directory/file name)"), ) perm_group = self.parser.add_mutually_exclusive_group() perm_group.add_argument( "-j", "--jid", - type=base.unicode_decoder, action="append", dest="jids", default=[], - help=_(u"jid of contacts allowed to retrieve the files"), + help=_("jid of contacts allowed to retrieve the files"), ) perm_group.add_argument( "--public", action="store_true", help=_( - u"share publicly the file(s) (/!\\ *everybody* will be able to access them)" + "share publicly the file(s) (/!\\ *everybody* will be able to access them)" ), ) self.parser.add_argument( "path", - type=base.unicode_decoder, - help=_(u"path to a file or directory to share"), + help=_("path to a file or directory to share"), ) def _FISSharePathCb(self, name): self.disp( - _(u'{path} shared under the name "{name}"').format(path=self.path, name=name) + _('{path} shared under the name "{name}"').format(path=self.path, name=name) ) self.host.quit() def start(self): self.path = os.path.abspath(self.args.path) if self.args.public: - access = {u"read": {u"type": u"public"}} + access = {"read": {"type": "public"}} else: jids = self.args.jids if jids: - access = {u"read": {u"type": "whitelist", u"jids": jids}} + access = {"read": {"type": "whitelist", "jids": jids}} else: access = {} self.host.bridge.FISSharePath( @@ -696,7 +681,7 @@ callback=self._FISSharePathCb, errback=partial( self.errback, - msg=_(u"can't share path: {}"), + msg=_("can't share path: {}"), exit_code=C.EXIT_BRIDGE_ERRBACK, ), ) @@ -705,7 +690,7 @@ class ShareInvite(base.CommandBase): def __init__(self, host): super(ShareInvite, self).__init__( - host, "invite", help=_(u"send invitation for a shared repository") + host, "invite", help=_("send invitation for a shared repository") ) self.need_loop = True @@ -713,61 +698,55 @@ self.parser.add_argument( "-n", "--name", - type=base.unicode_decoder, - default=u"", - help=_(u"name of the repository"), + default="", + help=_("name of the repository"), ) self.parser.add_argument( "-N", "--namespace", - type=base.unicode_decoder, - default=u"", - help=_(u"namespace of the repository"), + default="", + help=_("namespace of the repository"), ) self.parser.add_argument( "-P", "--path", - type=base.unicode_decoder, - help=_(u"path to the repository"), + help=_("path to the repository"), ) self.parser.add_argument( "-t", "--type", - choices=[u"files", u"photos"], - default=u"files", - help=_(u"type of the repository"), + choices=["files", "photos"], + default="files", + help=_("type of the repository"), ) self.parser.add_argument( "-T", "--thumbnail", - type=base.unicode_decoder, - help=_(u"https URL of a image to use as thumbnail"), + help=_("https URL of a image to use as thumbnail"), ) self.parser.add_argument( "service", - type=base.unicode_decoder, - help=_(u"jid of the file sharing service hosting the repository"), + help=_("jid of the file sharing service hosting the repository"), ) self.parser.add_argument( "jid", - type=base.unicode_decoder, - help=_(u"jid of the person to invite"), + help=_("jid of the person to invite"), ) def _FISInviteCb(self): self.disp( - _(u'invitation sent to {entity}').format(entity=self.args.jid) + _('invitation sent to {entity}').format(entity=self.args.jid) ) self.host.quit() def start(self): - self.path = os.path.normpath(self.args.path) if self.args.path else u"" + self.path = os.path.normpath(self.args.path) if self.args.path else "" extra = {} if self.args.thumbnail is not None: - if not self.args.thumbnail.startswith(u'http'): - self.parser.error(_(u"only http(s) links are allowed with --thumbnail")) + if not self.args.thumbnail.startswith('http'): + self.parser.error(_("only http(s) links are allowed with --thumbnail")) else: - extra[u'thumb_url'] = self.args.thumbnail + extra['thumb_url'] = self.args.thumbnail self.host.bridge.FISInvite( self.args.jid, self.args.service, @@ -780,7 +759,7 @@ callback=self._FISInviteCb, errback=partial( self.errback, - msg=_(u"can't send invitation: {}"), + msg=_("can't send invitation: {}"), exit_code=C.EXIT_BRIDGE_ERRBACK, ), ) @@ -791,7 +770,7 @@ def __init__(self, host): super(Share, self).__init__( - host, "share", use_profile=False, help=_(u"files sharing management") + host, "share", use_profile=False, help=_("files sharing management") ) @@ -800,5 +779,5 @@ def __init__(self, host): super(File, self).__init__( - host, "file", use_profile=False, help=_(u"files sending/receiving/management") + host, "file", use_profile=False, help=_("files sending/receiving/management") )