Mercurial > libervia-backend
comparison sat_frontends/jp/cmd_roster.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 | 7c8773723200 |
children | fee60f17ebac |
comparison
equal
deleted
inserted
replaced
3027:ff5bcb12ae60 | 3028:ab2696e34d29 |
---|---|
16 # GNU Affero General Public License for more details. | 16 # GNU Affero General Public License for more details. |
17 | 17 |
18 # You should have received a copy of the GNU Affero General Public License | 18 # You should have received a copy of the GNU Affero General Public License |
19 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | 20 |
21 import base | 21 from . import base |
22 from collections import OrderedDict | 22 from collections import OrderedDict |
23 from functools import partial | 23 from functools import partial |
24 from sat.core.i18n import _ | 24 from sat.core.i18n import _ |
25 from sat_frontends.jp.constants import Const as C | 25 from sat_frontends.jp.constants import Const as C |
26 from twisted.words.protocols.jabber import jid | 26 from twisted.words.protocols.jabber import jid |
41 | 41 |
42 def start(self): | 42 def start(self): |
43 self.host.bridge.getContacts(profile_key=self.host.profile, callback=self.gotContacts, errback=self.error) | 43 self.host.bridge.getContacts(profile_key=self.host.profile, callback=self.gotContacts, errback=self.error) |
44 | 44 |
45 def error(self, failure): | 45 def error(self, failure): |
46 print (_("Error while retrieving the contacts [%s]") % failure) | 46 print((_("Error while retrieving the contacts [%s]") % failure)) |
47 self.host.quit(1) | 47 self.host.quit(1) |
48 | 48 |
49 def ask_confirmation(self, no_sub, no_from, no_to): | 49 def ask_confirmation(self, no_sub, no_from, no_to): |
50 """Ask the confirmation before removing contacts. | 50 """Ask the confirmation before removing contacts. |
51 | 51 |
53 @param no_from (list[unicode]): list of contacts with no 'from' subscription | 53 @param no_from (list[unicode]): list of contacts with no 'from' subscription |
54 @param no_to (list[unicode]): list of contacts with no 'to' subscription | 54 @param no_to (list[unicode]): list of contacts with no 'to' subscription |
55 @return bool | 55 @return bool |
56 """ | 56 """ |
57 if no_sub: | 57 if no_sub: |
58 print "There's no subscription between profile [%s] and the following contacts:" % self.host.profile | 58 print("There's no subscription between profile [%s] and the following contacts:" % self.host.profile) |
59 print " " + "\n ".join(no_sub) | 59 print(" " + "\n ".join(no_sub)) |
60 if no_from: | 60 if no_from: |
61 print "There's no 'from' subscription between profile [%s] and the following contacts:" % self.host.profile | 61 print("There's no 'from' subscription between profile [%s] and the following contacts:" % self.host.profile) |
62 print " " + "\n ".join(no_from) | 62 print(" " + "\n ".join(no_from)) |
63 if no_to: | 63 if no_to: |
64 print "There's no 'to' subscription between profile [%s] and the following contacts:" % self.host.profile | 64 print("There's no 'to' subscription between profile [%s] and the following contacts:" % self.host.profile) |
65 print " " + "\n ".join(no_to) | 65 print(" " + "\n ".join(no_to)) |
66 message = "REMOVE them from profile [%s]'s roster" % self.host.profile | 66 message = "REMOVE them from profile [%s]'s roster" % self.host.profile |
67 while True: | 67 while True: |
68 res = raw_input("%s (y/N)? " % message) | 68 res = input("%s (y/N)? " % message) |
69 if not res or res.lower() == 'n': | 69 if not res or res.lower() == 'n': |
70 return False | 70 return False |
71 if res.lower() == 'y': | 71 if res.lower() == 'y': |
72 return True | 72 return True |
73 | 73 |
85 elif self.args.no_from: | 85 elif self.args.no_from: |
86 no_from.append(contact) | 86 no_from.append(contact) |
87 elif not to and self.args.no_to: | 87 elif not to and self.args.no_to: |
88 no_to.append(contact) | 88 no_to.append(contact) |
89 if not no_sub and not no_from and not no_to: | 89 if not no_sub and not no_from and not no_to: |
90 print "Nothing to do - there's a from and/or to subscription(s) between profile [%s] and each of its contacts" % self.host.profile | 90 print("Nothing to do - there's a from and/or to subscription(s) between profile [%s] and each of its contacts" % self.host.profile) |
91 elif self.ask_confirmation(no_sub, no_from, no_to): | 91 elif self.ask_confirmation(no_sub, no_from, no_to): |
92 for contact in no_sub + no_from + no_to: | 92 for contact in no_sub + no_from + no_to: |
93 self.host.bridge.delContact(contact, profile_key=self.host.profile, callback=lambda __: None, errback=lambda failure: None) | 93 self.host.bridge.delContact(contact, profile_key=self.host.profile, callback=lambda __: None, errback=lambda failure: None) |
94 self.host.quit() | 94 self.host.quit() |
95 | 95 |
105 | 105 |
106 def start(self): | 106 def start(self): |
107 self.host.bridge.getContacts(profile_key=self.host.profile, callback=self.gotContacts, errback=self.error) | 107 self.host.bridge.getContacts(profile_key=self.host.profile, callback=self.gotContacts, errback=self.error) |
108 | 108 |
109 def error(self, failure): | 109 def error(self, failure): |
110 print (_("Error while retrieving the contacts [%s]") % failure) | 110 print((_("Error while retrieving the contacts [%s]") % failure)) |
111 self.host.quit(1) | 111 self.host.quit(1) |
112 | 112 |
113 def gotContacts(self, contacts): | 113 def gotContacts(self, contacts): |
114 """Process the list of contacts. | 114 """Process the list of contacts. |
115 | 115 |
133 if groups: | 133 if groups: |
134 unique_groups.update(groups) | 134 unique_groups.update(groups) |
135 total_group_subscription += len(groups) | 135 total_group_subscription += len(groups) |
136 if not groups: | 136 if not groups: |
137 no_group += 1 | 137 no_group += 1 |
138 hosts = OrderedDict(sorted(hosts.items(), key=lambda item:-item[1])) | 138 hosts = OrderedDict(sorted(list(hosts.items()), key=lambda item:-item[1])) |
139 | 139 |
140 print | 140 print() |
141 print "Total number of contacts: %d" % len(contacts) | 141 print("Total number of contacts: %d" % len(contacts)) |
142 print "Number of different hosts: %d" % len(hosts) | 142 print("Number of different hosts: %d" % len(hosts)) |
143 print | 143 print() |
144 for host, count in hosts.iteritems(): | 144 for host, count in hosts.items(): |
145 print "Contacts on {host}: {count} ({rate:.1f}%)".format(host=host, count=count, rate=100 * float(count) / len(contacts)) | 145 print("Contacts on {host}: {count} ({rate:.1f}%)".format(host=host, count=count, rate=100 * float(count) / len(contacts))) |
146 print | 146 print() |
147 print "Contacts with no 'from' subscription: %d" % no_from | 147 print("Contacts with no 'from' subscription: %d" % no_from) |
148 print "Contacts with no 'to' subscription: %d" % no_to | 148 print("Contacts with no 'to' subscription: %d" % no_to) |
149 print "Contacts with no subscription at all: %d" % no_sub | 149 print("Contacts with no subscription at all: %d" % no_sub) |
150 print | 150 print() |
151 print "Total number of groups: %d" % len(unique_groups) | 151 print("Total number of groups: %d" % len(unique_groups)) |
152 try: | 152 try: |
153 contacts_per_group = float(total_group_subscription) / len(unique_groups) | 153 contacts_per_group = float(total_group_subscription) / len(unique_groups) |
154 except ZeroDivisionError: | 154 except ZeroDivisionError: |
155 contacts_per_group = 0 | 155 contacts_per_group = 0 |
156 print "Average contacts per group: {:.1f}".format(contacts_per_group) | 156 print("Average contacts per group: {:.1f}".format(contacts_per_group)) |
157 try: | 157 try: |
158 groups_per_contact = float(total_group_subscription) / len(contacts) | 158 groups_per_contact = float(total_group_subscription) / len(contacts) |
159 except ZeroDivisionError: | 159 except ZeroDivisionError: |
160 groups_per_contact = 0 | 160 groups_per_contact = 0 |
161 print "Average groups' subscriptions per contact: {:.1f}".format(groups_per_contact) | 161 print("Average groups' subscriptions per contact: {:.1f}".format(groups_per_contact)) |
162 print "Contacts not assigned to any group: %d" % no_group | 162 print("Contacts not assigned to any group: %d" % no_group) |
163 self.host.quit() | 163 self.host.quit() |
164 | 164 |
165 | 165 |
166 class Get(base.CommandBase): | 166 class Get(base.CommandBase): |
167 | 167 |
176 | 176 |
177 def start(self): | 177 def start(self): |
178 self.host.bridge.getContacts(profile_key=self.host.profile, callback=self.gotContacts, errback=self.error) | 178 self.host.bridge.getContacts(profile_key=self.host.profile, callback=self.gotContacts, errback=self.error) |
179 | 179 |
180 def error(self, failure): | 180 def error(self, failure): |
181 print (_("Error while retrieving the contacts [%s]") % failure) | 181 print((_("Error while retrieving the contacts [%s]") % failure)) |
182 self.host.quit(1) | 182 self.host.quit(1) |
183 | 183 |
184 def gotContacts(self, contacts): | 184 def gotContacts(self, contacts): |
185 """Process the list of contacts. | 185 """Process the list of contacts. |
186 | 186 |
198 if self.args.subscriptions: | 198 if self.args.subscriptions: |
199 args.append("ask" if C.bool(attrs["ask"]) else "") | 199 args.append("ask" if C.bool(attrs["ask"]) else "") |
200 args.append("from" if C.bool(attrs["from"]) else "") | 200 args.append("from" if C.bool(attrs["from"]) else "") |
201 args.append("to" if C.bool(attrs["to"]) else "") | 201 args.append("to" if C.bool(attrs["to"]) else "") |
202 if self.args.name: | 202 if self.args.name: |
203 args.append(unicode(attrs.get("name", ""))) | 203 args.append(str(attrs.get("name", ""))) |
204 if self.args.groups: | 204 if self.args.groups: |
205 args.append(u"\t".join(groups) if groups else "") | 205 args.append("\t".join(groups) if groups else "") |
206 print u";".join(["{}"] * field_count).format(*args).encode("utf-8") | 206 print(";".join(["{}"] * field_count).format(*args).encode("utf-8")) |
207 self.host.quit() | 207 self.host.quit() |
208 | 208 |
209 | 209 |
210 class Resync(base.CommandBase): | 210 class Resync(base.CommandBase): |
211 | 211 |
212 def __init__(self, host): | 212 def __init__(self, host): |
213 super(Resync, self).__init__( | 213 super(Resync, self).__init__( |
214 host, 'resync', help=_(u'do a full resynchronisation of roster with server')) | 214 host, 'resync', help=_('do a full resynchronisation of roster with server')) |
215 self.need_loop = True | 215 self.need_loop = True |
216 | 216 |
217 def add_parser_options(self): | 217 def add_parser_options(self): |
218 pass | 218 pass |
219 | 219 |
220 def rosterResyncCb(self): | 220 def rosterResyncCb(self): |
221 self.disp(_(u"Roster resynchronized")) | 221 self.disp(_("Roster resynchronized")) |
222 self.host.quit(C.EXIT_OK) | 222 self.host.quit(C.EXIT_OK) |
223 | 223 |
224 def start(self): | 224 def start(self): |
225 self.host.bridge.rosterResync(profile_key=self.host.profile, | 225 self.host.bridge.rosterResync(profile_key=self.host.profile, |
226 callback=self.rosterResyncCb, | 226 callback=self.rosterResyncCb, |
227 errback=partial( | 227 errback=partial( |
228 self.errback, | 228 self.errback, |
229 msg=_(u"can't resynchronise roster: {}"), | 229 msg=_("can't resynchronise roster: {}"), |
230 exit_code=C.EXIT_BRIDGE_ERRBACK, | 230 exit_code=C.EXIT_BRIDGE_ERRBACK, |
231 )) | 231 )) |
232 | 232 |
233 | 233 |
234 class Roster(base.CommandBase): | 234 class Roster(base.CommandBase): |