diff --git a/dist/py/build.sh b/dist/py/build.sh index b700e6c..d48d0a0 100755 --- a/dist/py/build.sh +++ b/dist/py/build.sh @@ -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 + diff --git a/src/ffi/python/mod.rs b/src/ffi/python/mod.rs index f89af03..c52a126 100644 --- a/src/ffi/python/mod.rs +++ b/src/ffi/python/mod.rs @@ -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 = 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 { if self.0.changed().await.is_ok() { return Some(self.0.borrow().clone()); - } else { - return None; + } + + None + } +} + +#[pyclass] +pub struct Promise(Option>>); + +#[pymethods] +impl Promise { + #[pyo3(name = "await")] + fn a_wait(&mut self) -> PyResult { + 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, + }, } } } diff --git a/src/ffi/python/workspace.rs b/src/ffi/python/workspace.rs index ebb5d03..4257bd4 100644 --- a/src/ffi/python/workspace.rs +++ b/src/ffi/python/workspace.rs @@ -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 { - 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")]