Skip to content

Commit

Permalink
pybricks.tools: Document multitasking.
Browse files Browse the repository at this point in the history
  • Loading branch information
laurensvalk committed Oct 24, 2023
1 parent faf1158 commit 209fba5
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 24 deletions.
22 changes: 0 additions & 22 deletions doc/main/signaltypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -293,25 +293,3 @@ though the *hub* accelerates backward.
and other creations, by noting which way the top and
front :class:`Side <Side>` of the hub are pointing. The example
on the left is the default configuration.

.. class:: await

Multitasking
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Pybricks supports cooperative multitasking using the ``async`` and ``await``
keywords. This allows operations that normally take some time to complete, to
run in parallel with other operations.

Whenever you see the word ``await`` in the documentation, this means that the
method or function supports multitasking.

The following example shows how to use multitasking to make a robot drive
forward, then turn and move a gripper at the same time, and then drive
backward.

.. literalinclude::
../../examples/pup/robotics/drivebase_async.py

If you don't use multitasking, you can ignore the ``await`` keyword and write
programs as usual.
32 changes: 32 additions & 0 deletions doc/main/tools/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,35 @@ Linear algebra tools
.. autofunction:: pybricks.tools.vector

.. autofunction:: pybricks.tools.cross

Multitasking
--------------------

.. versionadded:: 3.3

Pybricks supports cooperative multitasking using the ``async`` and ``await``
keywords. This allows operations that normally take some time to complete to
run in parallel with other operations.

.. autofunction:: pybricks.tools.multitask

.. autofunction:: pybricks.tools.run_task

The following example shows how to use multitasking to make a robot drive
forward, then turn and move a gripper at the same time, and then drive
backward.

.. literalinclude::
../../../examples/pup/robotics/drivebase_async.py

.. class:: coroutine

.. class:: await

Whenever you see a function or method prefixed by ``await``, this means that
it supports multitasking. When running a coroutine with ``run_task``, all
methods and functions prefixed by ``await`` will act as coroutines.

If you don't use multitasking, you can ignore the ``await`` keyword and write
programs as usual. Specifically, when ``run_task`` is not used, functions
prefixed by ``await`` will act as normal functions.
2 changes: 2 additions & 0 deletions jedi/tests/test_complete_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ def test_from_pybricks_tools_import():
"DataLog",
"hub_menu",
"Matrix",
"multitask",
"read_input_byte",
"run_task",
"StopWatch",
"vector",
"wait",
Expand Down
37 changes: 35 additions & 2 deletions src/pybricks/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Optional, Sequence, Tuple, overload
from typing import TYPE_CHECKING, Any, Optional, Sequence, Tuple, overload, Coroutine

if TYPE_CHECKING:
from ._common import MaybeAwaitable
from ._common import MaybeAwaitable, MaybeAwaitableTuple
from .parameters import Number


Expand Down Expand Up @@ -255,7 +255,40 @@ def hub_menu(*symbols: int | str) -> int | str:
"""


def multitask(*coroutines: Coroutine, race=False) -> MaybeAwaitableTuple:
"""
multitask(coroutine1, coroutine2, ...) -> Tuple
Runs multiple coroutines concurrently. This creates a new coroutine that
can be used like any other, including in another ``multitask`` statement.
Arguments:
coroutines (coroutine, coroutine, ...): One or more coroutines to run
in parallel.
race (bool): Choose ``False`` to wait for all coroutines to finish.
Choose ``True`` to wait for one coroutine to finish and then
cancel the others, as if it's a "race".
Returns:
Tuple of the return values of each coroutine. Unfinished coroutines
will have ``None`` as their return value.
"""


def run_task(coroutine: Coroutine):
"""
run_task(coroutine)
Runs a coroutine from start to finish while blocking the rest of the
program. This is used primarily to run the main coroutine of a program.
Arguments:
coroutine (coroutine): The main coroutine to run.
"""


# HACK: hide from jedi
if TYPE_CHECKING:
del Number
del MaybeAwaitable
del MaybeAwaitableTuple

0 comments on commit 209fba5

Please sign in to comment.