From: Christian Heller Date: Mon, 6 Oct 2025 19:29:47 +0000 (+0200) Subject: Refactor IrcConnException hierarchy. X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/todo?a=commitdiff_plain;h=44091b046fb8e827695af0aab8c1f601ee17419d;p=ircplom Refactor IrcConnException hierarchy. --- diff --git a/src/ircplom/client.py b/src/ircplom/client.py index fd05bf9..141b59e 100644 --- a/src/ircplom/client.py +++ b/src/ircplom/client.py @@ -13,9 +13,8 @@ from uuid import UUID, uuid4 from ircplom.events import ( AffectiveEvent, CrashingException, ExceptionEvent, QueueMixin) from ircplom.irc_conn import ( - BaseIrcConnection, IrcConnAbortException, IrcConnException, - IrcConnTimeoutException, IrcMessage, ILLEGAL_NICK_CHARS, - ILLEGAL_NICK_FIRSTCHARS, ISUPPORT_DEFAULTS, PORT_SSL) + BaseIrcConnection, IrcConnException, IrcMessage, ERR_STR_TIMEOUT, + ILLEGAL_NICK_CHARS, ILLEGAL_NICK_FIRSTCHARS, ISUPPORT_DEFAULTS, PORT_SSL) from ircplom.msg_parse_expectations import MSG_EXPECTATIONS @@ -861,7 +860,7 @@ class Client(ABC, ClientQueueMixin): def _on_connecting_exception(self, e: IrcConnException) -> None: self.db.connection_state = f'failed to connect: {e}' - if isinstance(e, IrcConnTimeoutException): + if e.retry: if not self._retry_connect_in_s > 0: self._retry_connect_in_s = 1 self._delayed_retry_connect() @@ -902,20 +901,20 @@ class Client(ABC, ClientQueueMixin): self._delayed_retry_connect() def on_handled_loop_exception(self, e: IrcConnException) -> None: - 'On …AbortException, call .close(), on …Timeout… first (!) try PING.' - if isinstance(e, IrcConnAbortException): - self._retry_connect_in_s = 1 + 'Execute e.abort, .retry, or interpret str(e) to PING/check on PONG.' + if e.abort: + if e.retry: + self._retry_connect_in_s = 1 self.db.connection_state = f'broken: {e}' self.close() - elif isinstance(e, IrcConnTimeoutException): + elif str(e) == ERR_STR_TIMEOUT: if self._expected_pong: self.on_handled_loop_exception( - IrcConnAbortException('no timely PONG from server')) + IrcConnException('no timely PONG from server', + abort=True, retry=True)) else: self._expected_pong = "what's up?" self.send('PING', self._expected_pong) - else: - raise e @abstractmethod def _on_update(self, *path) -> None: diff --git a/src/ircplom/irc_conn.py b/src/ircplom/irc_conn.py index 2605e94..9e74bd2 100644 --- a/src/ircplom/irc_conn.py +++ b/src/ircplom/irc_conn.py @@ -15,6 +15,8 @@ _TIMEOUT_PING = 120 _TIMEOUT_CONNECT = 5 _CONN_RECV_BUFSIZE = 1024 +ERR_STR_TIMEOUT = 'timeout' + ILLEGAL_NICK_CHARS = ' ,*?!@' ILLEGAL_NICK_FIRSTCHARS = ':$' ISUPPORT_DEFAULTS = { @@ -130,16 +132,16 @@ class IrcMessage: return self._raw -class IrcConnException(BaseException): +class IrcConnException(Exception): 'Thrown by BaseIrcConnection on expectable connection issues.' + def __init__(self, *args, abort=True, retry=False, **kwargs) -> None: + super().__init__(*args, **kwargs) + self.abort = abort + self.retry = retry -class IrcConnAbortException(IrcConnException): - 'Thrown by BaseIrcConnection on expectable connection failures.' - - -class IrcConnTimeoutException(IrcConnException): - 'Thrown by BaseIrcConnection if recv timeout triggered.' + def __str__(self) -> str: + return str(self.__cause__) if not self.args else ' '.join(self.args) class BaseIrcConnection(QueueMixin, ABC): @@ -160,9 +162,9 @@ class BaseIrcConnection(QueueMixin, ABC): try: self._socket.connect((hostname, port)) except TimeoutError as e: - raise IrcConnTimeoutException(e) from e + raise IrcConnException(retry=True) from e except socket_gaierror as e: - raise IrcConnAbortException(e) from e + raise IrcConnException() from e self._socket.settimeout(_TIMEOUT_RECV_LOOP) def close(self) -> None: @@ -191,20 +193,20 @@ class BaseIrcConnection(QueueMixin, ABC): while True: try: bytes_new = self._socket.recv(_CONN_RECV_BUFSIZE) - except TimeoutError as e: + except TimeoutError: if (datetime.now() - time_last_ping_check).seconds\ > _TIMEOUT_PING: time_last_ping_check = datetime.now() yield self._on_handled_loop_exception( - IrcConnTimeoutException(e)) + IrcConnException(ERR_STR_TIMEOUT, abort=False)) else: yield None continue except ConnectionResetError as e: - raise IrcConnAbortException(e) from e + raise IrcConnException(retry=True) from e except OSError as e: if e.errno == 9: - raise IrcConnAbortException(e) from e + raise IrcConnException(retry=True) from e raise e if not bytes_new: break diff --git a/src/ircplom/testing.py b/src/ircplom/testing.py index b3ecd3e..ad63e37 100644 --- a/src/ircplom/testing.py +++ b/src/ircplom/testing.py @@ -7,8 +7,7 @@ from typing import Callable, Generator, Iterator, Optional from ircplom.events import Event, Loop, QueueMixin from ircplom.client import IrcConnection, IrcConnSetup from ircplom.client_tui import ClientKnowingTui, ClientTui, LOG_PREFIX_IN -from ircplom.irc_conn import (IrcConnAbortException, IrcConnTimeoutException, - IrcMessage) +from ircplom.irc_conn import ERR_STR_TIMEOUT, IrcConnException, IrcMessage from ircplom.tui_base import (TerminalInterface, TuiEvent, LOG_FMT_SEP, LOG_FMT_ATTRS) @@ -69,7 +68,7 @@ class _FakeIrcConnection(IrcConnection): def _set_up_socket(self, hostname: str, port: int) -> None: if port > _FAKE_TIMEOUT_PORTS_BEYOND: - raise IrcConnTimeoutException('FAKE TESTING TIMEOUT') + raise IrcConnException('FAKE TESTING TIMEOUT', retry=True) def close(self) -> None: self._recv_loop.stop() @@ -87,12 +86,12 @@ class _FakeIrcConnection(IrcConnection): continue if msg == 'FAKE_IRC_CONN_TIMEOUT_EXCEPTION': yield self._on_handled_loop_exception( - IrcConnTimeoutException(msg)) + IrcConnException(ERR_STR_TIMEOUT, abort=False)) continue if msg == 'FAKE_IRC_CONN_ABORT_EXCEPTION': - raise IrcConnAbortException(msg) + raise IrcConnException(msg, retry=True) yield self._make_recv_event(IrcMessage.from_raw(msg)) - except IrcConnAbortException as e: + except IrcConnException as e: yield self._on_handled_loop_exception(e)