.. _upgrading_3_0:

Upgrading to prompt_toolkit 3.0
===============================

There are two major changes in 3.0 to be aware of:

- First, prompt_toolkit uses the asyncio event loop natively, rather then using
  its own implementations of event loops. This means that all coroutines are
  now asyncio coroutines, and all Futures are asyncio futures. Asynchronous
  generators became real asynchronous generators as well.

- Prompt_toolkit uses type annotations (almost) everywhere. This should not
  break any code, but its very helpful in many ways.

There are some minor breaking changes:

- The dialogs API had to change (see below).


Detecting the prompt_toolkit version
------------------------------------

Detecting whether version 3 is being used can be done as follows:

.. code:: python

    from prompt_toolkit import __version__ as ptk_version

    PTK3 = ptk_version.startswith('3.')


Fixing calls to `get_event_loop`
--------------------------------

Every usage of ``get_event_loop`` has to be fixed. An easy way to do this is by
changing the imports like this:

.. code:: python

    if PTK3:
        from asyncio import get_event_loop
    else:
        from prompt_toolkit.eventloop import get_event_loop

Notice that for prompt_toolkit 2.0, ``get_event_loop`` returns a prompt_toolkit
``EventLoop`` object. This is not an asyncio eventloop, but the API is
similar.

There are some changes to the eventloop API:

+-----------------------------------+--------------------------------------+
| version 2.0                       | version 3.0 (asyncio)                |
+===================================+======================================+
| loop.run_in_executor(callback)    | loop.run_in_executor(None, callback) |
+-----------------------------------+--------------------------------------+
| loop.call_from_executor(callback) | loop.call_soon_threadsafe(callback)  |
+-----------------------------------+--------------------------------------+


Running on top of asyncio
-------------------------

For 2.0, you had tell prompt_toolkit to run on top of the asyncio event loop.
Now it's the default. So, you can simply remove the following two lines:

.. code::

    from prompt_toolkit.eventloop.defaults import use_asyncio_event_loop
    use_asyncio_event_loop()

There is a few little breaking changes though. The following:

.. code::

    # For 2.0
    result = await PromptSession().prompt('Say something: ', async_=True)

has to be changed into:

.. code::

    # For 3.0
    result = await PromptSession().prompt_async('Say something: ')

Further, it's impossible to call the `prompt()` function within an asyncio
application (within a coroutine), because it will try to run the event loop
again. In that case, always use `prompt_async()`.


Changes to the dialog functions
-------------------------------

The original way of using dialog boxes looked like this:

.. code:: python

    from prompt_toolkit.shortcuts import input_dialog

    result = input_dialog(title='...', text='...')

Now, the dialog functions return a prompt_toolkit Application object. You have
to call either its ``run`` or ``run_async`` method to display the dialog. The
``async_`` parameter has been removed everywhere.

.. code:: python

    if PTK3:
        result = input_dialog(title='...', text='...').run()
    else:
        result = input_dialog(title='...', text='...')

    # Or

    if PTK3:
        result = await input_dialog(title='...', text='...').run_async()
    else:
        result = await input_dialog(title='...', text='...', async_=True)
