home · contact · privacy
Allow for exceptions that crash app but explain some more details.
authorChristian Heller <c.heller@plomlompom.de>
Thu, 14 Aug 2025 12:14:07 +0000 (14:14 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 14 Aug 2025 12:14:07 +0000 (14:14 +0200)
ircplom/client.py
ircplom/events.py

index 3eea8865bef9121b0ddc9fdd43211f7079fc5178..5aa87bbf9b42ab5080c24d553279d3745f3facce 100644 (file)
@@ -8,7 +8,8 @@ from getpass import getuser
 from threading import Thread
 from typing import Any, Callable, NamedTuple, Optional
 # ourselves
-from ircplom.events import AffectiveEvent, ExceptionEvent, QueueMixin
+from ircplom.events import (
+        AffectiveEvent, CrashingException, ExceptionEvent, QueueMixin)
 from ircplom.irc_conn import (BaseIrcConnection, IrcConnAbortException,
                               IrcMessage, PORT_SSL)
 
@@ -195,7 +196,7 @@ class ClientDb:
         if value is None:
             if old_value is None:
                 if confirm:
-                    raise Exception
+                    raise CrashingException('called to unset non-set entry')
                 del self._dict[key]
         elif value_changed:
             self._dict[key] = value
@@ -218,7 +219,7 @@ class ClientDb:
         elif targeted is None:
             self._dict[key] = [value]
         else:
-            raise Exception
+            raise CrashingException('called on non-list entry')
 
     def get_force(self, key: str) -> tuple[Optional[int | str | list[str]],
                                            bool]:
@@ -273,8 +274,9 @@ class Client(ABC, ClientQueueMixin):
                 self._client_trigger('_on_connect')
             except IrcConnAbortException as e:
                 self._log(f'failed to connect: {e}', alert=True)
+            # catch _all_ just so they exit readably with the main loop
             except Exception as e:  # pylint: disable=broad-exception-caught
-                self._put(ExceptionEvent(e))
+                self._put(ExceptionEvent(CrashingException(e)))
 
         self._log('connecting …', conn_setup=self._db.conn_setup)
         Thread(target=connect, daemon=True, args=(self,)).start()
index bdb1b0d7f107f486bedcc3cd4645da816f0352db..9dac06b2e0468a8dd17a1e39c5505053ada7a6b2 100644 (file)
@@ -49,10 +49,14 @@ class AffectiveEvent(Event, ABC):
         return wrap()(t_method=t_method, **kwargs)
 
 
+class CrashingException(BaseException):
+    'To explicitly crash, because it should never happen, but explaining why.'
+
+
 @dataclass
 class ExceptionEvent(Event):
     'To deliver Exception to main loop for handling.'
-    exception: Exception
+    exception: CrashingException
 
 
 @dataclass
@@ -101,5 +105,6 @@ class Loop(QueueMixin):
                     break
                 if it_yield is not None:
                     self._put(it_yield)
+        # catch _all_ just so they exit readably with the main loop
         except Exception as e:  # pylint: disable=broad-exception-caught
-            self._put(ExceptionEvent(e))
+            self._put(ExceptionEvent(CrashingException(e)))