Mercurial > libervia-backend
comparison sat_frontends/primitivus/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 | 4d5b9d4c7448 |
children | ab7e8ade848a |
comparison
equal
deleted
inserted
replaced
3027:ff5bcb12ae60 | 3028:ab2696e34d29 |
---|---|
33 from sat_frontends.primitivus.contact_list import ContactList | 33 from sat_frontends.primitivus.contact_list import ContactList |
34 from functools import total_ordering | 34 from functools import total_ordering |
35 import bisect | 35 import bisect |
36 | 36 |
37 | 37 |
38 OCCUPANTS_FOOTER = _(u"{} occupants") | 38 OCCUPANTS_FOOTER = _("{} occupants") |
39 | 39 |
40 | 40 |
41 class MessageWidget(urwid.WidgetWrap, quick_chat.MessageWidget): | 41 class MessageWidget(urwid.WidgetWrap, quick_chat.MessageWidget): |
42 def __init__(self, mess_data): | 42 def __init__(self, mess_data): |
43 """ | 43 """ |
111 d = self.mess_data | 111 d = self.mess_data |
112 mention = d.mention | 112 mention = d.mention |
113 | 113 |
114 # message status | 114 # message status |
115 if d.status is None: | 115 if d.status is None: |
116 markup.append(u" ") | 116 markup.append(" ") |
117 elif d.status == "delivered": | 117 elif d.status == "delivered": |
118 markup.append(("msg_status_received", u"✔")) | 118 markup.append(("msg_status_received", "✔")) |
119 else: | 119 else: |
120 log.warning(u"Unknown status: {}".format(d.status)) | 120 log.warning("Unknown status: {}".format(d.status)) |
121 | 121 |
122 # timestamp | 122 # timestamp |
123 if self.parent.show_timestamp: | 123 if self.parent.show_timestamp: |
124 attr = "msg_mention" if mention else "date" | 124 attr = "msg_mention" if mention else "date" |
125 markup.append((attr, u"[{}]".format(d.time_text))) | 125 markup.append((attr, "[{}]".format(d.time_text))) |
126 else: | 126 else: |
127 if mention: | 127 if mention: |
128 markup.append(("msg_mention", "[*]")) | 128 markup.append(("msg_mention", "[*]")) |
129 | 129 |
130 # nickname | 130 # nickname |
132 markup.append( | 132 markup.append( |
133 ("my_nick" if d.own_mess else "other_nick", "**" if d.own_mess else "*") | 133 ("my_nick" if d.own_mess else "other_nick", "**" if d.own_mess else "*") |
134 ) | 134 ) |
135 else: | 135 else: |
136 markup.append( | 136 markup.append( |
137 ("my_nick" if d.own_mess else "other_nick", u"[{}] ".format(d.nick or "")) | 137 ("my_nick" if d.own_mess else "other_nick", "[{}] ".format(d.nick or "")) |
138 ) | 138 ) |
139 | 139 |
140 msg = self.message # needed to generate self.selected_lang | 140 msg = self.message # needed to generate self.selected_lang |
141 | 141 |
142 if d.selected_lang: | 142 if d.selected_lang: |
143 markup.append(("msg_lang", u"[{}] ".format(d.selected_lang))) | 143 markup.append(("msg_lang", "[{}] ".format(d.selected_lang))) |
144 | 144 |
145 # message body | 145 # message body |
146 markup.append(msg) | 146 markup.append(msg) |
147 | 147 |
148 return markup | 148 return markup |
169 self.occupant_data.parent._occupantsClicked, | 169 self.occupant_data.parent._occupantsClicked, |
170 user_args=[self.occupant_data], | 170 user_args=[self.occupant_data], |
171 ) | 171 ) |
172 super(OccupantWidget, self).__init__(text) | 172 super(OccupantWidget, self).__init__(text) |
173 | 173 |
174 def __hash__(self): | |
175 return id(self) | |
176 | |
174 def __eq__(self, other): | 177 def __eq__(self, other): |
175 if other is None: | 178 if other is None: |
176 return False | 179 return False |
177 return self.occupant_data.nick == other.occupant_data.nick | 180 return self.occupant_data.nick == other.occupant_data.nick |
178 | 181 |
216 # TODO: role and affiliation are shown in a Q&D way | 219 # TODO: role and affiliation are shown in a Q&D way |
217 # should be more intuitive and themable | 220 # should be more intuitive and themable |
218 o = self.occupant_data | 221 o = self.occupant_data |
219 markup = [] | 222 markup = [] |
220 markup.append( | 223 markup.append( |
221 ("info_msg", u"{}{} ".format(o.role[0].upper(), o.affiliation[0].upper())) | 224 ("info_msg", "{}{} ".format(o.role[0].upper(), o.affiliation[0].upper())) |
222 ) | 225 ) |
223 markup.append(o.nick) | 226 markup.append(o.nick) |
224 if o.state is not None: | 227 if o.state is not None: |
225 markup.append(u" {}".format(C.CHAT_STATE_ICON[o.state])) | 228 markup.append(" {}".format(C.CHAT_STATE_ICON[o.state])) |
226 return markup | 229 return markup |
227 | 230 |
228 # events | 231 # events |
229 def update(self, update_dict=None): | 232 def update(self, update_dict=None): |
230 self.redraw() | 233 self.redraw() |
238 self.updateFooter() | 241 self.updateFooter() |
239 occupants_widget = urwid.Frame( | 242 occupants_widget = urwid.Frame( |
240 urwid.ListBox(self.occupants_walker), footer=self.occupants_footer | 243 urwid.ListBox(self.occupants_walker), footer=self.occupants_footer |
241 ) | 244 ) |
242 super(OccupantsWidget, self).__init__(occupants_widget) | 245 super(OccupantsWidget, self).__init__(occupants_widget) |
243 occupants_list = sorted(self.parent.occupants.keys(), key=lambda o: o.lower()) | 246 occupants_list = sorted(list(self.parent.occupants.keys()), key=lambda o: o.lower()) |
244 for occupant in occupants_list: | 247 for occupant in occupants_list: |
245 occupant_data = self.parent.occupants[occupant] | 248 occupant_data = self.parent.occupants[occupant] |
246 self.occupants_walker.append(OccupantWidget(occupant_data)) | 249 self.occupants_walker.append(OccupantWidget(occupant_data)) |
247 | 250 |
248 def clear(self): | 251 def clear(self): |
251 def updateFooter(self): | 254 def updateFooter(self): |
252 """update footer widget""" | 255 """update footer widget""" |
253 txt = OCCUPANTS_FOOTER.format(len(self.parent.occupants)) | 256 txt = OCCUPANTS_FOOTER.format(len(self.parent.occupants)) |
254 self.occupants_footer.set_text(txt) | 257 self.occupants_footer.set_text(txt) |
255 | 258 |
256 def getNicks(self, start=u""): | 259 def getNicks(self, start=""): |
257 """Return nicks of all occupants | 260 """Return nicks of all occupants |
258 | 261 |
259 @param start(unicode): only return nicknames which start with this text | 262 @param start(unicode): only return nicknames which start with this text |
260 """ | 263 """ |
261 return [ | 264 return [ |
279 | 282 |
280 | 283 |
281 class Chat(PrimitivusWidget, quick_chat.QuickChat): | 284 class Chat(PrimitivusWidget, quick_chat.QuickChat): |
282 def __init__(self, host, target, type_=C.CHAT_ONE2ONE, nick=None, occupants=None, | 285 def __init__(self, host, target, type_=C.CHAT_ONE2ONE, nick=None, occupants=None, |
283 subject=None, profiles=None): | 286 subject=None, profiles=None): |
284 quick_chat.QuickChat.__init__( | |
285 self, host, target, type_, nick, occupants, subject, profiles=profiles | |
286 ) | |
287 self.filters = [] # list of filter callbacks to apply | 287 self.filters = [] # list of filter callbacks to apply |
288 self.mess_walker = urwid.SimpleListWalker([]) | 288 self.mess_walker = urwid.SimpleListWalker([]) |
289 self.mess_widgets = urwid.ListBox(self.mess_walker) | 289 self.mess_widgets = urwid.ListBox(self.mess_walker) |
290 self.chat_widget = urwid.Frame(self.mess_widgets) | 290 self.chat_widget = urwid.Frame(self.mess_widgets) |
291 self.chat_colums = urwid.Columns([("weight", 8, self.chat_widget)]) | 291 self.chat_colums = urwid.Columns([("weight", 8, self.chat_widget)]) |
292 self.pile = urwid.Pile([self.chat_colums]) | 292 self.pile = urwid.Pile([self.chat_colums]) |
293 PrimitivusWidget.__init__(self, self.pile, self.target) | 293 PrimitivusWidget.__init__(self, self.pile, target) |
294 quick_chat.QuickChat.__init__( | |
295 self, host, target, type_, nick, occupants, subject, profiles=profiles | |
296 ) | |
294 | 297 |
295 # we must adapt the behaviour with the type | 298 # we must adapt the behaviour with the type |
296 if type_ == C.CHAT_GROUP: | 299 if type_ == C.CHAT_GROUP: |
297 if len(self.chat_colums.contents) == 1: | 300 if len(self.chat_colums.contents) == 1: |
298 self.occupants_widget = OccupantsWidget(self) | 301 self.occupants_widget = OccupantsWidget(self) |
363 word_idx = 0 | 366 word_idx = 0 |
364 else: | 367 else: |
365 if word_idx == len(words): | 368 if word_idx == len(words): |
366 word_idx = 0 | 369 word_idx = 0 |
367 word = completion_data["last_word"] = words[word_idx] | 370 word = completion_data["last_word"] = words[word_idx] |
368 return u"{}{}{}".format(text[: space + 1], word, ": " if space < 0 else "") | 371 return "{}{}{}".format(text[: space + 1], word, ": " if space < 0 else "") |
369 | 372 |
370 def getMenu(self): | 373 def getMenu(self): |
371 """Return Menu bar""" | 374 """Return Menu bar""" |
372 menu = sat_widgets.Menu(self.host.loop) | 375 menu = sat_widgets.Menu(self.host.loop) |
373 if self.type == C.CHAT_GROUP: | 376 if self.type == C.CHAT_GROUP: |
477 return | 480 return |
478 | 481 |
479 if wid.mess_data.mention: | 482 if wid.mess_data.mention: |
480 from_jid = wid.mess_data.from_jid | 483 from_jid = wid.mess_data.from_jid |
481 msg = _( | 484 msg = _( |
482 u"You have been mentioned by {nick} in {room}".format( | 485 "You have been mentioned by {nick} in {room}".format( |
483 nick=wid.mess_data.nick, room=self.target | 486 nick=wid.mess_data.nick, room=self.target |
484 ) | 487 ) |
485 ) | 488 ) |
486 self.host.notify( | 489 self.host.notify( |
487 C.NOTIFY_MENTION, from_jid, msg, widget=self, profile=self.profile | 490 C.NOTIFY_MENTION, from_jid, msg, widget=self, profile=self.profile |
488 ) | 491 ) |
489 elif not minor_notifs: | 492 elif not minor_notifs: |
490 return | 493 return |
491 elif self.type == C.CHAT_ONE2ONE: | 494 elif self.type == C.CHAT_ONE2ONE: |
492 from_jid = wid.mess_data.from_jid | 495 from_jid = wid.mess_data.from_jid |
493 msg = _(u"{entity} is talking to you".format(entity=from_jid)) | 496 msg = _("{entity} is talking to you".format(entity=from_jid)) |
494 self.host.notify( | 497 self.host.notify( |
495 C.NOTIFY_MESSAGE, from_jid, msg, widget=self, profile=self.profile | 498 C.NOTIFY_MESSAGE, from_jid, msg, widget=self, profile=self.profile |
496 ) | 499 ) |
497 else: | 500 else: |
498 self.host.notify( | 501 self.host.notify( |
555 | 558 |
556 def setSubject(self, subject, wrap="space"): | 559 def setSubject(self, subject, wrap="space"): |
557 """Set title for a group chat""" | 560 """Set title for a group chat""" |
558 quick_chat.QuickChat.setSubject(self, subject) | 561 quick_chat.QuickChat.setSubject(self, subject) |
559 self.subj_wid = urwid.Text( | 562 self.subj_wid = urwid.Text( |
560 unicode(subject.replace("\n", "|") if wrap == "clip" else subject), | 563 str(subject.replace("\n", "|") if wrap == "clip" else subject), |
561 align="left" if wrap == "clip" else "center", | 564 align="left" if wrap == "clip" else "center", |
562 wrap=wrap, | 565 wrap=wrap, |
563 ) | 566 ) |
564 self.chat_widget.header = urwid.AttrMap(self.subj_wid, "title") | 567 self.chat_widget.header = urwid.AttrMap(self.subj_wid, "title") |
565 self.host.redraw() | 568 self.host.redraw() |
571 | 574 |
572 @param clear(bool): clear message before printing if true | 575 @param clear(bool): clear message before printing if true |
573 """ | 576 """ |
574 if clear: | 577 if clear: |
575 del self.mess_walker[:] | 578 del self.mess_walker[:] |
576 for message in self.messages.itervalues(): | 579 for message in self.messages.values(): |
577 self.appendMessage(message, minor_notifs=False) | 580 self.appendMessage(message, minor_notifs=False) |
578 | 581 |
579 def redraw(self): | 582 def redraw(self): |
580 """redraw all messages""" | 583 """redraw all messages""" |
581 for w in self.mess_walker: | 584 for w in self.mess_walker: |
587 def updateHistory(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, profile="@NONE@"): | 590 def updateHistory(self, size=C.HISTORY_LIMIT_DEFAULT, filters=None, profile="@NONE@"): |
588 del self.mess_walker[:] | 591 del self.mess_walker[:] |
589 if filters and "search" in filters: | 592 if filters and "search" in filters: |
590 self.mess_walker.append( | 593 self.mess_walker.append( |
591 urwid.Text( | 594 urwid.Text( |
592 _(u"Results for searching the globbing pattern: {}").format( | 595 _("Results for searching the globbing pattern: {}").format( |
593 filters["search"] | 596 filters["search"] |
594 ) | 597 ) |
595 ) | 598 ) |
596 ) | 599 ) |
597 self.mess_walker.append( | 600 self.mess_walker.append( |
598 urwid.Text(_(u"Type ':history <lines>' to reset the chat history")) | 601 urwid.Text(_("Type ':history <lines>' to reset the chat history")) |
599 ) | 602 ) |
600 super(Chat, self).updateHistory(size, filters, profile) | 603 super(Chat, self).updateHistory(size, filters, profile) |
601 | 604 |
602 def _onHistoryPrinted(self): | 605 def _onHistoryPrinted(self): |
603 """Refresh or scroll down the focus after the history is printed""" | 606 """Refresh or scroll down the focus after the history is printed""" |
673 self.changeSubject(dialog.text) | 676 self.changeSubject(dialog.text) |
674 self.host.removePopUp(dialog) | 677 self.host.removePopUp(dialog) |
675 | 678 |
676 def onSubjectDialog(self, new_subject=None): | 679 def onSubjectDialog(self, new_subject=None): |
677 dialog = sat_widgets.InputDialog( | 680 dialog = sat_widgets.InputDialog( |
678 _(u"Change title"), | 681 _("Change title"), |
679 _(u"Enter the new title"), | 682 _("Enter the new title"), |
680 default_txt=new_subject if new_subject is not None else self.subject, | 683 default_txt=new_subject if new_subject is not None else self.subject, |
681 ) | 684 ) |
682 dialog.setCallback("ok", self._onSubjectDialogCb, dialog) | 685 dialog.setCallback("ok", self._onSubjectDialogCb, dialog) |
683 dialog.setCallback("cancel", lambda __: self.host.removePopUp(dialog)) | 686 dialog.setCallback("cancel", lambda __: self.host.removePopUp(dialog)) |
684 self.host.showPopUp(dialog) | 687 self.host.showPopUp(dialog) |