Mercurial > libervia-backend
comparison sat/plugins/plugin_misc_android.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 | 758bee45612b |
children | f91d0e6d9b13 |
comparison
equal
deleted
inserted
replaced
3027:ff5bcb12ae60 | 3028:ab2696e34d29 |
---|---|
1 #!/usr/bin/env python2 | 1 #!/usr/bin/env python3 |
2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
3 | 3 |
4 # SAT plugin for file tansfer | 4 # SAT plugin for file tansfer |
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) | 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
6 | 6 |
34 | 34 |
35 PLUGIN_INFO = { | 35 PLUGIN_INFO = { |
36 C.PI_NAME: "Android ", | 36 C.PI_NAME: "Android ", |
37 C.PI_IMPORT_NAME: "android", | 37 C.PI_IMPORT_NAME: "android", |
38 C.PI_TYPE: C.PLUG_TYPE_MISC, | 38 C.PI_TYPE: C.PLUG_TYPE_MISC, |
39 C.PI_RECOMMENDATIONS: [u"XEP-0352"], | 39 C.PI_RECOMMENDATIONS: ["XEP-0352"], |
40 C.PI_MAIN: "AndroidPlugin", | 40 C.PI_MAIN: "AndroidPlugin", |
41 C.PI_HANDLER: "no", | 41 C.PI_HANDLER: "no", |
42 C.PI_DESCRIPTION: D_( | 42 C.PI_DESCRIPTION: D_( |
43 """Manage Android platform specificities, like pause or notifications""" | 43 """Manage Android platform specificities, like pause or notifications""" |
44 ), | 44 ), |
45 } | 45 } |
46 | 46 |
47 if sys.platform != "android": | 47 if sys.platform != "android": |
48 raise exceptions.CancelError(u"this module is not needed on this platform") | 48 raise exceptions.CancelError("this module is not needed on this platform") |
49 | 49 |
50 | 50 |
51 from plyer import notification, vibrator | 51 from plyer import notification, vibrator |
52 from plyer.platforms.android import activity | 52 from plyer.platforms.android import activity |
53 from jnius import autoclass | 53 from jnius import autoclass |
58 #: quickly on an other app. | 58 #: quickly on an other app. |
59 CSI_DELAY = 30 | 59 CSI_DELAY = 30 |
60 | 60 |
61 PARAM_VIBRATE_CATEGORY = "Notifications" | 61 PARAM_VIBRATE_CATEGORY = "Notifications" |
62 PARAM_VIBRATE_NAME = "vibrate" | 62 PARAM_VIBRATE_NAME = "vibrate" |
63 PARAM_VIBRATE_LABEL = D_(u"Vibrate on notifications") | 63 PARAM_VIBRATE_LABEL = D_("Vibrate on notifications") |
64 SOCKET_DIR = "/data/data/org.salutatoi.cagou/" | 64 SOCKET_DIR = "/data/data/org.salutatoi.cagou/" |
65 SOCKET_FILE = ".socket" | 65 SOCKET_FILE = ".socket" |
66 STATE_RUNNING = "running" | 66 STATE_RUNNING = "running" |
67 STATE_PAUSED = "paused" | 67 STATE_PAUSED = "paused" |
68 STATE_STOPPED = "stopped" | 68 STATE_STOPPED = "stopped" |
99 with tempfile.TemporaryFile() as f: | 99 with tempfile.TemporaryFile() as f: |
100 f.write(b'1234567890') | 100 f.write(b'1234567890') |
101 f.seek(0, os.SEEK_END) | 101 f.seek(0, os.SEEK_END) |
102 size = f.tell() | 102 size = f.tell() |
103 if size == 10: | 103 if size == 10: |
104 log.info(u"seek() bug not present anymore, workaround code can be removed") | 104 log.info("seek() bug not present anymore, workaround code can be removed") |
105 else: | 105 else: |
106 log.warning(u"seek() bug detected, applying a workaround") | 106 log.warning("seek() bug detected, applying a workaround") |
107 web_client.FileBodyProducer._determineLength = determineLength_workaround | 107 web_client.FileBodyProducer._determineLength = determineLength_workaround |
108 | 108 |
109 patch_seek_bug() | 109 patch_seek_bug() |
110 | 110 |
111 | 111 |
116 | 116 |
117 def dataReceived(self, data): | 117 def dataReceived(self, data): |
118 if data in STATES: | 118 if data in STATES: |
119 self.android_plugin.state = data | 119 self.android_plugin.state = data |
120 else: | 120 else: |
121 log.warning(u"Unexpected data: {data}".format(data=data)) | 121 log.warning("Unexpected data: {data}".format(data=data)) |
122 | 122 |
123 | 123 |
124 class FrontendStateFactory(protocol.Factory): | 124 class FrontendStateFactory(protocol.Factory): |
125 | 125 |
126 def __init__(self, android_plugin): | 126 def __init__(self, android_plugin): |
147 param_name=PARAM_VIBRATE_NAME, | 147 param_name=PARAM_VIBRATE_NAME, |
148 param_label=PARAM_VIBRATE_LABEL, | 148 param_label=PARAM_VIBRATE_LABEL, |
149 ) | 149 ) |
150 | 150 |
151 def __init__(self, host): | 151 def __init__(self, host): |
152 log.info(_(u"plugin Android initialization")) | 152 log.info(_("plugin Android initialization")) |
153 self.host = host | 153 self.host = host |
154 self._csi = host.plugins.get(u'XEP-0352') | 154 self._csi = host.plugins.get('XEP-0352') |
155 self._csi_timer = None | 155 self._csi_timer = None |
156 host.memory.updateParams(self.params) | 156 host.memory.updateParams(self.params) |
157 try: | 157 try: |
158 os.mkdir(SOCKET_DIR, 0700) | 158 os.mkdir(SOCKET_DIR, 0o700) |
159 except OSError as e: | 159 except OSError as e: |
160 if e.errno == 17: | 160 if e.errno == 17: |
161 # dir already exists | 161 # dir already exists |
162 pass | 162 pass |
163 else: | 163 else: |
186 # "XXX has no attribute 'invoke'" error (looks like the same issue as | 186 # "XXX has no attribute 'invoke'" error (looks like the same issue as |
187 # https://github.com/kivy/pyjnius/issues/59) | 187 # https://github.com/kivy/pyjnius/issues/59) |
188 self.br = BroadcastReceiver( | 188 self.br = BroadcastReceiver( |
189 callback=lambda *args, **kwargs: reactor.callLater(0, | 189 callback=lambda *args, **kwargs: reactor.callLater(0, |
190 self.onConnectivityChange), | 190 self.onConnectivityChange), |
191 actions=[u"android.net.conn.CONNECTIVITY_CHANGE"]) | 191 actions=["android.net.conn.CONNECTIVITY_CHANGE"]) |
192 self.br.start() | 192 self.br.start() |
193 | 193 |
194 | 194 |
195 @property | 195 @property |
196 def state(self): | 196 def state(self): |
197 return self._state | 197 return self._state |
198 | 198 |
199 @state.setter | 199 @state.setter |
200 def state(self, new_state): | 200 def state(self, new_state): |
201 log.debug(u"frontend state has changed: {state}".format(state=new_state)) | 201 log.debug("frontend state has changed: {state}".format(state=new_state)) |
202 previous_state = self._state | 202 previous_state = self._state |
203 self._state = new_state | 203 self._state = new_state |
204 if new_state == STATE_RUNNING: | 204 if new_state == STATE_RUNNING: |
205 self._onRunning(previous_state) | 205 self._onRunning(previous_state) |
206 elif new_state == STATE_PAUSED: | 206 elif new_state == STATE_PAUSED: |
231 - there is a message and it is not a groupchat | 231 - there is a message and it is not a groupchat |
232 - message is not coming from ourself | 232 - message is not coming from ourself |
233 """ | 233 """ |
234 if (mess_data["message"] and mess_data["type"] != C.MESS_TYPE_GROUPCHAT | 234 if (mess_data["message"] and mess_data["type"] != C.MESS_TYPE_GROUPCHAT |
235 and not mess_data["from"].userhostJID() == client.jid.userhostJID()): | 235 and not mess_data["from"].userhostJID() == client.jid.userhostJID()): |
236 message = mess_data["message"].itervalues().next() | 236 message = next(iter(mess_data["message"].values())) |
237 try: | 237 try: |
238 subject = mess_data["subject"].itervalues().next() | 238 subject = next(iter(mess_data["subject"].values())) |
239 except StopIteration: | 239 except StopIteration: |
240 subject = u"Cagou new message" | 240 subject = "Cagou new message" |
241 | 241 |
242 notification.notify(title=subject, message=message) | 242 notification.notify(title=subject, message=message) |
243 if self.host.memory.getParamA( | 243 if self.host.memory.getParamA( |
244 PARAM_VIBRATE_NAME, PARAM_VIBRATE_CATEGORY, profile_key=client.profile | 244 PARAM_VIBRATE_NAME, PARAM_VIBRATE_CATEGORY, profile_key=client.profile |
245 ): | 245 ): |
246 try: | 246 try: |
247 vibrator.vibrate() | 247 vibrator.vibrate() |
248 except Exception as e: | 248 except Exception as e: |
249 # FIXME: vibrator is currently not working, | 249 # FIXME: vibrator is currently not working, |
250 # cf. https://github.com/kivy/plyer/issues/509 | 250 # cf. https://github.com/kivy/plyer/issues/509 |
251 log.warning(u"Can't use vibrator: {e}".format(e=e)) | 251 log.warning("Can't use vibrator: {e}".format(e=e)) |
252 return mess_data | 252 return mess_data |
253 | 253 |
254 def messageReceivedTrigger(self, client, message_elt, post_treat): | 254 def messageReceivedTrigger(self, client, message_elt, post_treat): |
255 if not self.cagou_active: | 255 if not self.cagou_active: |
256 # we only send notification is the frontend is not displayed | 256 # we only send notification is the frontend is not displayed |
304 elif net_type_android == ConnectivityManager.TYPE_MOBILE: | 304 elif net_type_android == ConnectivityManager.TYPE_MOBILE: |
305 net_type = NET_TYPE_MOBILE | 305 net_type = NET_TYPE_MOBILE |
306 else: | 306 else: |
307 net_type = NET_TYPE_OTHER | 307 net_type = NET_TYPE_OTHER |
308 if net_type != self._net_type: | 308 if net_type != self._net_type: |
309 log.info(u"connectivity has changed") | 309 log.info("connectivity has changed") |
310 previous = self._net_type | 310 previous = self._net_type |
311 self._net_type = net_type | 311 self._net_type = net_type |
312 if net_type == NET_TYPE_NONE: | 312 if net_type == NET_TYPE_NONE: |
313 log.info(u"no network active") | 313 log.info("no network active") |
314 elif net_type == NET_TYPE_WIFI: | 314 elif net_type == NET_TYPE_WIFI: |
315 log.info(u"WIFI activated") | 315 log.info("WIFI activated") |
316 elif net_type == NET_TYPE_MOBILE: | 316 elif net_type == NET_TYPE_MOBILE: |
317 log.info(u"mobile data activated") | 317 log.info("mobile data activated") |
318 else: | 318 else: |
319 log.info(u"network activated (type={net_type_android})" | 319 log.info("network activated (type={net_type_android})" |
320 .format(net_type_android=net_type_android)) | 320 .format(net_type_android=net_type_android)) |
321 self._handleNetworkChange(previous, net_type) | 321 self._handleNetworkChange(previous, net_type) |
322 else: | 322 else: |
323 log.debug(u"_checkConnectivity called without network change ({net_type})" | 323 log.debug("_checkConnectivity called without network change ({net_type})" |
324 .format(net_type = net_type)) | 324 .format(net_type = net_type)) |
325 | 325 |
326 | 326 |
327 def onConnectivityChange(self): | 327 def onConnectivityChange(self): |
328 log.debug(u"onConnectivityChange called") | 328 log.debug("onConnectivityChange called") |
329 self._checkConnectivity() | 329 self._checkConnectivity() |