mirror of
https://github.com/hexedtech/codemp.git
synced 2024-12-22 21:04:53 +01:00
fix(python): changed entry point. separated logger from driver.
This commit is contained in:
parent
7fc25cd332
commit
487a490887
5 changed files with 92 additions and 89 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -228,7 +228,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "codemp"
|
||||
version = "0.6.2"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"codemp-proto",
|
||||
|
@ -254,7 +254,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "codemp-proto"
|
||||
version = "0.6.1"
|
||||
version = "0.7.0"
|
||||
source = "git+ssh://git@github.com/hexedtech/codemp-proto.git?tag=v0.7.0#11cc52e837a2e568c14ef3bc3a70e8124564f5aa"
|
||||
dependencies = [
|
||||
"prost",
|
||||
"tonic",
|
||||
|
|
78
dist/py/codemp.pyi
vendored
78
dist/py/codemp.pyi
vendored
|
@ -8,7 +8,9 @@ class Driver:
|
|||
def stop(self) -> None: ...
|
||||
|
||||
|
||||
def init(logger_cb: Callable[[str], None], debug: bool) -> Driver: ...
|
||||
def init() -> Driver: ...
|
||||
def set_logger(logger_cb: Callable[[str], None], debug: bool) -> bool: ...
|
||||
def connect(host: str, username: str, password: str) -> Promise[Client]: ...
|
||||
|
||||
class Promise[T]:
|
||||
"""
|
||||
|
@ -22,6 +24,41 @@ class Promise[T]:
|
|||
def wait(self) -> T: ...
|
||||
def is_done(self) -> bool: ...
|
||||
|
||||
class Client:
|
||||
"""
|
||||
Handle to the actual client that manages the session. It manages the connection
|
||||
to a server and joining/creating new workspaces
|
||||
"""
|
||||
def join_workspace(self, workspace: str) -> Promise[Workspace]: ...
|
||||
def create_workspace(self, workspace: str) -> Promise[None]: ...
|
||||
def delete_workspace(self, workspace: str) -> Promise[None]: ...
|
||||
def invite_to_workspace(self, workspace: str, username: str) -> Promise[None]: ...
|
||||
def list_workspaces(self, owned: bool, invited: bool) -> Promise[list[str]]: ...
|
||||
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 user_name(self) -> str: ...
|
||||
def refresh(self) -> Promise[None]: ...
|
||||
|
||||
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]: ...
|
||||
|
||||
class TextChange:
|
||||
"""
|
||||
Editor agnostic representation of a text change, it translate between internal
|
||||
|
@ -85,42 +122,3 @@ class CursorController:
|
|||
def clear_callback(self) -> None: ...
|
||||
def stop(self) -> bool: ...
|
||||
|
||||
|
||||
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]: ...
|
||||
|
||||
|
||||
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) -> Client: ...
|
||||
def join_workspace(self, workspace: str) -> Promise[Workspace]: ...
|
||||
def create_workspace(self, workspace: str) -> Promise[None]: ...
|
||||
def delete_workspace(self, workspace: str) -> Promise[None]: ...
|
||||
def invite_to_workspace(self, workspace: str, username: str) -> Promise[None]: ...
|
||||
def list_workspaces(self, owned: bool, invited: bool) -> Promise[list[str]]: ...
|
||||
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 user_name(self) -> str: ...
|
||||
def refresh(self) -> Promise[None]: ...
|
||||
|
|
2
dist/py/pyproject.toml
vendored
2
dist/py/pyproject.toml
vendored
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "codemp"
|
||||
version = "0.6.2"
|
||||
version = "0.7.0"
|
||||
description = "Cooperative multi-player coding"
|
||||
requires-python = ">=3.8"
|
||||
license = {file = "../../LICENSE"}
|
||||
|
|
|
@ -2,25 +2,11 @@ use crate::workspace::Workspace;
|
|||
use crate::Client;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use super::tokio;
|
||||
|
||||
#[pymethods]
|
||||
impl Client {
|
||||
#[new]
|
||||
fn __new__(host: String, username: String, password: String) -> crate::Result<Self> {
|
||||
tokio().block_on(Client::connect(host, username, password))
|
||||
}
|
||||
|
||||
// #[pyo3(name = "join_workspace")]
|
||||
// async fn pyjoin_workspace(&self, workspace: String) -> JoinHandle<crate::Result<Workspace>> {
|
||||
// tracing::info!("attempting to join the workspace {}", workspace);
|
||||
|
||||
// let this = self.clone();
|
||||
// async {
|
||||
// tokio()
|
||||
// .spawn(async move { this.join_workspace(workspace).await })
|
||||
// .await
|
||||
// }
|
||||
// #[new]
|
||||
// fn __new__(host: String, username: String, password: String) -> crate::Result<Self> {
|
||||
// tokio().block_on(Client::connect(host, username, password))
|
||||
// }
|
||||
|
||||
#[pyo3(name = "join_workspace")]
|
||||
|
@ -52,14 +38,24 @@ impl Client {
|
|||
}
|
||||
|
||||
#[pyo3(name = "invite_to_workspace")]
|
||||
fn pyinvite_to_workspace(&self, py: Python<'_>, workspace: String, user: String) -> PyResult<super::Promise> {
|
||||
fn pyinvite_to_workspace(
|
||||
&self,
|
||||
py: Python<'_>,
|
||||
workspace: String,
|
||||
user: String,
|
||||
) -> PyResult<super::Promise> {
|
||||
tracing::info!("attempting to invite {user} to workspace {workspace}");
|
||||
let this = self.clone();
|
||||
crate::a_sync_allow_threads!(py, this.invite_to_workspace(workspace, user).await)
|
||||
}
|
||||
|
||||
#[pyo3(name = "list_workspaces")]
|
||||
fn pylist_workspaces(&self, py: Python<'_>, owned: bool, invited: bool) -> PyResult<super::Promise> {
|
||||
fn pylist_workspaces(
|
||||
&self,
|
||||
py: Python<'_>,
|
||||
owned: bool,
|
||||
invited: bool,
|
||||
) -> PyResult<super::Promise> {
|
||||
tracing::info!("attempting to list workspaces");
|
||||
let this = self.clone();
|
||||
crate::a_sync_allow_threads!(py, this.list_workspaces(owned, invited).await)
|
||||
|
|
|
@ -131,8 +131,30 @@ impl Driver {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn init(py: Python, logging_cb: Py<PyFunction>, debug: bool) -> PyResult<Driver> {
|
||||
fn init() -> PyResult<Driver> {
|
||||
let (rt_stop_tx, mut rt_stop_rx) = oneshot::channel::<()>();
|
||||
std::thread::spawn(move || {
|
||||
tokio().block_on(async move {
|
||||
tracing::info!("started runtime driver...");
|
||||
tokio::select! {
|
||||
() = std::future::pending::<()>() => {},
|
||||
_ = &mut rt_stop_rx => {}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
Ok(Driver(Some(rt_stop_tx)))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn connect(host: String, username: String, password: String) -> PyResult<Promise> {
|
||||
a_sync!(Client::connect(host, username, password).await)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn set_logger(logging_cb: Py<PyFunction>, debug: bool) -> bool {
|
||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||
let level = if debug {
|
||||
tracing::Level::DEBUG
|
||||
|
@ -151,38 +173,22 @@ fn init(py: Python, logging_cb: Py<PyFunction>, debug: bool) -> PyResult<Driver>
|
|||
.with_source_location(false)
|
||||
.compact();
|
||||
|
||||
let log_subscribing = tracing_subscriber::fmt()
|
||||
let log_subscribed = tracing_subscriber::fmt()
|
||||
.with_ansi(false)
|
||||
.event_format(format)
|
||||
.with_max_level(level)
|
||||
.with_writer(std::sync::Mutex::new(LoggerProducer(tx)))
|
||||
.try_init();
|
||||
.try_init()
|
||||
.is_ok();
|
||||
|
||||
let (rt_stop_tx, mut rt_stop_rx) = oneshot::channel::<()>();
|
||||
|
||||
match log_subscribing {
|
||||
Ok(_) => {
|
||||
// the runtime is driven by the logger awaiting messages from codemp and echoing them back to
|
||||
// a provided logger.
|
||||
py.allow_threads(move || {
|
||||
std::thread::spawn(move || {
|
||||
tokio().block_on(async move {
|
||||
loop {
|
||||
tokio::select! {
|
||||
biased;
|
||||
Some(msg) = rx.recv() => {
|
||||
let _ = Python::with_gil(|py| logging_cb.call1(py, (msg,)));
|
||||
},
|
||||
_ = &mut rt_stop_rx => { break }, // a bit brutal but will do for now.
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
Ok(Driver(Some(rt_stop_tx)))
|
||||
}
|
||||
Err(_) => Err(PyRuntimeError::new_err("codemp was already initialised.")),
|
||||
if log_subscribed {
|
||||
tokio().spawn(async move {
|
||||
while let Some(msg) = rx.recv().await {
|
||||
let _ = Python::with_gil(|py| logging_cb.call1(py, (msg,)));
|
||||
}
|
||||
});
|
||||
}
|
||||
log_subscribed
|
||||
}
|
||||
|
||||
impl From<crate::Error> for PyErr {
|
||||
|
@ -211,6 +217,8 @@ impl IntoPy<PyObject> for crate::api::User {
|
|||
#[pymodule]
|
||||
fn codemp(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
m.add_function(wrap_pyfunction!(init, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(connect, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(set_logger, m)?)?;
|
||||
m.add_class::<Driver>()?;
|
||||
|
||||
m.add_class::<TextChange>()?;
|
||||
|
|
Loading…
Reference in a new issue