From e763ad56ef2829293b493e22cde47db8644147d2 Mon Sep 17 00:00:00 2001 From: pt2302 <1553279+pt2302@users.noreply.github.com> Date: Thu, 28 Aug 2025 17:47:23 -0400 Subject: [PATCH 1/7] Refactor for modern asyncio use --- bot.py | 14 ++++---------- bot_local.py | 6 ++---- bot_test.py | 9 ++++----- web_test.py | 3 +-- 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/bot.py b/bot.py index eea6dac..4da30ab 100755 --- a/bot.py +++ b/bot.py @@ -130,8 +130,7 @@ def __init__( github_access_token, npm_token, timezone, - repos_info, - loop, + repos_info ): """ Create the slack bot @@ -143,7 +142,6 @@ def __init__( npm_token (str): The NPM token to publish npm packages timezone (tzinfo): The time zone of the team interacting with the bot repos_info (list of RepoInfo): Information about the repositories connected to channels - loop (asyncio.events.AbstractEventLoop): The asyncio event loop """ self.doof_id = doof_id self.slack_access_token = slack_access_token @@ -151,7 +149,6 @@ def __init__( self.npm_token = npm_token self.timezone = timezone self.repos_info = repos_info - self.loop = loop # Keep track of long running or scheduled tasks self.tasks = set() self.doof_boot = now_in_utc() @@ -1038,7 +1035,7 @@ async def start_new_releases(self, command_args): # pylint: disable=too-many-lo title=f"Starting release {version} with these commits", text=release_notes, ) - self.loop.create_task( + asyncio.create_task( self._new_release( repo_info=repo_info, version=version, @@ -1549,7 +1546,7 @@ async def startup(self): if not release_pr: continue - self.loop.create_task( + asyncio.create_task( self.run_release_lifecycle( repo_info=repo_info, manager=None, release_pr=release_pr ) @@ -1640,7 +1637,6 @@ async def async_main(): npm_token=envs["NPM_TOKEN"], timezone=pytz.timezone(envs["TIMEZONE"]), repos_info=repos_info, - loop=asyncio.get_event_loop(), doof_id=doof_id, ) app = make_app(secret=envs["SLACK_SECRET"], bot=bot) @@ -1651,9 +1647,7 @@ async def async_main(): def main(): """main function for bot command""" - loop = asyncio.get_event_loop() - loop.run_until_complete(async_main()) - loop.run_forever() + asyncio.run(async_main()) if __name__ == "__main__": diff --git a/bot_local.py b/bot_local.py index 9c1874f..11cdec8 100755 --- a/bot_local.py +++ b/bot_local.py @@ -48,8 +48,7 @@ async def async_main(): github_access_token=envs["GITHUB_ACCESS_TOKEN"], timezone=envs["TIMEZONE"], npm_token=envs["NPM_TOKEN"], - repos_info=repos_info, - loop=asyncio.get_event_loop(), + repos_info=repos_info ) await bot.startup() @@ -63,8 +62,7 @@ async def async_main(): def main(): """Main function""" - loop = asyncio.get_event_loop() - loop.run_until_complete(async_main()) + asyncio.run(async_main()) if __name__ == "__main__": diff --git a/bot_test.py b/bot_test.py index ad4215a..2f4056e 100644 --- a/bot_test.py +++ b/bot_test.py @@ -50,7 +50,7 @@ class DoofSpoof(Bot): """Testing bot""" - def __init__(self, *, loop): + def __init__(self): """Since the testing bot isn't contacting slack or github we don't need these tokens here""" super().__init__( doof_id="Doofenshmirtz", @@ -58,8 +58,7 @@ def __init__(self, *, loop): github_access_token=GITHUB_ACCESS, npm_token=NPM_TOKEN, timezone=pytz.timezone("America/New_York"), - repos_info=[WEB_TEST_REPO_INFO, LIBRARY_TEST_REPO_INFO], - loop=loop, + repos_info=[WEB_TEST_REPO_INFO, LIBRARY_TEST_REPO_INFO] ) self.slack_users = [] @@ -130,9 +129,9 @@ def sleep_sync_mock(mocker): @pytest.fixture -def doof(event_loop, sleep_sync_mock): # pylint: disable=unused-argument +def doof(sleep_sync_mock): # pylint: disable=unused-argument """Create a Doof""" - yield DoofSpoof(loop=event_loop) + yield DoofSpoof() @pytest.fixture diff --git a/web_test.py b/web_test.py index e425184..e079236 100644 --- a/web_test.py +++ b/web_test.py @@ -21,8 +21,7 @@ class FinishReleaseTests(AsyncHTTPTestCase): def setUp(self): self.secret = uuid.uuid4().hex - self.loop = asyncio.get_event_loop() - self.doof = DoofSpoof(loop=self.loop) + self.doof = DoofSpoof() self.app = make_app(secret=self.secret, bot=self.doof) super().setUp() From d69dc21b9f5aa915b23d14aba302ee269259e6bf Mon Sep 17 00:00:00 2001 From: pt2302 <1553279+pt2302@users.noreply.github.com> Date: Thu, 28 Aug 2025 17:49:00 -0400 Subject: [PATCH 2/7] Removing unused dependency --- web_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/web_test.py b/web_test.py index e079236..c02c480 100644 --- a/web_test.py +++ b/web_test.py @@ -1,6 +1,5 @@ """Tests for the web server""" -import asyncio import json from unittest.mock import patch import urllib.parse From c6b141d0cccf3cd9394a3b8bda12af00ebe86a45 Mon Sep 17 00:00:00 2001 From: pt2302 <1553279+pt2302@users.noreply.github.com> Date: Thu, 28 Aug 2025 17:50:26 -0400 Subject: [PATCH 3/7] Formatting --- bot.py | 2 +- bot_local.py | 2 +- bot_test.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index 4da30ab..c1d601a 100755 --- a/bot.py +++ b/bot.py @@ -130,7 +130,7 @@ def __init__( github_access_token, npm_token, timezone, - repos_info + repos_info, ): """ Create the slack bot diff --git a/bot_local.py b/bot_local.py index 11cdec8..1027fcd 100755 --- a/bot_local.py +++ b/bot_local.py @@ -48,7 +48,7 @@ async def async_main(): github_access_token=envs["GITHUB_ACCESS_TOKEN"], timezone=envs["TIMEZONE"], npm_token=envs["NPM_TOKEN"], - repos_info=repos_info + repos_info=repos_info, ) await bot.startup() diff --git a/bot_test.py b/bot_test.py index 2f4056e..45c542e 100644 --- a/bot_test.py +++ b/bot_test.py @@ -58,7 +58,7 @@ def __init__(self): github_access_token=GITHUB_ACCESS, npm_token=NPM_TOKEN, timezone=pytz.timezone("America/New_York"), - repos_info=[WEB_TEST_REPO_INFO, LIBRARY_TEST_REPO_INFO] + repos_info=[WEB_TEST_REPO_INFO, LIBRARY_TEST_REPO_INFO], ) self.slack_users = [] From 2f380cd88e1dc8b8a771952f715bed94505f5f29 Mon Sep 17 00:00:00 2001 From: pt2302 <1553279+pt2302@users.noreply.github.com> Date: Thu, 28 Aug 2025 17:59:04 -0400 Subject: [PATCH 4/7] Refactor to use asyncio.create_task --- web.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web.py b/web.py index 44fcf91..30b4ab2 100644 --- a/web.py +++ b/web.py @@ -2,6 +2,7 @@ Web server for handling slack webhooks """ +import asyncio import hmac import json @@ -54,7 +55,7 @@ async def post(self, *args, **kwargs): # pylint: disable=unused-argument arguments = json.loads( self.get_argument("payload") ) # pylint: disable=no-value-for-parameter - self.bot.loop.create_task(self.bot.handle_webhook(webhook_dict=arguments)) + asyncio.create_task(self.bot.handle_webhook(webhook_dict=arguments)) await self.finish("") @@ -87,7 +88,7 @@ async def post(self, *args, **kwargs): # pylint: disable=unused-argument await self.finish(challenge) return - self.bot.loop.create_task(self.bot.handle_event(webhook_dict=arguments)) + asyncio.create_task(self.bot.handle_event(webhook_dict=arguments)) await self.finish("") From 7e0668ca302db5a271a7e87b9efc39bac8320d21 Mon Sep 17 00:00:00 2001 From: pt2302 <1553279+pt2302@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:02:57 -0400 Subject: [PATCH 5/7] Pin requirements to latest versions --- requirements.txt | 14 +++++++------- test_requirements.txt | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/requirements.txt b/requirements.txt index 414cc24..201bd4b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -python-dateutil -pytz -requests -sentry-sdk -tornado -virtualenv -packaging +packaging==25.0 +python-dateutil==2.9.0.post0 +pytz==2025.2 +requests==2.32.5 +sentry-sdk==2.35.1 +tornado==6.5.2 +virtualenv==20.34.0 diff --git a/test_requirements.txt b/test_requirements.txt index 1807841..c059714 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,8 +1,8 @@ black==25.1.0 -codecov -pdbpp -pylint -pytest -pytest-asyncio -pytest-cov -pytest-mock +codecov==2.1.13 +pdbpp==0.11.7 +pylint==3.3.8 +pytest==8.4.1 +pytest-asyncio==1.1.0 +pytest-cov==6.2.1 +pytest-mock==3.14.1 From e128805a2e8eead3e6019ed4206c78a9594b781f Mon Sep 17 00:00:00 2001 From: pt2302 <1553279+pt2302@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:18:54 -0400 Subject: [PATCH 6/7] Using Tornado to run loop --- bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index c1d601a..2b75436 100755 --- a/bot.py +++ b/bot.py @@ -11,6 +11,7 @@ import pytz import sentry_sdk +import tornado from client_wrapper import ClientWrapper from constants import ( @@ -1644,10 +1645,9 @@ async def async_main(): await bot.startup() - def main(): """main function for bot command""" - asyncio.run(async_main()) + tornado.ioloop.IOLoop.current().run_sync(async_main) if __name__ == "__main__": From c18dfded064410c55d64fb0dff621231dc825423 Mon Sep 17 00:00:00 2001 From: pt2302 <1553279+pt2302@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:23:17 -0400 Subject: [PATCH 7/7] Formatting --- bot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bot.py b/bot.py index 2b75436..698989a 100755 --- a/bot.py +++ b/bot.py @@ -1645,6 +1645,7 @@ async def async_main(): await bot.startup() + def main(): """main function for bot command""" tornado.ioloop.IOLoop.current().run_sync(async_main)