From 99831bf0c780c94b27454032bb8abfc4c9dba5bd Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Fri, 2 Apr 2021 19:27:25 +0200 Subject: [PATCH] Fix compatibility with all versions of websocket-client, regardless of the list of arguments required by the callbacks (either ws as a first argument or not) --- platypush/backend/music/mopidy.py | 14 +++++++---- platypush/backend/todoist.py | 10 ++++---- platypush/backend/trello.py | 28 ++++++++++++++-------- platypush/plugins/media/kodi.py | 8 ++++--- platypush/plugins/websocket.py | 40 +++++++++++++++---------------- setup.py | 2 +- 6 files changed, 58 insertions(+), 44 deletions(-) diff --git a/platypush/backend/music/mopidy.py b/platypush/backend/music/mopidy.py index 161fbd5ccf..f31905b5ed 100644 --- a/platypush/backend/music/mopidy.py +++ b/platypush/backend/music/mopidy.py @@ -117,7 +117,8 @@ class MusicMopidyBackend(Backend): } def _on_msg(self): - def hndl(ws, msg): + def hndl(*args): + msg = args[1] if len(args) > 1 else args[0] msg = json.loads(msg) event = msg.get('event') if not event: @@ -213,14 +214,17 @@ class MusicMopidyBackend(Backend): self._reconnect_thread.start() def _on_error(self): - def hndl(ws, error): + def hndl(*args): + error = args[1] if len(args) > 1 else args[0] + ws = args[0] if len(args) > 1 else None self.logger.warning('Mopidy websocket error: {}'.format(error)) - ws.close() + if ws: + ws.close() return hndl def _on_close(self): - def hndl(ws): + def hndl(*_): self._connected_event.clear() self._ws = None self.logger.warning('Mopidy websocket connection closed') @@ -231,7 +235,7 @@ class MusicMopidyBackend(Backend): return hndl def _on_open(self): - def hndl(ws): + def hndl(*_): self._connected_event.set() self.logger.info('Mopidy websocket connected') diff --git a/platypush/backend/todoist.py b/platypush/backend/todoist.py index b4cb86885e..ef8ec74b03 100644 --- a/platypush/backend/todoist.py +++ b/platypush/backend/todoist.py @@ -50,8 +50,8 @@ class TodoistBackend(Backend): self._event_handled = False def _on_msg(self): - # noinspection PyUnusedLocal - def hndl(ws, msg): + def hndl(*args): + msg = args[1] if len(args) > 1 else args[0] msg = json.loads(msg) if msg.get('type') == 'sync_needed': self._refresh_all() @@ -68,15 +68,15 @@ class TodoistBackend(Backend): time.sleep(10) def _on_error(self): - # noinspection PyUnusedLocal - def hndl(ws, error): + def hndl(*args): + error = args[1] if len(args) > 1 else args[0] self.logger.warning('Todoist websocket error: {}'.format(error)) self._retry_hndl() return hndl def _on_close(self): - def hndl(*_, **__): + def hndl(*_): self.logger.info('Todoist websocket closed') self._retry_hndl() diff --git a/platypush/backend/trello.py b/platypush/backend/trello.py index 293065fd32..2f3b88f270 100644 --- a/platypush/backend/trello.py +++ b/platypush/backend/trello.py @@ -57,7 +57,9 @@ class TrelloBackend(Backend): for b in boards: b = self._plugin.get_board(b).board + # noinspection PyUnresolvedReferences self._boards_by_id[b.id] = b + # noinspection PyUnresolvedReferences self._boards_by_name[b.name] = b self.url = self._websocket_url_base.format(token=self.token) @@ -79,8 +81,13 @@ class TrelloBackend(Backend): self.logger.info('Trello boards subscribed') def _on_msg(self): - # noinspection PyUnusedLocal - def hndl(ws: WebSocketApp, msg): + def hndl(*args): + if len(args) < 2: + self.logger.warning('Missing websocket argument - make sure that you are using ' + 'a version of websocket-client < 0.53.0 or >= 0.58.0') + return + + ws, msg = args[:2] if not msg: # Reply back with an empty message when the server sends an empty message ws.send('') @@ -89,8 +96,8 @@ class TrelloBackend(Backend): # noinspection PyBroadException try: msg = json.loads(msg) - except: - self.logger.warning('Received invalid JSON message from Trello: {}'.format(msg)) + except Exception as e: + self.logger.warning('Received invalid JSON message from Trello: {}: {}'.format(msg, e)) return if 'error' in msg: @@ -141,15 +148,14 @@ class TrelloBackend(Backend): return hndl def _on_error(self): - # noinspection PyUnusedLocal - def hndl(ws: WebSocketApp, error): + def hndl(*args): + error = args[1] if len(args) > 1 else args[0] self.logger.warning('Trello websocket error: {}'.format(error)) return hndl def _on_close(self): - # noinspection PyUnusedLocal - def hndl(ws: WebSocketApp): + def hndl(*_): self.logger.warning('Trello websocket connection closed') self._connected.clear() self._req_id = 0 @@ -166,9 +172,11 @@ class TrelloBackend(Backend): def _on_open(self): # noinspection PyUnusedLocal - def hndl(ws: WebSocketApp): + def hndl(*args): + ws = args[0] if args else None self._connected.set() - self._send(ws, {'type': 'ping'}) + if ws: + self._send(ws, {'type': 'ping'}) self.logger.info('Trello websocket connected') return hndl diff --git a/platypush/plugins/media/kodi.py b/platypush/plugins/media/kodi.py index d7f6fe65b3..27dda49548 100644 --- a/platypush/plugins/media/kodi.py +++ b/platypush/plugins/media/kodi.py @@ -100,7 +100,8 @@ class MediaKodiPlugin(MediaPlugin): bus.post(evt_type(player=self.host, plugin='media.kodi', **evt)) def _on_ws_msg(self): - def hndl(ws, msg): + def hndl(*args): + msg = args[1] if len(args) > 1 else args[0] self.logger.info("Received Kodi message: {}".format(msg)) msg = json.loads(msg) method = msg.get('method') @@ -129,12 +130,13 @@ class MediaKodiPlugin(MediaPlugin): return hndl def _on_ws_error(self): - def hndl(ws, error): + def hndl(*args): + error = args[1] if len(args) > 1 else args[0] self.logger.warning("Kodi websocket connection error: {}".format(error)) return hndl def _on_ws_close(self): - def hndl(ws): + def hndl(*_): self._ws = None self.logger.warning("Kodi websocket connection closed") time.sleep(5) diff --git a/platypush/plugins/websocket.py b/platypush/plugins/websocket.py index 561e740ca5..2a29a33697 100644 --- a/platypush/plugins/websocket.py +++ b/platypush/plugins/websocket.py @@ -1,6 +1,4 @@ -import asyncio import json -import os import websockets from platypush.context import get_or_create_event_loop @@ -18,30 +16,30 @@ class WebsocketPlugin(Plugin): * **websockets** (``pip install websockets``) """ - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + def __init__(self, **kwargs): + super().__init__(**kwargs) @action - def send(self, url, msg, ssl_cert=None, ssl_key=None, ssl_cafile=None, - ssl_capath=None, *args, **kwargs): + def send(self, url, msg, ssl_cert=None, ssl_key=None, ssl_cafile=None, ssl_capath=None): """ Sends a message to a websocket. :param url: Websocket URL, e.g. ws://localhost:8765 or wss://localhost:8765 - :type topic: str + :type url: str :param msg: Message to be sent. It can be a list, a dict, or a Message object - :param ssl_cert: Path to the SSL certificate to be used, if the SSL connection requires client authentication as well (default: None) - :type ssl_cert: str + :param ssl_cert: Path to the SSL certificate to be used, if the SSL connection requires client authentication + as well (default: None) :type ssl_cert: str - :param ssl_key: Path to the SSL key to be used, if the SSL connection requires client authentication as well (default: None) - :type ssl_key: str + :param ssl_key: Path to the SSL key to be used, if the SSL connection requires client authentication as well + (default: None) :type ssl_key: str :param ssl_cafile: Path to the certificate authority file if required by the SSL configuration (default: None) :type ssl_cafile: str - :param ssl_capath: Path to the certificate authority directory if required by the SSL configuration (default: None) + :param ssl_capath: Path to the certificate authority directory if required by the SSL configuration + (default: None) :type ssl_capath: str """ @@ -56,19 +54,21 @@ class WebsocketPlugin(Plugin): async with websockets.connect(url, **websocket_args) as websocket: try: await websocket.send(str(msg)) - except websockets.exceptions.ConnectionClosed: + except websockets.exceptions.ConnectionClosed as err: self.logger.warning('Error on websocket {}: {}'. - format(url, e)) + format(url, err)) - try: msg = json.dumps(msg) - except: pass + try: + msg = json.dumps(msg) + except Exception as e: + self.logger.debug(e) - try: msg = Message.build(json.loads(msg)) - except: pass + try: + msg = Message.build(json.loads(msg)) + except Exception as e: + self.logger.debug(e) loop = get_or_create_event_loop() loop.run_until_complete(send()) - # vim:sw=4:ts=4:et: - diff --git a/setup.py b/setup.py index 138eda8f73..045a2d0422 100755 --- a/setup.py +++ b/setup.py @@ -74,7 +74,7 @@ setup( # Support for Kafka backend and plugin 'kafka': ['kafka-python'], # Support for Pushbullet backend and plugin - 'pushbullet': ['pushbullet.py @ https://github.com/rbrcsk/pushbullet.py/tarball/master'], + 'pushbullet': ['pushbullet.py @ https://github.com/BlackLight/pushbullet.py/tarball/master'], # Support for HTTP backend 'http': ['flask', 'frozendict', 'bcrypt'], # Support for uWSGI HTTP backend