From 774e755d4a4fb985548cd3d17703c1f700687ff3 Mon Sep 17 00:00:00 2001 From: kaliko Date: Sat, 2 Oct 2021 13:09:01 +0200 Subject: [PATCH] Some refactoring around Exceptions --- sima/core.py | 3 --- sima/lib/http.py | 12 ++++++------ sima/lib/meta.py | 5 ++++- sima/lib/simadb.py | 3 ++- sima/lib/simafm.py | 6 +++--- sima/mpdclient.py | 29 +++++++++++++++++------------ sima/plugins/internal/tags.py | 4 ++-- sima/utils/filelock.py | 2 +- sima/utils/utils.py | 8 ++++---- 9 files changed, 39 insertions(+), 33 deletions(-) diff --git a/sima/core.py b/sima/core.py index eb01031..83c5e91 100644 --- a/sima/core.py +++ b/sima/core.py @@ -129,9 +129,6 @@ class Sima(Daemon): except PlayerError as err: self.log.debug(err) continue - except PlayerError as err: - # TODO: unhandled Player exceptions - self.log.warning('Unhandled player exception: %s', err) self.log.info('Got reconnected') break self.foreach_plugin('start') diff --git a/sima/lib/http.py b/sima/lib/http.py index 949b306..3b27bdd 100644 --- a/sima/lib/http.py +++ b/sima/lib/http.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2014-2015, 2020 kaliko +# Copyright (c) 2014-2015, 2020, 2021 kaliko # Copyright (c) 2012, 2013 Eric Larson # # This program is free software: you can redistribute it and/or modify @@ -26,7 +26,7 @@ import time import email.utils -from requests import Session, Request, Timeout, ConnectionError +from requests import Session, Request, Timeout, ConnectionError as HTTPConnectionError from sima import SOCKET_TIMEOUT, WAIT_BETWEEN_REQUESTS from sima.utils.utils import WSError, WSTimeout, WSHTTPError, Throttle @@ -293,11 +293,11 @@ class HttpClient: return cached_response try: return self.fetch_ws(req) - except Timeout: + except Timeout as err: raise WSTimeout('Failed to reach server within {0}s'.format( - SOCKET_TIMEOUT)) - except ConnectionError as err: - raise WSError(err) + SOCKET_TIMEOUT)) from err + except HTTPConnectionError as err: + raise WSError(err) from err @Throttle(WAIT_BETWEEN_REQUESTS) def fetch_ws(self, prepreq): diff --git a/sima/lib/meta.py b/sima/lib/meta.py index f118e82..4ff5601 100644 --- a/sima/lib/meta.py +++ b/sima/lib/meta.py @@ -26,6 +26,9 @@ from collections.abc import Set import logging import re +from ..utils.utils import MPDSimaException + + UUID_RE = r'^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[89AB][a-f0-9]{3}-[a-f0-9]{12}$' #: The Track Object is collapsing multiple tags into a single string using this # separator. It is used then to split back the string to tags list. @@ -44,7 +47,7 @@ def is_uuid4(uuid): return False -class MetaException(Exception): +class MetaException(MPDSimaException): """Generic Meta Exception""" diff --git a/sima/lib/simadb.py b/sima/lib/simadb.py index 75119aa..f3c1a09 100644 --- a/sima/lib/simadb.py +++ b/sima/lib/simadb.py @@ -33,9 +33,10 @@ from datetime import timezone from sima.lib.meta import Artist, Album from sima.lib.track import Track +from sima.utils.utils import MPDSimaException -class SimaDBError(Exception): +class SimaDBError(MPDSimaException): """ Exceptions. """ diff --git a/sima/lib/simafm.py b/sima/lib/simafm.py index bd203f7..bdfd02d 100644 --- a/sima/lib/simafm.py +++ b/sima/lib/simafm.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2009-2014 kaliko +# Copyright (c) 2009-2014, 2021 kaliko # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -101,9 +101,9 @@ class SimaFM: ans = self.http(self.root_url, payload) try: ans.json() - except ValueError: + except ValueError as err: # Corrupted/malformed cache? cf. gitlab issue #35 - raise WSError('Malformed json, try purging the cache: %s') + raise WSError('Malformed json, try purging the cache: %s') from err self._controls_answer(ans.json()) # pylint: disable=no-member # Artist might be found but return no 'artist' list… # cf. "Mulatu Astatqe" vs. "Mulatu Astatqé" with autocorrect=0 diff --git a/sima/mpdclient.py b/sima/mpdclient.py index 1347edd..53a62d0 100644 --- a/sima/mpdclient.py +++ b/sima/mpdclient.py @@ -23,7 +23,7 @@ from logging import getLogger from select import select # external module -from musicpd import MPDClient, MPDError as PlayerError +from musicpd import MPDClient, MPDError # local import @@ -31,6 +31,11 @@ from .lib.meta import Meta, Artist, Album from .lib.track import Track from .lib.simastr import SimaStr from .utils.leven import levenshtein_ratio +from .utils.utils import MPDSimaException + + +class PlayerError(MPDSimaException): + """Fatal error in the player.""" # Some decorators @@ -124,7 +129,7 @@ class MPD(MPDClient): return tracks_wrapper(super().__getattr__(cmd)) return super().__getattr__(cmd) except OSError as err: - raise PlayerError(err) + raise PlayerError(err) from err def disconnect(self): """Overriding explicitly MPDClient.disconnect()""" @@ -144,19 +149,19 @@ class MPD(MPDClient): # Catch socket errors except OSError as err: raise PlayerError('Could not connect to "%s:%s": %s' % - (host, port, err.strerror)) + (host, port, err.strerror)) from err # Catch all other possible errors # ConnectionError and ProtocolError are always fatal. Others may not # be, but we don't know how to handle them here, so treat them as if # they are instead of ignoring them. - except PlayerError as err: + except MPDError as err: raise PlayerError('Could not connect to "%s:%s": %s' % - (host, port, err)) + (host, port, err)) from err if password: try: self.password(password) - except (PlayerError, OSError) as err: - raise PlayerError("Could not connect to '%s': %s" % (host, err)) + except (MPDError, OSError) as err: + raise PlayerError("Could not connect to '%s': %s" % (host, err)) from err # Controls we have sufficient rights available_cmd = self.commands() for cmd in MPD.needed_cmds: @@ -244,11 +249,11 @@ class MPD(MPDClient): if 'database' in ret: self._reset_cache() return ret - else: - try: # noidle cmd does not go through __getattr__, need to catch OSError then - self.noidle() - except OSError as err: - raise PlayerError(err) + # Nothing to read, canceling idle + try: # noidle cmd does not go through __getattr__, need to catch OSError then + self.noidle() + except OSError as err: + raise PlayerError(err) from err def clean(self): """Clean blocking event (idle) and pending commands diff --git a/sima/plugins/internal/tags.py b/sima/plugins/internal/tags.py index 5e5d08c..39ac0ea 100644 --- a/sima/plugins/internal/tags.py +++ b/sima/plugins/internal/tags.py @@ -117,9 +117,9 @@ class Tags(AdvancedPlugin): if self.plugin_conf['filter']: # Use window to limit response size self.player.find(self.plugin_conf['filter'], "window", (0, 1)) - except CommandError: + except CommandError as err: raise PluginException('Badly formated filter in tags plugin configuration: "%s"' - % self.plugin_conf['filter']) + % self.plugin_conf['filter']) from err def callback_need_track(self): candidates = [] diff --git a/sima/utils/filelock.py b/sima/utils/filelock.py index 959f636..31df146 100644 --- a/sima/utils/filelock.py +++ b/sima/utils/filelock.py @@ -65,7 +65,7 @@ class FileLock: if err.errno != errno.EEXIST: raise if (time.time() - start_time) >= self.timeout: - raise FileLockException('Timeout occured.') + raise FileLockException('Timeout occured.') from err time.sleep(self.delay) self.is_locked = True diff --git a/sima/utils/utils.py b/sima/utils/utils.py index d226ef0..83799e0 100644 --- a/sima/utils/utils.py +++ b/sima/utils/utils.py @@ -100,10 +100,6 @@ def exception_log(): sys.exit(1) -class SigHup(Exception): - """SIGHUP raises this Exception""" - - # ArgParse Callbacks class Obsolete(Action): # pylint: disable=R0903 @@ -193,6 +189,10 @@ class MPDSimaException(Exception): """Generic MPD_sima Exception""" +class SigHup(MPDSimaException): + """SIGHUP raises this Exception""" + + # http client exceptions (for webservices) class WSError(MPDSimaException): pass -- 2.39.2