From f57250e0b4403668e2b867299d0c94004d33a154 Mon Sep 17 00:00:00 2001 From: Marius Eriksen Date: Thu, 30 Oct 2025 09:42:55 -0700 Subject: [PATCH 1/2] [monarch] document pytokio We keep getting questions about how this works. This is an attempt to document it in simple terms. Differential Revision: [D85870468](https://our.internmc.facebook.com/intern/diff/D85870468/) **NOTE FOR REVIEWERS**: This PR has internal Meta-specific changes or comments, please review them on [Phabricator](https://our.internmc.facebook.com/intern/diff/D85870468/)! [ghstack-poisoned] --- monarch_hyperactor/src/pytokio.rs | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/monarch_hyperactor/src/pytokio.rs b/monarch_hyperactor/src/pytokio.rs index 8f04cfc2c..c8b8d3ce5 100644 --- a/monarch_hyperactor/src/pytokio.rs +++ b/monarch_hyperactor/src/pytokio.rs @@ -6,6 +6,38 @@ * LICENSE file in the root directory of this source tree. */ +/// Pytokio allows Python coroutines to await Rust futures, in specific contexts. +/// +/// A PythonTask is constructed in Python from `PythonTask.from_coroutine()`: +/// +/// ``` +/// async def task(): +/// # ... async work, await other python tasks +/// task = PythonTask.from_coroutine(coro=task()) +/// ``` +/// +/// The task may only await *other* PythonTasks; it is an error to await arbitrary +/// Python awaitables. In this way, Pytokio is a way to use Python to compose Tokio futures. +/// +/// A task can be spawned in order to produce an awaitable that can be awaited in +/// any async context: +/// +/// ``` +/// shared = task.spawn() +/// result = await shared +/// ``` +/// +/// Spawn spawns a tokio task that drives the coroutine to completion, and, using the Python +/// awaitable protocol, allows those coroutines to await other Tokio futures in turn. +/// +/// PythonTasks can also be awaited synchronously by `block_on`: +/// +/// ``` +/// result = task.block_on() +/// ``` +/// +/// This allows PythonTasks to be used in either async or sync contexts -- the underlying +/// code executes in exactly the same way, driven by an underlying tokio task. use std::error::Error; use std::future::Future; use std::pin::Pin; From 9e9cc19d8a515b7f9e131f28ce26440cfb0daec7 Mon Sep 17 00:00:00 2001 From: Marius Eriksen Date: Thu, 30 Oct 2025 10:48:14 -0700 Subject: [PATCH 2/2] Update on "[monarch] document pytokio" We keep getting questions about how this works. This is an attempt to document it in simple terms. Differential Revision: [D85870468](https://our.internmc.facebook.com/intern/diff/D85870468/) **NOTE FOR REVIEWERS**: This PR has internal Meta-specific changes or comments, please review them on [Phabricator](https://our.internmc.facebook.com/intern/diff/D85870468/)! [ghstack-poisoned] --- monarch_hyperactor/src/pytokio.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monarch_hyperactor/src/pytokio.rs b/monarch_hyperactor/src/pytokio.rs index c8b8d3ce5..0021d8c3f 100644 --- a/monarch_hyperactor/src/pytokio.rs +++ b/monarch_hyperactor/src/pytokio.rs @@ -10,7 +10,7 @@ /// /// A PythonTask is constructed in Python from `PythonTask.from_coroutine()`: /// -/// ``` +/// ```ignore /// async def task(): /// # ... async work, await other python tasks /// task = PythonTask.from_coroutine(coro=task()) @@ -22,7 +22,7 @@ /// A task can be spawned in order to produce an awaitable that can be awaited in /// any async context: /// -/// ``` +/// ```ignore /// shared = task.spawn() /// result = await shared /// ``` @@ -32,7 +32,7 @@ /// /// PythonTasks can also be awaited synchronously by `block_on`: /// -/// ``` +/// ```ignore /// result = task.block_on() /// ``` ///