From e85efe985fdb7140466d74de474c85933684f360 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Tue, 21 Apr 2020 00:02:45 +0900 Subject: [PATCH] Add a test case for #631 with possible solutions for it --- integration_tests/rtm/test_rtm_client.py | 138 +++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/integration_tests/rtm/test_rtm_client.py b/integration_tests/rtm/test_rtm_client.py index 5f55839f5..867286aa2 100644 --- a/integration_tests/rtm/test_rtm_client.py +++ b/integration_tests/rtm/test_rtm_client.py @@ -4,6 +4,7 @@ import os import threading import time +import traceback import unittest import psutil @@ -199,3 +200,140 @@ async def send_reply_async(**payload): await asyncio.sleep(5) self.assertLess(TestRTMClient.cpu_usage, 30, "Too high CPU usage detected") self.assertEqual(self.call_count, 3, "The RTM handler failed") + + # ----------------------- + # Issue #631 + # https://github.com/slackapi/python-slackclient/issues/631 + # ----------------------- + + @pytest.mark.skip() # TODO: this issue needs to be fixed + def test_issue_631_sharing_event_loop(self): + self.success = None + self.text = "This message was sent to verify issue #631" + + self.loop = asyncio.get_event_loop() + self.rtm_client = RTMClient( + token=self.bot_token, + run_async=False, # even though run_async=False, handlers for RTM events can be a coroutine + loop=self.loop, + ) + + # @RTMClient.run_on(event="message") + # def send_reply(**payload): + # self.logger.debug(payload) + # data = payload['data'] + # web_client = payload['web_client'] + # web_client._event_loop = self.loop + # # Maybe you will also need the following line uncommented + # # web_client.run_async = True + # + # if self.text in data['text']: + # channel_id = data['channel'] + # thread_ts = data['ts'] + # try: + # self.success = web_client.chat_postMessage( + # channel=channel_id, + # text="Thanks!", + # thread_ts=thread_ts + # ) + # except Exception as e: + # # slack.rtm.client:client.py:446 When calling '#send_reply()' + # # in the 'test_rtm_client' module the following error was raised: This event loop is already running + # self.logger.error(traceback.format_exc()) + # raise e + + # Solution (1) for #631 + @RTMClient.run_on(event="message") + # even though run_async=False, handlers for RTM events can be a coroutine + async def send_reply(**payload): + self.logger.debug(payload) + data = payload['data'] + web_client = payload['web_client'] + web_client._event_loop = self.loop + + try: + if "text" in data and self.text in data["text"]: + channel_id = data['channel'] + thread_ts = data['ts'] + self.success = await web_client.chat_postMessage( + channel=channel_id, + text="Thanks!", + thread_ts=thread_ts + ) + except Exception as e: + self.logger.error(traceback.format_exc()) + raise e + + def connect(): + self.logger.debug("Starting RTM Client...") + self.rtm_client.start() + + t = threading.Thread(target=connect) + t.setDaemon(True) + t.start() + + try: + self.assertIsNone(self.success) + time.sleep(5) + + self.web_client = WebClient( + token=self.bot_token, + run_async=False, + loop=asyncio.new_event_loop(), # TODO: this doesn't work without this + ) + new_message = self.web_client.chat_postMessage(channel=self.channel_id, text=self.text) + self.assertFalse("error" in new_message) + + time.sleep(5) + self.assertIsNotNone(self.success) + finally: + t.join(.3) + + # Solution (2) for #631 + @pytest.mark.skip("this is just for your reference") + @async_test + async def test_issue_631_sharing_event_loop_async(self): + self.loop = asyncio.get_event_loop() + self.success = None + self.text = "This message was sent to verify issue #631" + + self.rtm_client = RTMClient( + token=self.bot_token, + run_async=True, # To turn this on, the test method needs to be an async function + @async_test decorator + ) + + @RTMClient.run_on(event="message") + async def send_reply(**payload): + self.logger.debug(payload) + data = payload['data'] + web_client = payload['web_client'] + web_client._event_loop = self.loop + + try: + if "text" in data and self.text in data["text"]: + channel_id = data['channel'] + thread_ts = data['ts'] + self.success = await web_client.chat_postMessage( + channel=channel_id, + text="Thanks!", + thread_ts=thread_ts + ) + except Exception as e: + self.logger.error(traceback.format_exc()) + raise e + + # intentionally not waiting here + self.rtm_client.start() + + self.assertIsNone(self.success) + await asyncio.sleep(5) + + self.web_client = WebClient( + token=self.bot_token, + run_async=True, # all need to be async here + ) + new_message = await self.web_client.chat_postMessage(channel=self.channel_id, text=self.text) + self.assertFalse("error" in new_message) + + await asyncio.sleep(5) + self.assertIsNotNone(self.success)