Mercurial > libervia-backend
diff sat_frontends/quick_frontend/quick_chat.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 | b5f8cb26ef6f |
children | 1370323e8f6c |
line wrap: on
line diff
--- a/sat_frontends/quick_frontend/quick_chat.py Wed Jul 31 11:31:22 2019 +0200 +++ b/sat_frontends/quick_frontend/quick_chat.py Tue Aug 13 19:08:41 2019 +0200 @@ -43,12 +43,12 @@ try: # FIXME: to be removed when an acceptable solution is here - unicode("") # XXX: unicode doesn't exist in pyjamas + str("") # XXX: unicode doesn't exist in pyjamas except ( TypeError, AttributeError, ): # Error raised is not the same depending on pyjsbuild options - unicode = str + str = str # FIXME: day_format need to be settable (i18n) @@ -78,23 +78,20 @@ ) # is user mentioned here ? if self.parent.type == C.CHAT_GROUP and not self.own_mess: - for m in msg.itervalues(): + for m in msg.values(): if self.parent.nick.lower() in m.lower(): self._mention = True break self.handleMe() self.widgets = set() # widgets linked to this message - def __unicode__(self): - return u"Message<{mess_type}> [{time}]{nick}> {message}".format( + def __str__(self): + return "Message<{mess_type}> [{time}]{nick}> {message}".format( mess_type=self.type, time=self.time_text, nick=self.nick, message=self.main_message) - def __str__(self): - return self.__unicode__().encode('utf-8', 'ignore') - @property def host(self): return self.parent.host @@ -126,28 +123,28 @@ return self.message[""] except KeyError: try: - lang, mess = self.message.iteritems().next() + lang, mess = next(iter(self.message.items())) self.selected_lang = lang return mess except StopIteration: - log.error(u"Can't find message for uid {}".format(self.uid)) + log.error("Can't find message for uid {}".format(self.uid)) return "" @property def main_message_xhtml(self): """rich message""" - xhtml = {k: v for k, v in self.extra.iteritems() if "html" in k} + xhtml = {k: v for k, v in self.extra.items() if "html" in k} if xhtml: # FIXME: we only return first found value for now - return next(xhtml.itervalues()) + return next(iter(xhtml.values())) @property def time_text(self): """Return timestamp in a nicely formatted way""" # if the message was sent before today, we print the full date timestamp = time.localtime(self.timestamp) - time_format = u"%c" if timestamp < self.parent.day_change else u"%H:%M" - return time.strftime(time_format, timestamp).decode(getlocale()[1] or "utf-8") + time_format = "%c" if timestamp < self.parent.day_change else "%H:%M" + return time.strftime(time_format, timestamp) @property def avatar(self): @@ -162,7 +159,7 @@ try: return self.extra["user_nick"] except KeyError: - log.error(u"extra data is missing user nick for uid {}".format(self.uid)) + log.error("extra data is missing user nick for uid {}".format(self.uid)) return "" # FIXME: converted getSpecials to list for pyjamas if self.parent.type == C.CHAT_GROUP or entity in list( @@ -197,8 +194,8 @@ # TODO: XHTML-IM /me are not handled me = False # we need to check /me for every message - for m in self.message.itervalues(): - if m.startswith(u"/me "): + for m in self.message.values(): + if m.startswith("/me "): me = True else: me = False @@ -207,8 +204,8 @@ self.type = C.MESS_TYPE_INFO self.extra["info_type"] = "me" nick = self.nick - for lang, mess in self.message.iteritems(): - self.message[lang] = u"* " + nick + mess[3:] + for lang, mess in self.message.items(): + self.message[lang] = "* " + nick + mess[3:] class MessageWidget(object): @@ -245,7 +242,7 @@ @property def jid(self): """jid in the room""" - return jid.JID(u"{}/{}".format(self.parent.target.bare, self.nick)) + return jid.JID("{}/{}".format(self.parent.target.bare, self.nick)) @property def real_jid(self): @@ -295,10 +292,10 @@ if type_ == C.CHAT_GROUP: if target.resource: raise exceptions.InternalError( - u"a group chat entity can't have a resource" + "a group chat entity can't have a resource" ) if nick is None: - raise exceptions.InternalError(u"nick must not be None for group chat") + raise exceptions.InternalError("nick must not be None for group chat") self.nick = nick self.occupants = {} @@ -306,7 +303,7 @@ else: if occupants is not None or nick is not None: raise exceptions.InternalError( - u"only group chat can have occupants or nick" + "only group chat can have occupants or nick" ) self.messages = OrderedDict() # key: uid, value: Message instance self.games = {} # key=game name (unicode), value=instance of quick_games.RoomGame @@ -334,25 +331,25 @@ # FIXME: we don't use getter/setter here because of pyjamas # TODO: use proper getter/setter once we get rid of pyjamas if self._locked: - log.warning(u"{wid} is already locked!".format(wid=self)) + log.warning("{wid} is already locked!".format(wid=self)) return self._locked = True # messageNew signals are cached when locked self._cache = OrderedDict() - log.debug(u"{wid} is now locked".format(wid=self)) + log.debug("{wid} is now locked".format(wid=self)) def setUnlocked(self): if not self._locked: - log.debug(u"{wid} was already unlocked".format(wid=self)) + log.debug("{wid} was already unlocked".format(wid=self)) return self._locked = False - for uid, data in self._cache.iteritems(): + for uid, data in self._cache.items(): if uid not in self.messages: self.messageNew(*data) else: - log.debug(u"discarding message already in history: {data}, ".format(data=data)) + log.debug("discarding message already in history: {data}, ".format(data=data)) del self._cache - log.debug(u"{wid} is now unlocked".format(wid=self)) + log.debug("{wid} is now unlocked".format(wid=self)) def postInit(self): """Method to be called by frontend after widget is initialised @@ -404,8 +401,8 @@ if self._resync_lock: return self._resync_lock = True - log.debug(u"resynchronising {self}".format(self=self)) - for mess in reversed(self.messages.values()): + log.debug("resynchronising {self}".format(self=self)) + for mess in reversed(list(self.messages.values())): if mess.type == C.MESS_TYPE_INFO: continue last_message = mess @@ -417,7 +414,7 @@ if self.type == C.CHAT_GROUP: self.occupantsClear() self.host.bridge.mucOccupantsGet( - unicode(self.target), self.profile, callback=self.updateOccupants, + str(self.target), self.profile, callback=self.updateOccupants, errback=log.error) self.historyPrint( size=C.HISTORY_LIMIT_NONE, @@ -427,15 +424,15 @@ ## Widget management ## - def __unicode__(self): - return u"Chat Widget [target: {}, type: {}, profile: {}]".format( + def __str__(self): + return "Chat Widget [target: {}, type: {}, profile: {}]".format( self.target, self.type, self.profile ) @staticmethod def getWidgetHash(target, profiles): profile = list(profiles)[0] - return profile + "\n" + unicode(target.bare) + return profile + "\n" + str(target.bare) @staticmethod def getPrivateHash(target, profile): @@ -443,7 +440,7 @@ This method should be used with force_hash to get unique widget for private MUC conversations """ - return (unicode(profile), target) + return (str(profile), target) def addTarget(self, target): super(QuickChat, self).addTarget(target) @@ -456,7 +453,7 @@ """copy important attribute for a new widget""" kwargs["type_"] = self.type if self.type == C.CHAT_GROUP: - kwargs["occupants"] = {o.nick: o.data for o in self.occupants.itervalues()} + kwargs["occupants"] = {o.nick: o.data for o in self.occupants.values()} kwargs["subject"] = self.subject try: kwargs["nick"] = self.nick @@ -492,7 +489,7 @@ def setOccupants(self, occupants): """Set the whole list of occupants""" assert len(self.occupants) == 0 - for nick, data in occupants.iteritems(): + for nick, data in occupants.items(): # XXX: this log is disabled because it's really too verbose # but kept commented as it may be useful for debugging # log.debug(u"adding occupant {nick} to {room}".format( @@ -510,12 +507,12 @@ updated_occupants = set(occupants) left_occupants = local_occupants - updated_occupants joined_occupants = updated_occupants - local_occupants - log.debug(u"updating occupants for {room}:\n" - u"left: {left_occupants}\n" - u"joined: {joined_occupants}" + log.debug("updating occupants for {room}:\n" + "left: {left_occupants}\n" + "joined: {joined_occupants}" .format(room=self.target, - left_occupants=u", ".join(left_occupants), - joined_occupants=u", ".join(joined_occupants))) + left_occupants=", ".join(left_occupants), + joined_occupants=", ".join(joined_occupants))) for nick in left_occupants: self.removeUser(occupants[nick]) for nick in joined_occupants: @@ -533,7 +530,7 @@ try: occupant = self.occupants.pop(nick) except KeyError: - log.warning(u"Trying to remove an unknown occupant: {}".format(nick)) + log.warning("Trying to remove an unknown occupant: {}".format(nick)) else: return occupant @@ -602,12 +599,12 @@ if filters is None: filters = {} if size == 0: - log.debug(u"Empty history requested, skipping") + log.debug("Empty history requested, skipping") self._onHistoryPrinted() return - log_msg = _(u"now we print the history") + log_msg = _("now we print the history") if size != C.HISTORY_LIMIT_DEFAULT: - log_msg += _(u" ({} messages)".format(size)) + log_msg += _(" ({} messages)".format(size)) log.debug(log_msg) if self.type == C.CHAT_ONE2ONE: @@ -661,17 +658,17 @@ callback() def _historyGetEb(err): - log.error(_(u"Can't get history: {}").format(err)) + log.error(_("Can't get history: {}").format(err)) self._onHistoryPrinted() if callback is not None: callback() self.host.bridge.historyGet( - unicode(self.host.profiles[profile].whoami.bare), - unicode(target), + str(self.host.profiles[profile].whoami.bare), + str(target), size, True, - {k: unicode(v) for k,v in filters.iteritems()}, + {k: str(v) for k,v in filters.items()}, profile, callback=_historyGetCb, errback=_historyGetEb, @@ -683,7 +680,7 @@ self.messageEncryptionStarted(session_data) def messageEncryptionGetEb(self, failure_): - log.error(_(u"Can't get encryption state: {reason}").format(reason=failure_)) + log.error(_("Can't get encryption state: {reason}").format(reason=failure_)) def getEncryptionState(self): """Retrieve encryption state with current target. @@ -693,7 +690,7 @@ """ if self.type == C.CHAT_GROUP: return - self.host.bridge.messageEncryptionGet(unicode(self.target.bare), self.profile, + self.host.bridge.messageEncryptionGet(str(self.target.bare), self.profile, callback=self.messageEncryptionGetCb, errback=self.messageEncryptionGetEb) @@ -715,7 +712,7 @@ return if not msg and not subject and type_ != C.MESS_TYPE_INFO: - log.warning(u"Received an empty message for uid {}".format(uid)) + log.warning("Received an empty message for uid {}".format(uid)) return if self.type == C.CHAT_GROUP: @@ -734,7 +731,7 @@ pass else: user_data = { - k[5:]: v for k, v in extra.iteritems() if k.startswith("user_") + k[5:]: v for k, v in extra.items() if k.startswith("user_") } if info_type == ROOM_USER_JOINED: self.addUser(user_data) @@ -747,18 +744,18 @@ self.messages[uid] = message if "received_timestamp" in extra: - log.warning(u"Delayed message received after history, this should not happen") + log.warning("Delayed message received after history, this should not happen") self.createMessage(message) def messageEncryptionStarted(self, session_data): self.encrypted = True - log.debug(_(u"message encryption started with {target} using {encryption}").format( - target=self.target, encryption=session_data[u'name'])) + log.debug(_("message encryption started with {target} using {encryption}").format( + target=self.target, encryption=session_data['name'])) def messageEncryptionStopped(self, session_data): self.encrypted = False - log.debug(_(u"message encryption stopped with {target} (was using {encryption})") - .format(target=self.target, encryption=session_data[u'name'])) + log.debug(_("message encryption stopped with {target} (was using {encryption})") + .format(target=self.target, encryption=session_data['name'])) def createMessage(self, message, append=False): """Must be implemented by frontend to create and show a new message widget @@ -810,12 +807,12 @@ count = wid.reentered_count = 1 nick = wid.mess_data.nick if message.info_type == ROOM_USER_LEFT: - wid.message = _(u"<= {nick} has left the room ({count})").format( + wid.message = _("<= {nick} has left the room ({count})").format( nick=nick, count=count ) else: wid.message = _( - u"<=> {nick} re-entered the room ({count})" + "<=> {nick} re-entered the room ({count})" ).format(nick=nick, count=count) wid.reentered_count += 1 return True @@ -845,7 +842,7 @@ This change the subject on the room itself (i.e. via XMPP), while setSubject change the subject of this widget """ - self.host.bridge.mucSubject(unicode(self.target), new_subject, self.profile) + self.host.bridge.mucSubject(str(self.target), new_subject, self.profile) def addGamePanel(self, widget): """Insert a game panel to this Chat dialog. @@ -879,7 +876,7 @@ self.occupants[nick].state = state except KeyError: log.warning( - u"{nick} not found in {room}, ignoring new chat state".format( + "{nick} not found in {room}, ignoring new chat state".format( nick=nick, room=self.target.bare ) ) @@ -902,7 +899,7 @@ # entity is not here anymore pass - for m in self.messages.values(): + for m in list(self.messages.values()): if m.nick == entity.resource: for w in m.widgets: w.update({"avatar": filename}) @@ -911,8 +908,8 @@ entity.bare == self.target.bare or entity.bare == self.host.profiles[profile].whoami.bare ): - log.info(u"avatar updated for {}".format(entity)) - for m in self.messages.values(): + log.info("avatar updated for {}".format(entity)) + for m in list(self.messages.values()): if m.from_jid.bare == entity.bare: for w in m.widgets: w.update({"avatar": filename})