diff options
28 files changed, 79 insertions, 47 deletions
diff --git a/bot/async_stats.py b/bot/async_stats.py index 58a80f528..2af832e5b 100644 --- a/bot/async_stats.py +++ b/bot/async_stats.py @@ -3,6 +3,8 @@ import socket from statsd.client.base import StatsClientBase +from bot.utils import scheduling + class AsyncStatsClient(StatsClientBase): """An async transport method for statsd communication.""" @@ -32,7 +34,7 @@ class AsyncStatsClient(StatsClientBase): def _send(self, data: str) -> None: """Start an async task to send data to statsd.""" - self._loop.create_task(self._async_send(data)) + scheduling.create_task(self._async_send(data), event_loop=self._loop) async def _async_send(self, data: str) -> None: """Send data to the statsd server using the async transport.""" diff --git a/bot/exts/backend/branding/_cog.py b/bot/exts/backend/branding/_cog.py index 0ba146635..ab0a761ff 100644 --- a/bot/exts/backend/branding/_cog.py +++ b/bot/exts/backend/branding/_cog.py @@ -17,6 +17,7 @@ from bot.bot import Bot from bot.constants import Branding as BrandingConfig, Channels, Colours, Guild, MODERATION_ROLES from bot.decorators import mock_in_debug from bot.exts.backend.branding._repository import BrandingRepository, Event, RemoteObject +from bot.utils import scheduling log = logging.getLogger(__name__) @@ -126,7 +127,7 @@ class Branding(commands.Cog): self.bot = bot self.repository = BrandingRepository(bot) - self.bot.loop.create_task(self.maybe_start_daemon()) # Start depending on cache. + scheduling.create_task(self.maybe_start_daemon(), event_loop=self.bot.loop) # Start depending on cache. # region: Internal logic & state management diff --git a/bot/exts/backend/config_verifier.py b/bot/exts/backend/config_verifier.py index d72c6c22e..c24cb324f 100644 --- a/bot/exts/backend/config_verifier.py +++ b/bot/exts/backend/config_verifier.py @@ -4,7 +4,7 @@ from discord.ext.commands import Cog from bot import constants from bot.bot import Bot - +from bot.utils import scheduling log = logging.getLogger(__name__) @@ -14,7 +14,7 @@ class ConfigVerifier(Cog): def __init__(self, bot: Bot): self.bot = bot - self.channel_verify_task = self.bot.loop.create_task(self.verify_channels()) + self.channel_verify_task = scheduling.create_task(self.verify_channels(), event_loop=self.bot.loop) async def verify_channels(self) -> None: """ diff --git a/bot/exts/backend/logging.py b/bot/exts/backend/logging.py index 823f14ea4..8f1b8026f 100644 --- a/bot/exts/backend/logging.py +++ b/bot/exts/backend/logging.py @@ -5,7 +5,7 @@ from discord.ext.commands import Cog from bot.bot import Bot from bot.constants import Channels, DEBUG_MODE - +from bot.utils import scheduling log = logging.getLogger(__name__) @@ -16,7 +16,7 @@ class Logging(Cog): def __init__(self, bot: Bot): self.bot = bot - self.bot.loop.create_task(self.startup_greeting()) + scheduling.create_task(self.startup_greeting(), event_loop=self.bot.loop) async def startup_greeting(self) -> None: """Announce our presence to the configured devlog channel.""" diff --git a/bot/exts/backend/sync/_cog.py b/bot/exts/backend/sync/_cog.py index 48d2b6f02..f88dcf538 100644 --- a/bot/exts/backend/sync/_cog.py +++ b/bot/exts/backend/sync/_cog.py @@ -9,6 +9,7 @@ from bot import constants from bot.api import ResponseCodeError from bot.bot import Bot from bot.exts.backend.sync import _syncers +from bot.utils import scheduling log = logging.getLogger(__name__) @@ -18,7 +19,7 @@ class Sync(Cog): def __init__(self, bot: Bot) -> None: self.bot = bot - self.bot.loop.create_task(self.sync_guild()) + scheduling.create_task(self.sync_guild(), event_loop=self.bot.loop) async def sync_guild(self) -> None: """Syncs the roles/users of the guild with the database.""" diff --git a/bot/exts/filters/antispam.py b/bot/exts/filters/antispam.py index 8c075fa95..6808bfa03 100644 --- a/bot/exts/filters/antispam.py +++ b/bot/exts/filters/antispam.py @@ -129,7 +129,11 @@ class AntiSpam(Cog): self.max_interval = max_interval_config['interval'] self.cache = MessageCache(AntiSpamConfig.cache_size, newest_first=True) - self.bot.loop.create_task(self.alert_on_validation_error(), name="AntiSpam.alert_on_validation_error") + scheduling.create_task( + self.alert_on_validation_error(), + name="AntiSpam.alert_on_validation_error", + event_loop=self.bot.loop, + ) @property def mod_log(self) -> ModLog: diff --git a/bot/exts/filters/filter_lists.py b/bot/exts/filters/filter_lists.py index 232c1e48b..a06437f3d 100644 --- a/bot/exts/filters/filter_lists.py +++ b/bot/exts/filters/filter_lists.py @@ -9,6 +9,7 @@ from bot.api import ResponseCodeError from bot.bot import Bot from bot.converters import ValidDiscordServerInvite, ValidFilterListType from bot.pagination import LinePaginator +from bot.utils import scheduling log = logging.getLogger(__name__) @@ -27,7 +28,7 @@ class FilterLists(Cog): def __init__(self, bot: Bot) -> None: self.bot = bot - self.bot.loop.create_task(self._amend_docstrings()) + scheduling.create_task(self._amend_docstrings(), event_loop=self.bot.loop) async def _amend_docstrings(self) -> None: """Add the valid FilterList types to the docstrings, so they'll appear in !help invocations.""" diff --git a/bot/exts/filters/filtering.py b/bot/exts/filters/filtering.py index 7e698880f..64f3b82af 100644 --- a/bot/exts/filters/filtering.py +++ b/bot/exts/filters/filtering.py @@ -21,9 +21,9 @@ from bot.constants import ( ) from bot.exts.events.code_jams._channels import CATEGORY_NAME as JAM_CATEGORY_NAME from bot.exts.moderation.modlog import ModLog +from bot.utils import scheduling from bot.utils.messages import format_user from bot.utils.regex import INVITE_RE -from bot.utils.scheduling import Scheduler log = logging.getLogger(__name__) @@ -64,7 +64,7 @@ class Filtering(Cog): def __init__(self, bot: Bot): self.bot = bot - self.scheduler = Scheduler(self.__class__.__name__) + self.scheduler = scheduling.Scheduler(self.__class__.__name__) self.name_lock = asyncio.Lock() staff_mistake_str = "If you believe this was a mistake, please let staff know!" @@ -133,7 +133,7 @@ class Filtering(Cog): }, } - self.bot.loop.create_task(self.reschedule_offensive_msg_deletion()) + scheduling.create_task(self.reschedule_offensive_msg_deletion(), event_loop=self.bot.loop) def cog_unload(self) -> None: """Cancel scheduled tasks.""" diff --git a/bot/exts/fun/duck_pond.py b/bot/exts/fun/duck_pond.py index 7f7e4585c..8ced6922c 100644 --- a/bot/exts/fun/duck_pond.py +++ b/bot/exts/fun/duck_pond.py @@ -9,6 +9,7 @@ from discord.ext.commands import Cog, Context, command from bot import constants from bot.bot import Bot from bot.converters import MemberOrUser +from bot.utils import scheduling from bot.utils.checks import has_any_role from bot.utils.messages import count_unique_users_reaction, send_attachments from bot.utils.webhooks import send_webhook @@ -24,7 +25,7 @@ class DuckPond(Cog): self.webhook_id = constants.Webhooks.duck_pond self.webhook = None self.ducked_messages = [] - self.bot.loop.create_task(self.fetch_webhook()) + scheduling.create_task(self.fetch_webhook(), event_loop=self.bot.loop) self.relay_lock = None async def fetch_webhook(self) -> None: diff --git a/bot/exts/fun/off_topic_names.py b/bot/exts/fun/off_topic_names.py index 845b8175c..2f56aa5ba 100644 --- a/bot/exts/fun/off_topic_names.py +++ b/bot/exts/fun/off_topic_names.py @@ -11,6 +11,7 @@ from bot.bot import Bot from bot.constants import Channels, MODERATION_ROLES from bot.converters import OffTopicName from bot.pagination import LinePaginator +from bot.utils import scheduling CHANNELS = (Channels.off_topic_0, Channels.off_topic_1, Channels.off_topic_2) log = logging.getLogger(__name__) @@ -50,7 +51,7 @@ class OffTopicNames(Cog): self.bot = bot self.updater_task = None - self.bot.loop.create_task(self.init_offtopic_updater()) + scheduling.create_task(self.init_offtopic_updater(), event_loop=self.bot.loop) def cog_unload(self) -> None: """Cancel any running updater tasks on cog unload.""" @@ -62,7 +63,7 @@ class OffTopicNames(Cog): await self.bot.wait_until_guild_available() if self.updater_task is None: coro = update_names(self.bot) - self.updater_task = self.bot.loop.create_task(coro) + self.updater_task = scheduling.create_task(coro, event_loop=self.bot.loop) @group(name='otname', aliases=('otnames', 'otn'), invoke_without_command=True) @has_any_role(*MODERATION_ROLES) diff --git a/bot/exts/help_channels/_cog.py b/bot/exts/help_channels/_cog.py index cfc9cf477..40fb9429c 100644 --- a/bot/exts/help_channels/_cog.py +++ b/bot/exts/help_channels/_cog.py @@ -82,7 +82,7 @@ class HelpChannels(commands.Cog): # Asyncio stuff self.queue_tasks: t.List[asyncio.Task] = [] - self.init_task = self.bot.loop.create_task(self.init_cog()) + self.init_task = scheduling.create_task(self.init_cog(), event_loop=self.bot.loop) def cog_unload(self) -> None: """Cancel the init task and scheduled tasks when the cog unloads.""" diff --git a/bot/exts/info/codeblock/_cog.py b/bot/exts/info/codeblock/_cog.py index 9a0705d2b..f63a459ff 100644 --- a/bot/exts/info/codeblock/_cog.py +++ b/bot/exts/info/codeblock/_cog.py @@ -11,7 +11,7 @@ from bot.bot import Bot from bot.exts.filters.token_remover import TokenRemover from bot.exts.filters.webhook_remover import WEBHOOK_URL_RE from bot.exts.info.codeblock._instructions import get_instructions -from bot.utils import has_lines +from bot.utils import has_lines, scheduling from bot.utils.channel import is_help_channel from bot.utils.messages import wait_for_deletion @@ -114,7 +114,7 @@ class CodeBlockCog(Cog, name="Code Block"): bot_message = await message.channel.send(f"Hey {message.author.mention}!", embed=embed) self.codeblock_message_ids[message.id] = bot_message.id - self.bot.loop.create_task(wait_for_deletion(bot_message, (message.author.id,))) + scheduling.create_task(wait_for_deletion(bot_message, (message.author.id,)), event_loop=self.bot.loop) # Increase amount of codeblock correction in stats self.bot.stats.incr("codeblock_corrections") diff --git a/bot/exts/info/doc/_batch_parser.py b/bot/exts/info/doc/_batch_parser.py index 369bb462c..51ee29b68 100644 --- a/bot/exts/info/doc/_batch_parser.py +++ b/bot/exts/info/doc/_batch_parser.py @@ -24,9 +24,10 @@ class StaleInventoryNotifier: """Handle sending notifications about stale inventories through `DocItem`s to dev log.""" def __init__(self): - self._init_task = bot.instance.loop.create_task( + self._init_task = scheduling.create_task( self._init_channel(), - name="StaleInventoryNotifier channel init" + name="StaleInventoryNotifier channel init", + event_loop=bot.instance.loop, ) self._warned_urls = set() diff --git a/bot/exts/info/doc/_cog.py b/bot/exts/info/doc/_cog.py index a2119a53d..6cc1723cd 100644 --- a/bot/exts/info/doc/_cog.py +++ b/bot/exts/info/doc/_cog.py @@ -17,6 +17,7 @@ from bot.bot import Bot from bot.constants import MODERATION_ROLES, RedirectOutput from bot.converters import Inventory, PackageName, ValidURL, allowed_strings from bot.pagination import LinePaginator +from bot.utils import scheduling from bot.utils.lock import SharedEvent, lock from bot.utils.messages import send_denial, wait_for_deletion from bot.utils.scheduling import Scheduler @@ -75,9 +76,10 @@ class DocCog(commands.Cog): self.refresh_event.set() self.symbol_get_event = SharedEvent() - self.init_refresh_task = self.bot.loop.create_task( + self.init_refresh_task = scheduling.create_task( self.init_refresh_inventory(), - name="Doc inventory init" + name="Doc inventory init", + event_loop=self.bot.loop, ) @lock(NAMESPACE, COMMAND_LOCK_SINGLETON, raise_error=True) diff --git a/bot/exts/info/pep.py b/bot/exts/info/pep.py index b11b34db0..bbd112911 100644 --- a/bot/exts/info/pep.py +++ b/bot/exts/info/pep.py @@ -9,6 +9,7 @@ from discord.ext.commands import Cog, Context, command from bot.bot import Bot from bot.constants import Keys +from bot.utils import scheduling from bot.utils.caching import AsyncCache log = logging.getLogger(__name__) @@ -32,7 +33,7 @@ class PythonEnhancementProposals(Cog): self.peps: Dict[int, str] = {} # To avoid situations where we don't have last datetime, set this to now. self.last_refreshed_peps: datetime = datetime.now() - self.bot.loop.create_task(self.refresh_peps_urls()) + scheduling.create_task(self.refresh_peps_urls(), event_loop=self.bot.loop) async def refresh_peps_urls(self) -> None: """Refresh PEP URLs listing in every 3 hours.""" diff --git a/bot/exts/info/python_news.py b/bot/exts/info/python_news.py index 63eb4ac17..58dcd3a02 100644 --- a/bot/exts/info/python_news.py +++ b/bot/exts/info/python_news.py @@ -11,6 +11,7 @@ from discord.ext.tasks import loop from bot import constants from bot.bot import Bot +from bot.utils import scheduling from bot.utils.webhooks import send_webhook PEPS_RSS_URL = "https://www.python.org/dev/peps/peps.rss/" @@ -33,8 +34,8 @@ class PythonNews(Cog): self.webhook_names = {} self.webhook: t.Optional[discord.Webhook] = None - self.bot.loop.create_task(self.get_webhook_names()) - self.bot.loop.create_task(self.get_webhook_and_channel()) + scheduling.create_task(self.get_webhook_names(), event_loop=self.bot.loop) + scheduling.create_task(self.get_webhook_and_channel(), event_loop=self.bot.loop) async def start_tasks(self) -> None: """Start the tasks for fetching new PEPs and mailing list messages.""" diff --git a/bot/exts/moderation/defcon.py b/bot/exts/moderation/defcon.py index 6ac077b93..053e8ae57 100644 --- a/bot/exts/moderation/defcon.py +++ b/bot/exts/moderation/defcon.py @@ -17,6 +17,7 @@ from bot.bot import Bot from bot.constants import Channels, Colours, Emojis, Event, Icons, MODERATION_ROLES, Roles from bot.converters import DurationDelta, Expiry from bot.exts.moderation.modlog import ModLog +from bot.utils import scheduling from bot.utils.messages import format_user from bot.utils.scheduling import Scheduler from bot.utils.time import ( @@ -69,7 +70,7 @@ class Defcon(Cog): self.scheduler = Scheduler(self.__class__.__name__) - self.bot.loop.create_task(self._sync_settings()) + scheduling.create_task(self._sync_settings(), event_loop=self.bot.loop) @property def mod_log(self) -> ModLog: diff --git a/bot/exts/moderation/incidents.py b/bot/exts/moderation/incidents.py index 561e0251e..a3d90e3fe 100644 --- a/bot/exts/moderation/incidents.py +++ b/bot/exts/moderation/incidents.py @@ -9,6 +9,7 @@ from discord.ext.commands import Cog from bot.bot import Bot from bot.constants import Channels, Colours, Emojis, Guild, Webhooks +from bot.utils import scheduling from bot.utils.messages import sub_clyde log = logging.getLogger(__name__) @@ -190,7 +191,7 @@ class Incidents(Cog): self.bot = bot self.event_lock = asyncio.Lock() - self.crawl_task = self.bot.loop.create_task(self.crawl_incidents()) + self.crawl_task = scheduling.create_task(self.crawl_incidents(), event_loop=self.bot.loop) async def crawl_incidents(self) -> None: """ @@ -275,7 +276,7 @@ class Incidents(Cog): return payload.message_id == incident.id coroutine = self.bot.wait_for(event="raw_message_delete", check=check, timeout=timeout) - return self.bot.loop.create_task(coroutine) + return scheduling.create_task(coroutine, event_loop=self.bot.loop) async def process_event(self, reaction: str, incident: discord.Message, member: discord.Member) -> None: """ diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 6ba4e74e9..8e844822d 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -29,7 +29,7 @@ class InfractionScheduler: self.bot = bot self.scheduler = scheduling.Scheduler(self.__class__.__name__) - self.bot.loop.create_task(self.reschedule_infractions(supported_infractions)) + scheduling.create_task(self.reschedule_infractions(supported_infractions), event_loop=self.bot.loop) def cog_unload(self) -> None: """Cancel scheduled tasks.""" diff --git a/bot/exts/moderation/metabase.py b/bot/exts/moderation/metabase.py index 9eeeec074..6eadd4bad 100644 --- a/bot/exts/moderation/metabase.py +++ b/bot/exts/moderation/metabase.py @@ -14,7 +14,7 @@ from discord.ext.commands import Cog, Context, group, has_any_role from bot.bot import Bot from bot.constants import Metabase as MetabaseConfig, Roles from bot.converters import allowed_strings -from bot.utils import send_to_paste_service +from bot.utils import scheduling, send_to_paste_service from bot.utils.channel import is_mod_channel from bot.utils.scheduling import Scheduler @@ -40,7 +40,7 @@ class Metabase(Cog): self.exports: Dict[int, List[Dict]] = {} # Saves the output of each question, so internal eval can access it - self.init_task = self.bot.loop.create_task(self.init_cog()) + self.init_task = scheduling.create_task(self.init_cog(), event_loop=self.bot.loop) async def cog_command_error(self, ctx: Context, error: Exception) -> None: """Handle ClientResponseError errors locally to invalidate token if needed.""" diff --git a/bot/exts/moderation/modpings.py b/bot/exts/moderation/modpings.py index 80c9f0c38..d775cdedf 100644 --- a/bot/exts/moderation/modpings.py +++ b/bot/exts/moderation/modpings.py @@ -9,6 +9,7 @@ from discord.ext.commands import Cog, Context, group, has_any_role from bot.bot import Bot from bot.constants import Colours, Emojis, Guild, Icons, MODERATION_ROLES, Roles from bot.converters import Expiry +from bot.utils import scheduling from bot.utils.scheduling import Scheduler log = logging.getLogger(__name__) @@ -29,7 +30,11 @@ class ModPings(Cog): self.guild = None self.moderators_role = None - self.reschedule_task = self.bot.loop.create_task(self.reschedule_roles(), name="mod-pings-reschedule") + self.reschedule_task = scheduling.create_task( + self.reschedule_roles(), + name="mod-pings-reschedule", + event_loop=self.bot.loop, + ) async def reschedule_roles(self) -> None: """Reschedule moderators role re-apply times.""" diff --git a/bot/exts/moderation/silence.py b/bot/exts/moderation/silence.py index 95e2792c3..2ee6496df 100644 --- a/bot/exts/moderation/silence.py +++ b/bot/exts/moderation/silence.py @@ -13,6 +13,7 @@ from discord.ext.commands import Context from bot import constants from bot.bot import Bot from bot.converters import HushDurationConverter +from bot.utils import scheduling from bot.utils.lock import LockedResourceError, lock, lock_arg from bot.utils.scheduling import Scheduler @@ -104,7 +105,7 @@ class Silence(commands.Cog): self.bot = bot self.scheduler = Scheduler(self.__class__.__name__) - self._init_task = self.bot.loop.create_task(self._async_init()) + self._init_task = scheduling.create_task(self._async_init(), event_loop=self.bot.loop) async def _async_init(self) -> None: """Set instance attributes once the guild is available and reschedule unsilences.""" diff --git a/bot/exts/moderation/stream.py b/bot/exts/moderation/stream.py index 01d2614b0..b5bd62a71 100644 --- a/bot/exts/moderation/stream.py +++ b/bot/exts/moderation/stream.py @@ -15,7 +15,7 @@ from bot.constants import ( ) from bot.converters import Expiry from bot.pagination import LinePaginator -from bot.utils.scheduling import Scheduler +from bot.utils import scheduling from bot.utils.time import discord_timestamp, format_infraction_with_duration log = logging.getLogger(__name__) @@ -30,8 +30,8 @@ class Stream(commands.Cog): def __init__(self, bot: Bot): self.bot = bot - self.scheduler = Scheduler(self.__class__.__name__) - self.reload_task = self.bot.loop.create_task(self._reload_tasks_from_redis()) + self.scheduler = scheduling.Scheduler(self.__class__.__name__) + self.reload_task = scheduling.create_task(self._reload_tasks_from_redis(), event_loop=self.bot.loop) def cog_unload(self) -> None: """Cancel all scheduled tasks.""" diff --git a/bot/exts/moderation/watchchannels/_watchchannel.py b/bot/exts/moderation/watchchannels/_watchchannel.py index 146426569..a42e1f518 100644 --- a/bot/exts/moderation/watchchannels/_watchchannel.py +++ b/bot/exts/moderation/watchchannels/_watchchannel.py @@ -18,7 +18,7 @@ from bot.exts.filters.token_remover import TokenRemover from bot.exts.filters.webhook_remover import WEBHOOK_URL_RE from bot.exts.moderation.modlog import ModLog from bot.pagination import LinePaginator -from bot.utils import CogABCMeta, messages +from bot.utils import CogABCMeta, messages, scheduling from bot.utils.time import get_time_delta log = logging.getLogger(__name__) @@ -69,7 +69,7 @@ class WatchChannel(metaclass=CogABCMeta): self.message_history = MessageHistory() self.disable_header = disable_header - self._start = self.bot.loop.create_task(self.start_watchchannel()) + self._start = scheduling.create_task(self.start_watchchannel(), event_loop=self.bot.loop) @property def modlog(self) -> ModLog: @@ -169,7 +169,7 @@ class WatchChannel(metaclass=CogABCMeta): """Queues up messages sent by watched users.""" if msg.author.id in self.watched_users: if not self.consuming_messages: - self._consume_task = self.bot.loop.create_task(self.consume_messages()) + self._consume_task = scheduling.create_task(self.consume_messages(), event_loop=self.bot.loop) self.log.trace(f"Received message: {msg.content} ({len(msg.attachments)} attachments)") self.message_queue[msg.author.id][msg.channel.id].append(msg) @@ -199,7 +199,10 @@ class WatchChannel(metaclass=CogABCMeta): if self.message_queue: self.log.trace("Channel queue not empty: Continuing consuming queues") - self._consume_task = self.bot.loop.create_task(self.consume_messages(delay_consumption=False)) + self._consume_task = scheduling.create_task( + self.consume_messages(delay_consumption=False), + event_loop=self.bot.loop, + ) else: self.log.trace("Done consuming messages.") diff --git a/bot/exts/utils/reminders.py b/bot/exts/utils/reminders.py index 41b6cac5c..00eb930b5 100644 --- a/bot/exts/utils/reminders.py +++ b/bot/exts/utils/reminders.py @@ -17,6 +17,7 @@ from bot.constants import ( ) from bot.converters import Duration, UnambiguousUser from bot.pagination import LinePaginator +from bot.utils import scheduling from bot.utils.checks import has_any_role_check, has_no_roles_check from bot.utils.lock import lock_arg from bot.utils.messages import send_denial @@ -40,7 +41,7 @@ class Reminders(Cog): self.bot = bot self.scheduler = Scheduler(self.__class__.__name__) - self.bot.loop.create_task(self.reschedule_reminders()) + scheduling.create_task(self.reschedule_reminders(), event_loop=self.bot.loop) def cog_unload(self) -> None: """Cancel scheduled tasks.""" diff --git a/bot/exts/utils/snekbox.py b/bot/exts/utils/snekbox.py index b1f1ba6a8..5fb10a25b 100644 --- a/bot/exts/utils/snekbox.py +++ b/bot/exts/utils/snekbox.py @@ -14,7 +14,7 @@ from discord.ext.commands import Cog, Context, command, guild_only from bot.bot import Bot from bot.constants import Categories, Channels, Roles, URLs from bot.decorators import redirect_output -from bot.utils import send_to_paste_service +from bot.utils import scheduling, send_to_paste_service from bot.utils.messages import wait_for_deletion log = logging.getLogger(__name__) @@ -219,7 +219,7 @@ class Snekbox(Cog): response = await ctx.send("Attempt to circumvent filter detected. Moderator team has been alerted.") else: response = await ctx.send(msg) - self.bot.loop.create_task(wait_for_deletion(response, (ctx.author.id,))) + scheduling.create_task(wait_for_deletion(response, (ctx.author.id,)), event_loop=self.bot.loop) log.info(f"{ctx.author}'s job had a return code of {results['returncode']}") return response diff --git a/tests/bot/exts/backend/sync/test_cog.py b/tests/bot/exts/backend/sync/test_cog.py index 22a07313e..fdd0ab74a 100644 --- a/tests/bot/exts/backend/sync/test_cog.py +++ b/tests/bot/exts/backend/sync/test_cog.py @@ -60,13 +60,13 @@ class SyncCogTestCase(unittest.IsolatedAsyncioTestCase): class SyncCogTests(SyncCogTestCase): """Tests for the Sync cog.""" + @mock.patch("bot.utils.scheduling.create_task") @mock.patch.object(Sync, "sync_guild", new_callable=mock.MagicMock) - def test_sync_cog_init(self, sync_guild): + def test_sync_cog_init(self, sync_guild, create_task): """Should instantiate syncers and run a sync for the guild.""" # Reset because a Sync cog was already instantiated in setUp. self.RoleSyncer.reset_mock() self.UserSyncer.reset_mock() - self.bot.loop.create_task = mock.MagicMock() mock_sync_guild_coro = mock.MagicMock() sync_guild.return_value = mock_sync_guild_coro @@ -74,7 +74,8 @@ class SyncCogTests(SyncCogTestCase): Sync(self.bot) sync_guild.assert_called_once_with() - self.bot.loop.create_task.assert_called_once_with(mock_sync_guild_coro) + create_task.assert_called_once() + self.assertEqual(create_task.call_args.args[0], mock_sync_guild_coro) async def test_sync_cog_sync_guild(self): """Roles and users should be synced only if a guild is successfully retrieved.""" diff --git a/tests/helpers.py b/tests/helpers.py index 3978076ed..47f06f292 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -278,7 +278,10 @@ def _get_mock_loop() -> unittest.mock.Mock: # Since calling `create_task` on our MockBot does not actually schedule the coroutine object # as a task in the asyncio loop, this `side_effect` calls `close()` on the coroutine object # to prevent "has not been awaited"-warnings. - loop.create_task.side_effect = lambda coroutine: coroutine.close() + def mock_create_task(coroutine, **kwargs): + coroutine.close() + return unittest.mock.Mock() + loop.create_task.side_effect = mock_create_task return loop |