aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2023-09-18 17:44:12 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2023-09-18 17:44:12 +0200
commit2f2b51e40c7027d80bf4a6741f2063e2c224f938 (patch)
treed9558ede8f4615bb6d86c50360524b15f7ddf63f
parenta68565accffba8590bc539fb937a1adfcf7891ab (diff)
downloadgeldschieberbot-2f2b51e40c7027d80bf4a6741f2063e2c224f938.tar.gz
geldschieberbot-2f2b51e40c7027d80bf4a6741f2063e2c224f938.zip
make Geldschieberbot a context manager
Previosuly there was the problem that the state was saved when the bot object was destructed. When there was an unhandled exception it was possible for the builtins to be cleanedup before the bot's destructor was executed resulting in yet another exception because the open builtin was no longer available. This is no longer possible when the bot is used as a context manager python guarantees that the __exit__ code is executed before leaving the with block. This allows us prevent the state from beeing saved when there was an exception to prevent invalid states.
-rw-r--r--geldschieberbot.py11
-rwxr-xr-xsingle_shot.py35
-rwxr-xr-xtest.py4
3 files changed, 26 insertions, 24 deletions
diff --git a/geldschieberbot.py b/geldschieberbot.py
index 046d543..ff859f0 100644
--- a/geldschieberbot.py
+++ b/geldschieberbot.py
@@ -1009,8 +1009,6 @@ class Geldschieberbot:
self.dry_run = dry_run # Run without changing the stored state
self.record_changes = True # Should changes be recorded
- self.load_state()
-
# Command dispatch table
self.cmds = {
'reg': self.register,
@@ -1046,8 +1044,13 @@ class Geldschieberbot:
'thanks': self.thanks,
}
- def __del__(self):
- self.save_state()
+ def __enter__(self):
+ self.load_state()
+ return self
+
+ def __exit__(self, exc_type, exc_value, exc_tb):
+ if not exc_type:
+ self.save_state()
def enable_dry_run(self) -> bool:
"""Enable dry run"""
diff --git a/single_shot.py b/single_shot.py
index 41d9849..0c85947 100755
--- a/single_shot.py
+++ b/single_shot.py
@@ -80,24 +80,23 @@ def main():
if not group_id:
die('A group id must be provided')
- bot = Geldschieberbot(state_path, group_id, dry_run=args.dry_run)
-
- # Read cmds from stdin
- for line in sys.stdin.read().splitlines():
- try:
- envelope = json.loads(line)['envelope']
- except json.JSONDecodeError:
- print(datetime.now(), line, "not valid json")
- continue
-
- quote = None
- if not args.no_quote:
- quote = Quote(timestamp=envelope['timestamp'],
- author=envelope['source'])
-
- send(send_cmd, bot.handle(envelope), quote)
-
- send(send_cmd, bot.run_scheduled_cmds())
+ with Geldschieberbot(state_path, group_id, dry_run=args.dry_run) as bot:
+ # Read cmds from stdin
+ for line in sys.stdin.read().splitlines():
+ try:
+ envelope = json.loads(line)['envelope']
+ except json.JSONDecodeError:
+ print(datetime.now(), line, "not valid json")
+ continue
+
+ quote = None
+ if not args.no_quote:
+ quote = Quote(timestamp=envelope['timestamp'],
+ author=envelope['source'])
+
+ send(send_cmd, bot.handle(envelope), quote)
+
+ send(send_cmd, bot.run_scheduled_cmds())
if __name__ == "__main__":
diff --git a/test.py b/test.py
index f392a4d..8535485 100755
--- a/test.py
+++ b/test.py
@@ -1417,8 +1417,8 @@ class TestStateLoadStore(unittest.TestCase):
def test_init(self):
sp = "test/state_3users.json"
- bot = Geldschieberbot(sp, DEFAULT_GROUP_ID)
- self.assertTrue(compare_state(sp, state=bot.state))
+ with Geldschieberbot(sp, DEFAULT_GROUP_ID) as bot:
+ self.assertTrue(compare_state(sp, state=bot.state))
def test_explicit_load(self):
sp = "test/state_3users.json"