diff --git a/src/ffi/python/mod.rs b/src/ffi/python/mod.rs index a5394e2..1f29582 100644 --- a/src/ffi/python/mod.rs +++ b/src/ffi/python/mod.rs @@ -2,11 +2,6 @@ pub mod client; pub mod controllers; pub mod workspace; -use std::{ - future::{poll_fn, Future}, - task::Poll, -}; - use crate::{ api::{Cursor, TextChange}, buffer::Controller as BufferController, @@ -36,34 +31,34 @@ pub fn tokio() -> &'static tokio::runtime::Runtime { }) } -// // workaround to allow the GIL to be released across awaits, waiting on -// // https://github.com/PyO3/pyo3/pull/3610 -// struct AllowThreads(F); +#[pyclass] +pub struct Promise(Option>>); -// impl Future for AllowThreads -// where -// F: Future + Unpin + Send, -// F::Output: Send, -// { -// type Output = F::Output; +#[pymethods] +impl Promise { + #[pyo3(name = "wait")] + fn _await(&mut self) -> PyResult { + match self.0.take() { + None => Err(PyRuntimeError::new_err( + "promise can't be awaited multiple times!", + )), + Some(x) => match tokio().block_on(x) { + Err(e) => Err(PyRuntimeError::new_err(format!( + "error awaiting promise: {e}" + ))), + Ok(res) => res, + }, + } + } -// fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { -// let waker = cx.waker(); -// let fut = unsafe { self.map_unchecked_mut(|e| &mut e.0) }; -// Python::with_gil(|py| py.allow_threads(|| fut.poll(&mut Context::from_waker(waker)))) -// } -// } -// #[macro_export] -// macro_rules! spawn_future_allow_threads { -// ($fut:expr) => { -// $crate::ffi::python::tokio().spawn($crate::ffi::python::AllowThreads(Box::pin( -// async move { -// tracing::info!("running future from rust."); -// $fut.await -// }, -// ))) -// }; -// } + fn done(&self) -> PyResult { + if let Some(handle) = &self.0 { + Ok(handle.is_finished()) + } else { + Err(PyRuntimeError::new_err("promise was already awaited.")) + } + } +} #[macro_export] macro_rules! a_sync { @@ -80,7 +75,7 @@ struct LoggerProducer(mpsc::UnboundedSender); impl std::io::Write for LoggerProducer { fn write(&mut self, buf: &[u8]) -> std::io::Result { - let _ = self.0.send(String::from_utf8_lossy(buf).to_string()); // ignore: logger disconnected or with full buffer + let _ = self.0.send(String::from_utf8_lossy(buf).to_string()); Ok(buf.len()) } @@ -140,10 +135,10 @@ fn init(logging_cb: Py, debug: bool) -> PyResult { tokio().block_on(async move { tokio::select! { biased; + _ = rt_stop_rx => { todo!() }, Some(msg) = rx.recv() => { let _ = Python::with_gil(|py| logging_cb.call1(py, (msg,))); }, - _ = rt_stop_rx => { todo!() }, } }) }); @@ -153,34 +148,6 @@ fn init(logging_cb: Py, debug: bool) -> PyResult { } } -#[pyclass] -pub struct Promise(Option>>); - -#[pymethods] -impl Promise { - #[pyo3(name = "wait")] - fn _await(&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, - }, - } - } - - fn is_done(&self) -> bool { - if let Some(handle) = self.0 { - return handle.is_finished(); - } - false - } -} - impl From for PyErr { fn from(value: crate::Error) -> Self { match value { diff --git a/src/ffi/python/workspace.rs b/src/ffi/python/workspace.rs index 4bf9ba5..7dc5102 100644 --- a/src/ffi/python/workspace.rs +++ b/src/ffi/python/workspace.rs @@ -51,7 +51,7 @@ impl Workspace { #[pyo3(name = "list_buffer_users")] fn pylist_buffer_users(&self, path: String) -> PyResult { - // crate::Result> { + // crate::Result> let this = self.clone(); a_sync!(this.list_buffer_users(path.as_str()).await) } @@ -83,6 +83,7 @@ impl Workspace { } #[pyo3(name = "filetree")] + #[pyo3(signature = (filter=None))] fn pyfiletree(&self, filter: Option<&str>) -> Vec { self.filetree(filter) }