From 0df56d840a766a6100e986d3bb7044071fe002f4 Mon Sep 17 00:00:00 2001 From: Perso Date: Sun, 21 Feb 2021 18:48:45 +0100 Subject: [PATCH 1/2] add first test for app client --- app/app_client.py | 6 ++++++ main.py | 8 ++++---- tests/discord_app_test.py | 9 +++++++++ tests/stubs/discord_client_stub.py | 6 ++++++ 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 app/app_client.py create mode 100644 tests/discord_app_test.py create mode 100644 tests/stubs/discord_client_stub.py diff --git a/app/app_client.py b/app/app_client.py new file mode 100644 index 0000000..aec9b85 --- /dev/null +++ b/app/app_client.py @@ -0,0 +1,6 @@ +class AppClient(): + def __init__(self, bot_client): + self._bot_client = bot_client + + def start(self): + self._bot_client.start() diff --git a/main.py b/main.py index af72152..6a3171d 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,12 @@ from os import environ, path from dotenv import load_dotenv from app.discord_client import DiscordClient - +from app.app_client import AppClient if environ.get("BOT_ENV") == "development": basedir = path.dirname(__file__) load_dotenv(path.join(basedir, '.env.development')) - -client = DiscordClient(environ.get("DISCORD_BOT_SECRET_KEY")) -client.run() +discord_client = DiscordClient(environ.get("DISCORD_BOT_SECRET_KEY")) +app = AppClient(discord_client) +app.start() diff --git a/tests/discord_app_test.py b/tests/discord_app_test.py new file mode 100644 index 0000000..24a216f --- /dev/null +++ b/tests/discord_app_test.py @@ -0,0 +1,9 @@ +from app.app_client import AppClient +from stubs.discord_client_stub import DiscordClientStub + + +def test_app_run_bot_client_on_start(): + discord_client_stub = DiscordClientStub() + app = AppClient(discord_client_stub) + app.start() + assert discord_client_stub.is_start == True diff --git a/tests/stubs/discord_client_stub.py b/tests/stubs/discord_client_stub.py new file mode 100644 index 0000000..51ea6cf --- /dev/null +++ b/tests/stubs/discord_client_stub.py @@ -0,0 +1,6 @@ +class DiscordClientStub(): + def __init__(self): + self.is_start = False + + def start(self): + self.is_start = True From 0a1335dc416f8e34a1126d557aa4bc87d26f4015 Mon Sep 17 00:00:00 2001 From: Perso Date: Fri, 26 Feb 2021 19:26:39 +0100 Subject: [PATCH 2/2] add domain event, event_bus, subscribers --- .pylintrc | 2 +- app/__init__.py | 0 app/app_client.py | 18 ++++++++++++-- app/discord_client.py | 9 ++++++- app/domain/event/message_received_event.py | 5 ++++ app/shared/event/event.py | 3 +++ app/shared/event/event_bus.py | 29 ++++++++++++++++++++++ app/shared/event/event_logger.py | 13 ++++++++++ main.py | 11 ++++++-- requirements.txt | 1 + tests/discord_app_test.py | 24 ++++++++++++++++-- tests/stubs/discord_client_stub.py | 8 ++++-- tests/stubs/in_memory_event_logger.py | 13 ++++++++++ 13 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 app/__init__.py create mode 100644 app/domain/event/message_received_event.py create mode 100644 app/shared/event/event.py create mode 100644 app/shared/event/event_bus.py create mode 100644 app/shared/event/event_logger.py create mode 100644 tests/stubs/in_memory_event_logger.py diff --git a/.pylintrc b/.pylintrc index 5d12340..149e62f 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,3 +1,3 @@ [pylint] good-names = id -min-public-methods = 1 +min-public-methods = 0 diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/app_client.py b/app/app_client.py index aec9b85..ad99363 100644 --- a/app/app_client.py +++ b/app/app_client.py @@ -1,6 +1,20 @@ +from domain.event.message_received_event import MessageReceivedEvent + + class AppClient(): - def __init__(self, bot_client): + def __init__(self, bot_client, event_bus): self._bot_client = bot_client + self.event_bus = event_bus + + self.event_bus.subscribe(self) def start(self): - self._bot_client.start() + self._bot_client.run() + + async def on_receive_event(self, event): + if isinstance(event, MessageReceivedEvent): + print("yolo") + + @staticmethod + def subscribed_to(): + return [MessageReceivedEvent] diff --git a/app/discord_client.py b/app/discord_client.py index 3def8d7..2cef4e8 100644 --- a/app/discord_client.py +++ b/app/discord_client.py @@ -1,10 +1,17 @@ import discord +from domain.event.message_received_event import MessageReceivedEvent class DiscordClient(): - def __init__(self, bot_secret_key): + def __init__(self, bot_secret_key, event_bus): self._client = discord.Client() self._bot_secret_key = bot_secret_key + self.event_bus = event_bus + + self._client.on_message = self.on_message def run(self): self._client.run(self._bot_secret_key) + + async def on_message(self, _message): + await self.event_bus.publish(MessageReceivedEvent()) diff --git a/app/domain/event/message_received_event.py b/app/domain/event/message_received_event.py new file mode 100644 index 0000000..5fdde99 --- /dev/null +++ b/app/domain/event/message_received_event.py @@ -0,0 +1,5 @@ +from shared.event.event import Event + + +class MessageReceivedEvent(Event): + pass diff --git a/app/shared/event/event.py b/app/shared/event/event.py new file mode 100644 index 0000000..4ddf6dc --- /dev/null +++ b/app/shared/event/event.py @@ -0,0 +1,3 @@ +class Event(): + def __init__(self, payload=None): + self.payload = payload diff --git a/app/shared/event/event_bus.py b/app/shared/event/event_bus.py new file mode 100644 index 0000000..d8b0e84 --- /dev/null +++ b/app/shared/event/event_bus.py @@ -0,0 +1,29 @@ +class EventBus(): + def __init__(self): + self._subscribers = {} + + async def publish(self, event): + event_classes = [x for x in list( + map(lambda x: x.__name__, type(event).mro())) if x != 'object'] + + subscribers = [] + for event_class in event_classes: + if not event_class in self._subscribers.keys(): + continue + subscribers += self._subscribers[event_class] + + if not subscribers: + return + + for subscriber in subscribers: + await subscriber.on_receive_event(event) + + def subscribe(self, subscriber): + subscribed_events = list( + map(lambda event_class: event_class.__name__, subscriber.subscribed_to())) + + for event_class_name in subscribed_events: + if not event_class_name in self._subscribers.keys(): + self._subscribers[event_class_name] = [] + + self._subscribers[event_class_name].append(subscriber) diff --git a/app/shared/event/event_logger.py b/app/shared/event/event_logger.py new file mode 100644 index 0000000..f7fb92a --- /dev/null +++ b/app/shared/event/event_logger.py @@ -0,0 +1,13 @@ +from event import Event + + +class EventLogger(): + def __init__(self): + pass + + async def on_receive_event(self, event): + print("Received event", type(event).__name__) + + @staticmethod + def subscribed_to(): + return [Event] diff --git a/main.py b/main.py index 6a3171d..aafe444 100644 --- a/main.py +++ b/main.py @@ -2,11 +2,18 @@ from dotenv import load_dotenv from app.discord_client import DiscordClient from app.app_client import AppClient +from app.shared.event.event_bus import EventBus +from app.shared.event.event_logger import EventLogger if environ.get("BOT_ENV") == "development": basedir = path.dirname(__file__) load_dotenv(path.join(basedir, '.env.development')) -discord_client = DiscordClient(environ.get("DISCORD_BOT_SECRET_KEY")) -app = AppClient(discord_client) +event_bus = EventBus() +event_logger = EventLogger() +event_bus.subscribe(event_logger) + +discord_client = DiscordClient( + environ.get("DISCORD_BOT_SECRET_KEY"), event_bus) +app = AppClient(discord_client, event_bus) app.start() diff --git a/requirements.txt b/requirements.txt index 2d7c18c..9ff6af8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,6 +24,7 @@ pylama==7.7.1 pylint==2.6.2 pyparsing==2.4.7 pytest==6.2.2 +pytest-asyncio==0.14.0 pytest-mock==3.5.1 python-dateutil==2.8.1 python-dotenv==0.15.0 diff --git a/tests/discord_app_test.py b/tests/discord_app_test.py index 24a216f..95d29fd 100644 --- a/tests/discord_app_test.py +++ b/tests/discord_app_test.py @@ -1,9 +1,29 @@ from app.app_client import AppClient from stubs.discord_client_stub import DiscordClientStub +from app.shared.event.event_bus import EventBus +from app.domain.event.message_received_event import MessageReceivedEvent +from stubs.in_memory_event_logger import InMemoryEventLogger + + +import pytest def test_app_run_bot_client_on_start(): - discord_client_stub = DiscordClientStub() - app = AppClient(discord_client_stub) + event_bus = EventBus() + discord_client_stub = DiscordClientStub(event_bus) + app = AppClient(discord_client_stub, event_bus) app.start() assert discord_client_stub.is_start == True + + +@pytest.mark.asyncio +async def test_app_receive_event_from_bot_client(): + event_bus = EventBus() + discord_client_stub = DiscordClientStub(event_bus) + event_logger = InMemoryEventLogger() + event_bus.subscribe(event_logger) + app = AppClient(discord_client_stub, event_bus) + app.start() + + await discord_client_stub.trigger_event(MessageReceivedEvent()) + assert len(event_logger.events), 1 diff --git a/tests/stubs/discord_client_stub.py b/tests/stubs/discord_client_stub.py index 51ea6cf..78d2b5d 100644 --- a/tests/stubs/discord_client_stub.py +++ b/tests/stubs/discord_client_stub.py @@ -1,6 +1,10 @@ class DiscordClientStub(): - def __init__(self): + def __init__(self, event_bus): self.is_start = False + self._event_bus = event_bus - def start(self): + def run(self): self.is_start = True + + async def trigger_event(self, event): + await self._event_bus.publish(event) diff --git a/tests/stubs/in_memory_event_logger.py b/tests/stubs/in_memory_event_logger.py new file mode 100644 index 0000000..4dae9d3 --- /dev/null +++ b/tests/stubs/in_memory_event_logger.py @@ -0,0 +1,13 @@ +from app.shared.event.event import Event + + +class InMemoryEventLogger(): + def __init__(self): + self.events = [] + + async def on_receive_event(self, event): + self.events.append(event) + + @staticmethod + def subscribed_to(): + return [Event]