feat(python): added callback support, reaching feature parity with the lib.

This commit is contained in:
cschen 2024-08-22 15:22:51 +02:00
parent 4004f2011f
commit 472c33f734
2 changed files with 79 additions and 36 deletions

80
dist/py/codemp.pyi vendored
View file

@ -8,7 +8,7 @@ class Driver:
def stop(self) -> None: ... 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]: 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. It can either be used directly or you can wrap it inside a future python side.
""" """
def wait(self) -> T: ... def wait(self) -> T: ...
def is_done(self) -> bool: ... def is_done(self) -> bool: ...
class TextChange: class TextChange:
""" """
@ -31,10 +31,10 @@ class TextChange:
end: int end: int
content: str content: str
def is_delete(self) -> bool: ... def is_delete(self) -> bool: ...
def is_insert(self) -> bool: ... def is_insert(self) -> bool: ...
def is_empty(self) -> bool: ... def is_empty(self) -> bool: ...
def apply(self, txt: str) -> str: ... def apply(self, txt: str) -> str: ...
class BufferController: class BufferController:
@ -42,15 +42,18 @@ class BufferController:
Handle to the controller for a specific buffer, which manages the back and forth Handle to the controller for a specific buffer, which manages the back and forth
of operations to and from other peers. of operations to and from other peers.
""" """
def content(self) -> Promise[str]: ... def content(self) -> Promise[str]: ...
def send(self, def send(self,
start: int, start: int,
end: int, end: int,
txt: str) -> Promise[None]: ... txt: str) -> Promise[None]: ...
def try_recv(self) -> Optional[TextChange]: ... def try_recv(self) -> Optional[TextChange]: ...
def recv(self) -> Promise[TextChange]: ... def recv(self) -> Promise[TextChange]: ...
def poll(self) -> Promise[None]: ... def poll(self) -> Promise[None]: ...
def stop(self) -> bool: ... 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, def send(self,
path: str, path: str,
start: Tuple[int, int], start: Tuple[int, int],
end: Tuple[int, int]) -> Promise[None]: ... end: Tuple[int, int]) -> Promise[None]: ...
def try_recv(self) -> Optional[Cursor]: ... def try_recv(self) -> Optional[Cursor]: ...
def recv(self) -> Promise[Cursor]: ... def recv(self) -> Promise[Cursor]: ...
def poll(self) -> Promise[None]: ... def poll(self) -> Promise[None]: ...
def stop(self) -> bool: ... def callback(self,
cb: Callable[[CursorController], None]) -> None: ...
def clear_callback(self) -> None: ...
def stop(self) -> bool: ...
class Workspace: class Workspace:
@ -84,18 +90,18 @@ class Workspace:
Handle to a workspace inside codemp. It manages buffers. Handle to a workspace inside codemp. It manages buffers.
A cursor is tied to the single workspace. A cursor is tied to the single workspace.
""" """
def create(self, path: str) -> Promise[None]: ... def create(self, path: str) -> Promise[None]: ...
def attach(self, path: str) -> Promise[BufferController]: ... def attach(self, path: str) -> Promise[BufferController]: ...
def detach(self, path: str) -> bool: ... def detach(self, path: str) -> bool: ...
def fetch_buffers(self) -> Promise[None]: ... def fetch_buffers(self) -> Promise[None]: ...
def fetch_users(self) -> Promise[None]: ... def fetch_users(self) -> Promise[None]: ...
def list_buffer_users(self, path: str) -> Promise[list[str]]: ... def list_buffer_users(self, path: str) -> Promise[list[str]]: ...
def delete(self, path: str) -> Promise[None]: ... def delete(self, path: str) -> Promise[None]: ...
def id(self) -> str: ... def id(self) -> str: ...
def cursor(self) -> CursorController: ... def cursor(self) -> CursorController: ...
def buffer_by_name(self, path: str) -> Optional[BufferController]: ... def buffer_by_name(self, path: str) -> Optional[BufferController]: ...
def buffer_list(self) -> list[str]: ... def buffer_list(self) -> list[str]: ...
def filetree(self, filter: Optional[str]) -> list[str]: ... def filetree(self, filter: Optional[str]) -> list[str]: ...
class Client: class Client:
@ -103,9 +109,11 @@ class Client:
Handle to the actual client that manages the session. It manages the connection Handle to the actual client that manages the session. It manages the connection
to a server and joining/creating new workspaces to a server and joining/creating new workspaces
""" """
def __new__(cls, host: str, username: str, password: str) -> None: ... def __new__(cls,
def join_workspace(self, workspace: str) -> Promise[Workspace]: ... host: str,
def leave_workspace(self, workspace: str) -> bool: ... username: str, password: str) -> Client: ...
def get_workspace(self, id: str) -> Workspace: ... def join_workspace(self, workspace: str) -> Promise[Workspace]: ...
def active_workspaces(self) -> list[str]: ... def leave_workspace(self, workspace: str) -> bool: ...
def user_id(self) -> str: ... def get_workspace(self, id: str) -> Workspace: ...
def active_workspaces(self) -> list[str]: ...
def user_id(self) -> str: ...

View file

@ -4,6 +4,7 @@ use crate::api::TextChange;
use crate::buffer::Controller as BufferController; use crate::buffer::Controller as BufferController;
use crate::cursor::Controller as CursorController; use crate::cursor::Controller as CursorController;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::PyFunction;
use super::Promise; use super::Promise;
use crate::a_sync_allow_threads; use crate::a_sync_allow_threads;
@ -48,6 +49,23 @@ impl CursorController {
a_sync_allow_threads!(py, this.poll().await) a_sync_allow_threads!(py, this.poll().await)
} }
#[pyo3(name = "callback")]
fn pycallback(&self, py: Python, cb: Py<PyFunction>) {
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")] #[pyo3(name = "stop")]
fn pystop(&self) -> bool { fn pystop(&self) -> bool {
self.stop() self.stop()
@ -94,6 +112,23 @@ impl BufferController {
a_sync_allow_threads!(py, this.poll().await) a_sync_allow_threads!(py, this.poll().await)
} }
#[pyo3(name = "callback")]
fn pycallback(&self, py: Python, cb: Py<PyFunction>) {
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")] #[pyo3(name = "stop")]
fn pystop(&self) -> bool { fn pystop(&self) -> bool {
self.stop() self.stop()