From be4a8f062afa8e5cfd885abc28e0900ffca841d2 Mon Sep 17 00:00:00 2001 From: Era Dorta Date: Wed, 11 Dec 2024 16:16:30 +0100 Subject: [PATCH] fix: make Command an abstract class (#68) This ensures that a explicit NotImpletedError is raised if `handle` is not implemented, instead of a empty named exception. --- signalbot/command.py | 6 ++++-- signalbot/utils/__init__.py | 2 ++ signalbot/utils/chat_testing.py | 7 ++++++- tests/test_bot.py | 17 +++++++++++------ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/signalbot/command.py b/signalbot/command.py index 1dd53e8..f23b15a 100644 --- a/signalbot/command.py +++ b/signalbot/command.py @@ -1,4 +1,5 @@ import functools +from abc import ABC, abstractmethod from .message import Message from .context import Context @@ -27,7 +28,7 @@ async def wrapper_triggered(*args, **kwargs): return decorator_triggered -class Command: +class Command(ABC): # optional def setup(self): pass @@ -37,8 +38,9 @@ def describe(self) -> str: return None # overwrite + @abstractmethod async def handle(self, context: Context): - raise NotImplementedError + pass # helper method # deprecated: please use @triggered diff --git a/signalbot/utils/__init__.py b/signalbot/utils/__init__.py index 4acc72f..30ffabf 100644 --- a/signalbot/utils/__init__.py +++ b/signalbot/utils/__init__.py @@ -1,5 +1,6 @@ from .chat_testing import ( ChatTestCase, + DummyCommand, SendMessagesMock, ReceiveMessagesMock, ReactMessageMock, @@ -8,6 +9,7 @@ __all__ = [ "ChatTestCase", + "DummyCommand", "SendMessagesMock", "ReceiveMessagesMock", "ReactMessageMock", diff --git a/signalbot/utils/chat_testing.py b/signalbot/utils/chat_testing.py index c0aed90..50ec5be 100644 --- a/signalbot/utils/chat_testing.py +++ b/signalbot/utils/chat_testing.py @@ -6,7 +6,7 @@ import aiohttp from unittest.mock import AsyncMock, MagicMock -from ..bot import SignalBot +from ..bot import SignalBot, Command, Context from unittest.mock import patch @@ -131,3 +131,8 @@ def _extract_responses(self): for args in self.call_args_list: results.append(args[0]) return results + + +class DummyCommand(Command): + async def handle(self, context: Context): + pass diff --git a/tests/test_bot.py b/tests/test_bot.py index 545c659..7e44f6f 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -2,6 +2,8 @@ import asyncio from unittest.mock import patch, AsyncMock from signalbot import SignalBot, Command, SignalAPI +from signalbot.context import Context +from signalbot.utils import DummyCommand class BotTestCase(unittest.IsolatedAsyncioTestCase): @@ -35,8 +37,8 @@ async def test_produce(self, mock): ) self.signal_bot.listen(TestProducer.group_id, TestProducer.internal_id) # Any two commands - self.signal_bot.register(Command()) - self.signal_bot.register(Command()) + self.signal_bot.register(DummyCommand()) + self.signal_bot.register(DummyCommand()) await self.signal_bot._produce(1337) @@ -99,13 +101,13 @@ def test_listen_valid_invalid_phone_number(self): class TestRegisterCommand(BotTestCase): def test_register_one_command(self): - self.signal_bot.register(Command()) + self.signal_bot.register(DummyCommand()) self.assertEqual(len(self.signal_bot.commands), 1) def test_register_three_commands(self): - self.signal_bot.register(Command()) - self.signal_bot.register(Command()) - self.signal_bot.register(Command()) + self.signal_bot.register(DummyCommand()) + self.signal_bot.register(DummyCommand()) + self.signal_bot.register(DummyCommand()) self.assertEqual(len(self.signal_bot.commands), 3) def test_register_calls_setup_of_command(self): @@ -116,6 +118,9 @@ def __init__(self): def setup(self): self.state = True + def handle(self, context: Context): + pass + cmd = SomeTestCommand() self.assertEqual(cmd.state, False)