mirror of
https://github.com/facebook/sapling.git
synced 2024-12-24 05:21:49 +03:00
cpython-async: expose Rust Future to Python
Summary: Add a `PyFuture<F>` type that can be used as return type in binding function. It converts Rust Future to a Python object with an `await` method so Python can access the value stored in the future. Unlike `TStream`, it's currently only designed to support Rust->Python one way conversion so it looks simpler. Reviewed By: kulshrax Differential Revision: D23799644 fbshipit-source-id: da4a322527ad9bb4c2dbaa1c302147b784d1ee41
This commit is contained in:
parent
41b200c8d8
commit
7f1c05dd74
48
eden/scm/lib/cpython-async/src/future.rs
Normal file
48
eden/scm/lib/cpython-async/src/future.rs
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This software may be used and distributed according to the terms of the
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
use cpython_ext::cpython::*;
|
||||
use cpython_ext::ResultPyErrExt;
|
||||
use futures::future::BoxFuture;
|
||||
use futures::future::Future;
|
||||
use futures::future::FutureExt;
|
||||
use std::cell::RefCell;
|
||||
|
||||
// Type to make Python able to reason about a Rust future.
|
||||
//
|
||||
// Unlike TStream, it does not support typed lossless Python -> Rust conversion.
|
||||
py_class!(pub class future |py| {
|
||||
data inner: RefCell<Option<BoxFuture<'static, PyResult<PyObject>>>>;
|
||||
|
||||
/// Resolve the future and return the resolved object.
|
||||
def wait(&self) -> PyResult<PyObject> {
|
||||
let mut inner = None;
|
||||
std::mem::swap(&mut inner, &mut self.inner(py).borrow_mut());
|
||||
|
||||
match inner {
|
||||
Some(future) => async_runtime::block_on_future(future),
|
||||
None => Err(PyErr::new::<exc::ValueError, _>(py, "future was already waited")),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
impl future {
|
||||
/// Convert Rust Future to Python object.
|
||||
pub fn new<T, E, F>(py: Python, f: F) -> PyResult<Self>
|
||||
where
|
||||
T: ToPyObject,
|
||||
E: Into<anyhow::Error>,
|
||||
F: Future<Output = Result<T, E>> + Send + 'static,
|
||||
{
|
||||
let future = f.map(|v| {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
v.map_pyerr(py).map(|v| v.into_py_object(py).into_object())
|
||||
});
|
||||
Self::create_instance(py, RefCell::new(Some(Box::pin(future))))
|
||||
}
|
||||
}
|
@ -11,9 +11,14 @@
|
||||
//!
|
||||
//! The `TStream` type provides easy, and lossless conversion between
|
||||
//! Rust `Stream` and Python objects.
|
||||
//!
|
||||
//! The `PyFuture` type provides a way to export Rust `Future` to
|
||||
//! Python.
|
||||
|
||||
mod future;
|
||||
mod stream;
|
||||
|
||||
pub use future::future as PyFuture;
|
||||
pub use stream::TStream;
|
||||
|
||||
// Used by py_stream_class!.
|
||||
|
Loading…
Reference in New Issue
Block a user