summaryrefslogtreecommitdiffstats
path: root/docs/pages/upgrading
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 17:35:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 17:35:20 +0000
commite106bf94eff07d9a59771d9ccc4406421e18ab64 (patch)
treeedb6545500e39df9c67aa918a6125bffc8ec1aee /docs/pages/upgrading
parentInitial commit. (diff)
downloadprompt-toolkit-e106bf94eff07d9a59771d9ccc4406421e18ab64.tar.xz
prompt-toolkit-e106bf94eff07d9a59771d9ccc4406421e18ab64.zip
Adding upstream version 3.0.36.upstream/3.0.36upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--docs/pages/upgrading/2.0.rst221
-rw-r--r--docs/pages/upgrading/3.0.rst118
-rw-r--r--docs/pages/upgrading/index.rst11
3 files changed, 350 insertions, 0 deletions
diff --git a/docs/pages/upgrading/2.0.rst b/docs/pages/upgrading/2.0.rst
new file mode 100644
index 0000000..a580ff3
--- /dev/null
+++ b/docs/pages/upgrading/2.0.rst
@@ -0,0 +1,221 @@
+.. _upgrading_2_0:
+
+Upgrading to prompt_toolkit 2.0
+===============================
+
+Prompt_toolkit 2.0 is not compatible with 1.0, however you probably want to
+upgrade your applications. This page explains why we have these differences and
+how to upgrade.
+
+If you experience some difficulties or you feel that some information is
+missing from this page, don't hesitate to open a GitHub issue for help.
+
+
+Why all these breaking changes?
+-------------------------------
+
+After more and more custom prompt_toolkit applications were developed, it
+became clear that prompt_toolkit 1.0 was not flexible enough for certain use
+cases. Mostly, the development of full screen applications was not really
+natural. All the important components, like the rendering, key bindings, input
+and output handling were present, but the API was in the first place designed
+for simple command line prompts. This was mostly notably in the following two
+places:
+
+- First, there was the focus which was always pointing to a
+ :class:`~prompt_toolkit.buffer.Buffer` (or text input widget), but in full
+ screen applications there are other widgets, like menus and buttons which
+ can be focused.
+- And secondly, it was impossible to make reusable UI components. All the key
+ bindings for the entire applications were stored together in one
+ ``KeyBindings`` object, and similar, all
+ :class:`~prompt_toolkit.buffer.Buffer` objects were stored together in one
+ dictionary. This didn't work well. You want reusable components to define
+ their own key bindings and everything. It's the idea of encapsulation.
+
+For simple prompts, the changes wouldn't be that invasive, but given that there
+would be some, I took the opportunity to fix a couple of other things. For
+instance:
+
+- In prompt_toolkit 1.0, we translated `\\r` into `\\n` during the input
+ processing. This was not a good idea, because some people wanted to handle
+ these keys individually. This makes sense if you keep in mind that they
+ correspond to `Control-M` and `Control-J`. However, we couldn't fix this
+ without breaking everyone's enter key, which happens to be the most important
+ key in prompts.
+
+Given that we were going to break compatibility anyway, we changed a couple of
+other important things that effect both simple prompt applications and
+full screen applications. These are the most important:
+
+- We no longer depend on Pygments for styling. While we like Pygments, it was
+ not flexible enough to provide all the styling options that we need, and the
+ Pygments tokens were not ideal for styling anything besides tokenized text.
+
+ Instead we created something similar to CSS. All UI components can attach
+ classnames to themselves, as well as define an inline style. The final style is
+ then computed by combining the inline styles, the classnames and the style
+ sheet.
+
+ There are still adaptors available for using Pygments lexers as well as for
+ Pygments styles.
+
+- The way that key bindings were defined was too complex.
+ ``KeyBindingsManager`` was too complex and no longer exists. Every set of key
+ bindings is now a
+ :class:`~prompt_toolkit.key_binding.KeyBindings` object and multiple of these
+ can be merged together at any time. The runtime performance remains the same,
+ but it's now easier for users.
+
+- The separation between the ``CommandLineInterface`` and
+ :class:`~prompt_toolkit.application.Application` class was confusing and in
+ the end, didn't really had an advantage. These two are now merged together in
+ one :class:`~prompt_toolkit.application.Application` class.
+
+- We no longer pass around the active ``CommandLineInterface``. This was one of
+ the most annoying things. Key bindings need it in order to change anything
+ and filters need it in order to evaluate their state. It was pretty annoying,
+ especially because there was usually only one application active at a time.
+ So, :class:`~prompt_toolkit.application.Application` became a ``TaskLocal``.
+ That is like a global variable, but scoped in the current coroutine or
+ context. The way this works is still not 100% correct, but good enough for
+ the projects that need it (like Pymux), and hopefully Python will get support
+ for this in the future thanks to PEP521, PEP550 or PEP555.
+
+All of these changes have been tested for many months, and I can say with
+confidence that prompt_toolkit 2.0 is a better prompt_toolkit.
+
+
+Some new features
+-----------------
+
+Apart from the breaking changes above, there are also some exciting new
+features.
+
+- We now support vt100 escape codes for Windows consoles on Windows 10. This
+ means much faster rendering, and full color support.
+
+- We have a concept of formatted text. This is an object that evaluates to
+ styled text. Every input that expects some text, like the message in a
+ prompt, or the text in a toolbar, can take any kind of formatted text as input.
+ This means you can pass in a plain string, but also a list of `(style,
+ text)` tuples (similar to a Pygments tokenized string), or an
+ :class:`~prompt_toolkit.formatted_text.HTML` object. This simplifies many
+ APIs.
+
+- New utilities were added. We now have function for printing formatted text
+ and an experimental module for displaying progress bars.
+
+- Autocompletion, input validation, and auto suggestion can now either be
+ asynchronous or synchronous. By default they are synchronous, but by wrapping
+ them in :class:`~prompt_toolkit.completion.ThreadedCompleter`,
+ :class:`~prompt_toolkit.validation.ThreadedValidator` or
+ :class:`~prompt_toolkit.auto_suggest.ThreadedAutoSuggest`, they will become
+ asynchronous by running in a background thread.
+
+ Further, if the autocompletion code runs in a background thread, we will show
+ the completions as soon as they arrive. This means that the autocompletion
+ algorithm could for instance first yield the most trivial completions and then
+ take time to produce the completions that take more time.
+
+
+Upgrading
+---------
+
+More guidelines on how to upgrade will follow.
+
+
+`AbortAction` has been removed
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Prompt_toolkit 1.0 had an argument ``abort_action`` for both the
+``Application`` class as well as for the ``prompt`` function. This has been
+removed. The recommended way to handle this now is by capturing
+``KeyboardInterrupt`` and ``EOFError`` manually.
+
+
+Calling `create_eventloop` usually not required anymore
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Prompt_toolkit 2.0 will automatically create the appropriate event loop when
+it's needed for the first time. There is no need to create one and pass it
+around. If you want to run an application on top of asyncio (without using an
+executor), it still needs to be activated by calling
+:func:`~prompt_toolkit.eventloop.use_asyncio_event_loop` at the beginning.
+
+
+Pygments styles and tokens
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+prompt_toolkit 2.0 no longer depends on `Pygments <http://pygments.org/>`_, but
+that definitely doesn't mean that you can't use any Pygments functionality
+anymore. The only difference is that Pygments stuff needs to be wrapped in an
+adaptor to make it compatible with the native prompt_toolkit objects.
+
+- For instance, if you have a list of ``(pygments.Token, text)`` tuples for
+ formatting, then this needs to be wrapped in a
+ :class:`~prompt_toolkit.formatted_text.PygmentsTokens` object. This is an
+ adaptor that turns it into prompt_toolkit "formatted text". Feel free to keep
+ using this.
+
+- Pygments lexers need to be wrapped in a
+ :class:`~prompt_toolkit.lexers.PygmentsLexer`. This will convert the list of
+ Pygments tokens into prompt_toolkit formatted text.
+
+- If you have a Pygments style, then this needs to be converted as well. A
+ Pygments style class can be converted in a prompt_toolkit
+ :class:`~prompt_toolkit.styles.Style` with the
+ :func:`~prompt_toolkit.styles.pygments.style_from_pygments_cls` function
+ (which used to be called ``style_from_pygments``). A Pygments style
+ dictionary can be converted using
+ :func:`~prompt_toolkit.styles.pygments.style_from_pygments_dict`.
+
+ Multiple styles can be merged together using
+ :func:`~prompt_toolkit.styles.merge_styles`.
+
+
+Wordcompleter
+^^^^^^^^^^^^^
+
+`WordCompleter` was moved from
+:class:`prompt_toolkit.contrib.completers.base.WordCompleter` to
+:class:`prompt_toolkit.completion.word_completer.WordCompleter`.
+
+
+Asynchronous autocompletion
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By default, prompt_toolkit 2.0 completion is now synchronous. If you still want
+asynchronous auto completion (which is often good thing), then you have to wrap
+the completer in a :class:`~prompt_toolkit.completion.ThreadedCompleter`.
+
+
+Filters
+^^^^^^^
+
+We don't distiguish anymore between `CLIFilter` and `SimpleFilter`, because the
+application object is no longer passed around. This means that all filters are
+a `Filter` from now on.
+
+All filters have been turned into functions. For instance, `IsDone` became
+`is_done` and `HasCompletions` became `has_completions`.
+
+This was done because almost all classes were called without any arguments in
+the `__init__` causing additional braces everywhere. This means that
+`HasCompletions()` has to be replaced by `has_completions` (without
+parenthesis).
+
+The few filters that took arguments as input, became functions, but still have
+to be called with the given arguments.
+
+For new filters, it is recommended to use the `@Condition` decorator,
+rather then inheriting from `Filter`. For instance:
+
+.. code:: python
+
+ from prompt_toolkit.filters import Condition
+
+ @Condition
+ def my_filter();
+ return True # Or False
+
diff --git a/docs/pages/upgrading/3.0.rst b/docs/pages/upgrading/3.0.rst
new file mode 100644
index 0000000..7a867c5
--- /dev/null
+++ b/docs/pages/upgrading/3.0.rst
@@ -0,0 +1,118 @@
+.. _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)
diff --git a/docs/pages/upgrading/index.rst b/docs/pages/upgrading/index.rst
new file mode 100644
index 0000000..b790a64
--- /dev/null
+++ b/docs/pages/upgrading/index.rst
@@ -0,0 +1,11 @@
+.. _upgrading:
+
+Upgrading
+=========
+
+.. toctree::
+ :caption: Contents:
+ :maxdepth: 1
+
+ 2.0
+ 3.0