diff --git a/docs/api.rst b/docs/api.rst index 22d8e37c2..4f7b0d92f 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -331,6 +331,7 @@ to handle it, which defaults to print a traceback and ignore the exception. :param user: The user that started typing. :param when: A ``datetime.datetime`` object representing when typing started. +.. _discord-api-utils: Utility Functions ----------------- @@ -339,6 +340,8 @@ Utility Functions .. autofunction:: discord.utils.get +.. _discord-api-enums: + Enumerators ------------ @@ -400,6 +403,8 @@ All enumerators are subclasses of `enum`_. The member is idle. +.. _discord_api_data: + Data Classes -------------- diff --git a/docs/index.rst b/docs/index.rst index 7f3ab9d79..3f526b37f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,6 +12,7 @@ Contents: :maxdepth: 2 logging + migrating api diff --git a/docs/migrating.rst b/docs/migrating.rst new file mode 100644 index 000000000..9d447a2ae --- /dev/null +++ b/docs/migrating.rst @@ -0,0 +1,235 @@ +.. currentmodule:: discord + +.. _migrating-to-async: + +Migrating to v0.10.0 +====================== + +v0.10.0 is one of the biggest breaking changes in the library due to massive +fundamental changes in how the library operates. + +The biggest major change is that the library has dropped support to all versions prior to +Python 3.4.2. This was made to support ``asyncio``, in which more detail can be seen +:issue:`in the corresponding issue <50>`. To reiterate this, the implication is that +**python version 2.7 and 3.3 are no longer supported**. + +Below are all the other major changes from v0.9.0 to v0.10.0. + +.. _migrating-event-registration: + +Event Registration +-------------------- + +All events before were registered using :meth:`Client.event`. While this is still +possible, the events must be decorated with ``@asyncio.coroutine``. + +Before: + +.. code-block:: python + + @client.event + def on_message(message): + pass + +After: + +.. code-block:: python + + @client.event + @asyncio.coroutine + def on_message(message): + pass + +Or in Python 3.5+: + +.. code-block:: python + + @client.event + async def on_message(message): + pass + +Because there is a lot of typing, a utility decorator (:meth:`Client.async_event`) is provided +for easier registration. For example: + +.. code-block:: python + + @client.async_event + def on_message(message): + pass + + +Be aware however, that this is still a coroutine and your other functions that are coroutines must +be decorated with `` @asyncio.coroutine`` or be ``async def``. + +.. _migrating_event_changes: + +Event Changes +-------------- + +Some events in v0.9.0 were considered pretty useless due to having no separate states. The main +events that were changed were the ``_update`` events since previously they had no context on what +was changed. + +Before: + +.. code-block:: python + + def on_channel_update(channel): pass + def on_member_update(member): pass + def on_status(member): pass + def on_server_role_update(role): pass + def on_voice_state_update(member): pass + + +After: + +.. code-block:: python + + def on_channel_update(before, after): pass + def on_member_update(before, after): pass + def on_server_role_update(before, after): pass + def on_voice_state_update(before, after): pass + +Note that ``on_status`` was removed. If you want its functionality, use :func:`on_member_update`. +See :ref:`discord-api-events` for more information. + + +.. _migrating-coroutines: + +Coroutines +----------- + +The biggest change that the library went through is that almost every function in :class:`Client` +was changed to be a `coroutine `_. Functions +that are marked as a coroutine in the documentation must be awaited from or yielded from in order +for the computation to be done. For example... + +Before: + +.. code-block:: python + + client.send_message(message.channel, 'Hello') + +After: + +.. code-block:: python + + yield from client.send_message(message.channel, 'Hello') + + # or in python 3.5+ + await client.send_message(message.channel, 'Hello') + +In order for you to ``yield from`` or ``await`` a coroutine then your function must be decorated +with ``@asyncio.coroutine`` or ``async def``. + +.. _migrating-enums: + +Enumerators +------------ + +Due to dropping support for versions lower than Python 3.4.2, the library can now use +`enumerators `_ in places where it makes sense. + +The common places where this was changed was in the server region, member status, and channel type. + +Before: + +.. code-block:: python + + server.region == 'us-west' + member.status == 'online' + channel.type == 'text' + +After: + +.. code-block:: python + + server.region == discord.ServerRegion.us_west + member.status = discord.Status.online + channel.type == discord.ChannelType.text + +The main reason for this change was to reduce the use of finnicky strings in the API as this +could give users a false sense of power. More information can be found in the :ref:`discord-api-enums` page. + +.. _migrating-properties: + +Properties +----------- + +A lot of function calls that returned constant values were changed into Python properties for ease of use +in format strings. + +The following functions were changed into properties: + ++----------------------------------------+--------------------------------------+ +| Before | After | ++----------------------------------------+--------------------------------------+ +| ``user.avatar_url()`` | :attr:`User.avatar_url` | ++----------------------------------------+--------------------------------------+ +| ``user.mention()`` | :attr:`User.mention` | ++----------------------------------------+--------------------------------------+ +| ``channel.mention()`` | :attr:`Channel.mention` | ++----------------------------------------+--------------------------------------+ +| ``channel.is_default_channel()`` | :attr:`Channel.is_default` | ++----------------------------------------+--------------------------------------+ +| ``role.is_everyone()`` | :attr:`Role.is_everyone` | ++----------------------------------------+--------------------------------------+ +| ``server.get_default_role()`` | :attr:`Server.default_role` | ++----------------------------------------+--------------------------------------+ +| ``server.icon_url()`` | :attr:`Server.icon_url` | ++----------------------------------------+--------------------------------------+ +| ``server.get_default_channel()`` | :attr:`Server.default_channel` | ++----------------------------------------+--------------------------------------+ +| ``message.get_raw_mentions()`` | :attr:`Message.raw_mentions` | ++----------------------------------------+--------------------------------------+ +| ``message.get_raw_channel_mentions()`` | :attr:`Message.raw_channel_mentions` | ++----------------------------------------+--------------------------------------+ + +.. _migrating-running: + +Running the Client +-------------------- + +In earlier versions of discord.py, ``client.run()`` was a blocking call to the main thread +that called it. In v0.10.0 it is still a blocking call but it handles the event loop for you. +However, in order to do that you must pass in your credentials to :meth:`Client.run`. + +Basically, before: + +.. code-block:: python + + client.login('email', 'password') + client.run() + +After: + +.. code-block:: python + + client.run('email', 'password') + +This is a utility function that abstracts the event loop for you. There's no need for +the run call to be blocking and out of your control. Indeed, if you want control of the +event loop then doing so is quite straightforward: + +.. code-block:: python + + import discord + import asyncio + + client = discord.Client() + + @asyncio.coroutine + def main_task(): + yield from client.login('email', 'password') + yield from client.connect() + + loop = asyncio.get_event_loop() + try: + loop.run_until_complete(main_task()) + except: + loop.run_until_complete(client.logout()) + finally: + loop.close() + + +