feat(python): tentative of Promise based approach

This commit is contained in:
cschen 2024-08-20 17:16:36 +02:00
parent b09c7a2206
commit 72896d87d6
3 changed files with 53 additions and 7 deletions

8
dist/py/build.sh vendored
View file

@ -7,8 +7,16 @@ TARGET_EXT="$($PYO3_PYTHON -c 'import sysconfig; print(sysconfig.get_config_var(
maturin build -i "$PYO3_PYTHON" --out "$WHEEL_DIR"
CODEMPSUBLIME_DIR="../../../codemp-sublime/bindings/"
CODEMPTEST_DIR="../../../codemp-python-test/"
wheels=($WHEEL_DIR/*.whl)
for wheel in $wheels; do
echo "moving $wheel to $CODEMPSUBLIME_DIR"
cp $wheel "$CODEMPSUBLIME_DIR"
cp $wheel "$CODEMPTEST_DIR"
done
cd "$CODEMPSUBLIME_DIR"
source .venv/bin/activate
pip install $wheel --force-reinstall

View file

@ -15,11 +15,15 @@ use crate::{
cursor::Controller as CursorController,
Client, Workspace,
};
use pyo3::exceptions::{PyConnectionError, PyRuntimeError, PySystemError};
use pyo3::prelude::*;
use pyo3::{
exceptions::{PyConnectionError, PyRuntimeError, PySystemError},
ffi::PyFunctionObject,
types::PyFunction,
};
use tokio::sync::watch;
fn tokio() -> &'static tokio::runtime::Runtime {
pub fn tokio() -> &'static tokio::runtime::Runtime {
static RT: OnceLock<tokio::runtime::Runtime> = OnceLock::new();
RT.get_or_init(|| {
tokio::runtime::Builder::new_current_thread()
@ -49,6 +53,16 @@ where
}
}
#[macro_export]
macro_rules! a_sync {
($($clone:ident)* => $x:expr) => {
{
$(let $clone = $clone.clone();)*
Ok(Promise(Some($crate::ffi::python::tokio().spawn(async move { $x }))))
}
};
}
#[macro_export]
macro_rules! spawn_future_allow_threads {
($fut:expr) => {
@ -145,8 +159,29 @@ impl PyLogger {
async fn listen(&mut self) -> Option<String> {
if self.0.changed().await.is_ok() {
return Some(self.0.borrow().clone());
} else {
return None;
}
None
}
}
#[pyclass]
pub struct Promise(Option<tokio::task::JoinHandle<PyResult<PyObject>>>);
#[pymethods]
impl Promise {
#[pyo3(name = "await")]
fn a_wait(&mut self) -> PyResult<PyObject> {
match self.0.take() {
None => Err(PySystemError::new_err(
"promise can't be awaited multiple times!",
)),
Some(x) => match tokio().block_on(x) {
Err(e) => Err(PySystemError::new_err(format!(
"error awaiting promise: {e}"
))),
Ok(res) => res,
},
}
}
}

View file

@ -5,6 +5,8 @@ use pyo3::prelude::*;
use crate::spawn_future;
use super::Promise;
#[pymethods]
impl Workspace {
// join a workspace
@ -30,9 +32,10 @@ impl Workspace {
}
#[pyo3(name = "event")]
async fn pyevent(&self) -> crate::Result<crate::api::Event> {
let rc = self.clone();
spawn_future!(rc.event()).await.unwrap()
fn pyevent(&self) -> Promise {
crate::a_sync! { self =>
self.event().await
}
}
#[pyo3(name = "fetch_buffers")]