[commads] Change cog/extension load/unload methods to be async

This commit is contained in:
Josh
2022-03-14 11:03:45 +10:00
committed by GitHub
parent a339e01047
commit a1c618215e
8 changed files with 210 additions and 50 deletions

View File

@ -58,7 +58,7 @@ Once you have defined your cogs, you need to tell the bot to register the cogs t
.. code-block:: python3
bot.add_cog(Greetings(bot))
await bot.add_cog(Greetings(bot))
This binds the cog to the bot, adding all commands and listeners to the bot automatically.
@ -66,7 +66,7 @@ Note that we reference the cog by name, which we can override through :ref:`ext_
.. code-block:: python3
bot.remove_cog('Greetings')
await bot.remove_cog('Greetings')
Using Cogs
-------------
@ -112,6 +112,7 @@ As cogs get more complicated and have more commands, there comes a point where w
They are as follows:
- :meth:`.Cog.cog_load`
- :meth:`.Cog.cog_unload`
- :meth:`.Cog.cog_check`
- :meth:`.Cog.cog_command_error`

View File

@ -24,10 +24,10 @@ An example extension looks like this:
async def hello(ctx):
await ctx.send(f'Hello {ctx.author.display_name}.')
def setup(bot):
async def setup(bot):
bot.add_command(hello)
In this example we define a simple command, and when the extension is loaded this command is added to the bot. Now the final step to this is loading the extension, which we do by calling :meth:`.Bot.load_extension`. To load this extension we call ``bot.load_extension('hello')``.
In this example we define a simple command, and when the extension is loaded this command is added to the bot. Now the final step to this is loading the extension, which we do by calling :meth:`.Bot.load_extension`. To load this extension we call ``await bot.load_extension('hello')``.
.. admonition:: Cogs
:class: helpful
@ -45,7 +45,7 @@ When you make a change to the extension and want to reload the references, the l
.. code-block:: python3
>>> bot.reload_extension('hello')
>>> await bot.reload_extension('hello')
Once the extension reloads, any changes that we did will be applied. This is useful if we want to add or remove functionality without restarting our bot. If an error occurred during the reloading process, the bot will pretend as if the reload never happened.
@ -57,8 +57,8 @@ Although rare, sometimes an extension needs to clean-up or know when it's being
.. code-block:: python3
:caption: basic_ext.py
def setup(bot):
async def setup(bot):
print('I am being loaded!')
def teardown(bot):
async def teardown(bot):
print('I am being unloaded!')

View File

@ -65,6 +65,54 @@ The following have been removed:
- ``User.mutual_friends`` attribute
- ``User.relationship`` attribute
.. _migrating_2_0_client_async_setup:
asyncio Event Loop Changes
---------------------------
Python 3.7 introduced a new helper function :func:`asyncio.run` which automatically creates and destroys the asynchronous event loop.
In order to support this, the way discord.py handles the :mod:`asyncio` event loop has changed.
This allows you to rather than using :meth:`Client.run` create your own asynchronous loop to setup other asynchronous code as needed.
Quick example:
.. code-block:: python
client = discord.Client()
async def main():
# do other async things
await my_async_function()
# start the client
async with client:
await client.start(TOKEN)
asyncio.run(main())
A new :meth:`~Client.setup_hook` method has also been added to the :class:`Client` class.
This method is called after login but before connecting to the discord gateway.
It is intended to be used to setup various bot features in an asynchronous context.
:meth:`~Client.setup_hook` can be defined by subclassing the :class:`Client` class.
Quick example:
.. code-block:: python
class MyClient(discord.Client):
async def setup_hook(self):
print('This is asynchronous!')
client = MyClient()
client.run(TOKEN)
In parallel with this change, changes were made to loading and unloading of commands extension extensions and cogs,
see :ref:`migrating_2_0_commands_extension_cog_async` for more information.
Abstract Base Classes Changes
-------------------------------
@ -1095,6 +1143,55 @@ The following changes have been made:
Command Extension Changes
---------------------------
.. _migrating_2_0_commands_extension_cog_async:
Extension and Cog Loading / Unloading is Now Asynchronous
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As an extension to the :ref:`asyncio changes <migrating_2_0_client_async_setup>` the loading and unloading of extensions and cogs is now asynchronous.
To accommodate this, the following changes have been made:
- the ``setup`` and ``teardown`` functions in extensions must now be coroutines.
- :meth:`ext.commands.Bot.load_extension` must now be awaited.
- :meth:`ext.commands.Bot.unload_extension` must now be awaited.
- :meth:`ext.commands.Bot.reload_extension` must now be awaited.
- :meth:`ext.commands.Bot.add_cog` must now be awaited.
- :meth:`ext.commands.Bot.remove_cog` must now be awaited.
Quick example of an extension setup function:
.. code:: python
# before
def setup(bot):
bot.add_cog(MyCog(bot))
#after
async def setup(bot):
await bot.add_cog(MyCog(bot))
Quick example of loading an extension:
.. code:: python
#before
bot.load_extension('my_extension')
#after using setup_hook
class MyBot(commands.Bot):
async def setup_hook(self):
await self.load_extension('my_extension')
# after using async_with
async def main():
async with bot:
await bot.load_extension('my_extension')
await bot.start(TOKEN)
asyncio.run(main())
Converters Are Now Generic Runtime Protocols
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1192,6 +1289,8 @@ Miscellanous Changes
- :attr:`ext.commands.Context.channel` may now be a :class:`PartialMessageable`.
- ``MissingPermissions.missing_perms`` has been renamed to :attr:`ext.commands.MissingPermissions.missing_permissions`.
- ``BotMissingPermissions.missing_perms`` has been renamed to :attr:`ext.commands.BotMissingPermissions.missing_permissions`.
- :meth:`ext.commands.Cog.cog_load` has been added as part of the :ref:`migrating_2_0_commands_extension_cog_async` changes.
- :meth:`ext.commands.Cog.cog_unload` may now be a :term:`coroutine` due to the :ref:`migrating_2_0_commands_extension_cog_async` changes.
.. _migrating_2_0_tasks: