diff --git a/dist/py/codemp.pyi b/dist/py/codemp.pyi index 5a92bbc..528f37f 100644 --- a/dist/py/codemp.pyi +++ b/dist/py/codemp.pyi @@ -8,7 +8,7 @@ class Driver: def stop(self) -> None: ... -def init(logger_cb: Callable, debug: bool) -> Driver: ... +def init(logger_cb: Callable[[str], None], debug: bool) -> Driver: ... class Promise[T]: """ @@ -19,8 +19,8 @@ class Promise[T]: It can either be used directly or you can wrap it inside a future python side. """ - def wait(self) -> T: ... - def is_done(self) -> bool: ... + def wait(self) -> T: ... + def is_done(self) -> bool: ... class TextChange: """ @@ -31,10 +31,10 @@ class TextChange: end: int content: str - def is_delete(self) -> bool: ... - def is_insert(self) -> bool: ... - def is_empty(self) -> bool: ... - def apply(self, txt: str) -> str: ... + def is_delete(self) -> bool: ... + def is_insert(self) -> bool: ... + def is_empty(self) -> bool: ... + def apply(self, txt: str) -> str: ... class BufferController: @@ -42,15 +42,18 @@ class BufferController: Handle to the controller for a specific buffer, which manages the back and forth of operations to and from other peers. """ - def content(self) -> Promise[str]: ... + def content(self) -> Promise[str]: ... def send(self, start: int, end: int, - txt: str) -> Promise[None]: ... - def try_recv(self) -> Optional[TextChange]: ... - def recv(self) -> Promise[TextChange]: ... - def poll(self) -> Promise[None]: ... - def stop(self) -> bool: ... + txt: str) -> Promise[None]: ... + def try_recv(self) -> Optional[TextChange]: ... + def recv(self) -> Promise[TextChange]: ... + def poll(self) -> Promise[None]: ... + def callback(self, + cb: Callable[[BufferController], None]) -> None: ... + def clear_callback(self) -> None: ... + def stop(self) -> bool: ... @@ -72,11 +75,14 @@ class CursorController: def send(self, path: str, start: Tuple[int, int], - end: Tuple[int, int]) -> Promise[None]: ... - def try_recv(self) -> Optional[Cursor]: ... - def recv(self) -> Promise[Cursor]: ... - def poll(self) -> Promise[None]: ... - def stop(self) -> bool: ... + end: Tuple[int, int]) -> Promise[None]: ... + def try_recv(self) -> Optional[Cursor]: ... + def recv(self) -> Promise[Cursor]: ... + def poll(self) -> Promise[None]: ... + def callback(self, + cb: Callable[[CursorController], None]) -> None: ... + def clear_callback(self) -> None: ... + def stop(self) -> bool: ... class Workspace: @@ -84,18 +90,18 @@ class Workspace: Handle to a workspace inside codemp. It manages buffers. A cursor is tied to the single workspace. """ - def create(self, path: str) -> Promise[None]: ... - def attach(self, path: str) -> Promise[BufferController]: ... - def detach(self, path: str) -> bool: ... - def fetch_buffers(self) -> Promise[None]: ... - def fetch_users(self) -> Promise[None]: ... - def list_buffer_users(self, path: str) -> Promise[list[str]]: ... - def delete(self, path: str) -> Promise[None]: ... - def id(self) -> str: ... - def cursor(self) -> CursorController: ... - def buffer_by_name(self, path: str) -> Optional[BufferController]: ... - def buffer_list(self) -> list[str]: ... - def filetree(self, filter: Optional[str]) -> list[str]: ... + def create(self, path: str) -> Promise[None]: ... + def attach(self, path: str) -> Promise[BufferController]: ... + def detach(self, path: str) -> bool: ... + def fetch_buffers(self) -> Promise[None]: ... + def fetch_users(self) -> Promise[None]: ... + def list_buffer_users(self, path: str) -> Promise[list[str]]: ... + def delete(self, path: str) -> Promise[None]: ... + def id(self) -> str: ... + def cursor(self) -> CursorController: ... + def buffer_by_name(self, path: str) -> Optional[BufferController]: ... + def buffer_list(self) -> list[str]: ... + def filetree(self, filter: Optional[str]) -> list[str]: ... class Client: @@ -103,9 +109,11 @@ class Client: Handle to the actual client that manages the session. It manages the connection to a server and joining/creating new workspaces """ - def __new__(cls, host: str, username: str, password: str) -> None: ... - def join_workspace(self, workspace: str) -> Promise[Workspace]: ... - def leave_workspace(self, workspace: str) -> bool: ... - def get_workspace(self, id: str) -> Workspace: ... - def active_workspaces(self) -> list[str]: ... - def user_id(self) -> str: ... + def __new__(cls, + host: str, + username: str, password: str) -> Client: ... + def join_workspace(self, workspace: str) -> Promise[Workspace]: ... + def leave_workspace(self, workspace: str) -> bool: ... + def get_workspace(self, id: str) -> Workspace: ... + def active_workspaces(self) -> list[str]: ... + def user_id(self) -> str: ... diff --git a/src/ffi/python/controllers.rs b/src/ffi/python/controllers.rs index d599ca7..f68f14f 100644 --- a/src/ffi/python/controllers.rs +++ b/src/ffi/python/controllers.rs @@ -4,6 +4,7 @@ use crate::api::TextChange; use crate::buffer::Controller as BufferController; use crate::cursor::Controller as CursorController; use pyo3::prelude::*; +use pyo3::types::PyFunction; use super::Promise; use crate::a_sync_allow_threads; @@ -48,6 +49,23 @@ impl CursorController { a_sync_allow_threads!(py, this.poll().await) } + #[pyo3(name = "callback")] + fn pycallback(&self, py: Python, cb: Py) { + py.allow_threads(move || { + self.callback(move |ctl| { + Python::with_gil(|py| { + // TODO what to do with this error? + let _ = cb.call1(py, (ctl,)); + }) + }) + }) + } + + #[pyo3(name = "clear_callback")] + fn pyclear_callback(&self) { + self.clear_callback(); + } + #[pyo3(name = "stop")] fn pystop(&self) -> bool { self.stop() @@ -94,6 +112,23 @@ impl BufferController { a_sync_allow_threads!(py, this.poll().await) } + #[pyo3(name = "callback")] + fn pycallback(&self, py: Python, cb: Py) { + py.allow_threads(move || { + self.callback(move |ctl| { + Python::with_gil(|py| { + // TODO what to do with this error? + let _ = cb.call1(py, (ctl,)); + }) + }) + }) + } + + #[pyo3(name = "clear_callback")] + fn pyclear_callback(&self) { + self.clear_callback(); + } + #[pyo3(name = "stop")] fn pystop(&self) -> bool { self.stop()