Skip to content

Commit

Permalink
🦄 refactor: Allow python api be hooted in middle
Browse files Browse the repository at this point in the history
  • Loading branch information
wychlw committed Sep 29, 2024
1 parent 3dd5a8d commit 33afac7
Show file tree
Hide file tree
Showing 11 changed files with 556 additions and 92 deletions.
483 changes: 480 additions & 3 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "tester"
version = "0.1.0"
edition = "2021"
license = "GPL-3.0-or-later" # We used GPL lib

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
Expand All @@ -27,6 +28,7 @@ portable-pty = "0.8.1"
inventory = "0.3.15"
eframe = "0.28.1"
egui_extras = "0.28.1"
termwiz = "0.22.0"

[toolchain]
channel = "nightly"
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![feature(box_into_inner)]
#![feature(macro_metavar_expr_concat)]
#![allow(clippy::module_inception)]
#![feature(new_range_api)]

pub mod consts;
pub mod cli;
Expand Down
6 changes: 3 additions & 3 deletions src/pythonapi/asciicast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use pyo3::{exceptions::PyRuntimeError, pyclass, pymethods, PyResult};

use crate::util::anybase::heap_raw;

use super::shell_like::{handle_wrap, PyTty, PyTtyWrapper, TtyType};
use super::shell_like::{handle_wrap, py_tty_inner, PyTty, PyTtyInner, TtyType};

pub fn handle_asciicast(inner: &mut Option<PyTtyWrapper>) -> PyResult<()> {
pub fn handle_asciicast(inner: &mut Option<PyTtyInner>) -> PyResult<()> {
if inner.is_none() {
return Err(PyRuntimeError::new_err(
"You must define at least one valid object",
Expand All @@ -15,7 +15,7 @@ pub fn handle_asciicast(inner: &mut Option<PyTtyWrapper>) -> PyResult<()> {
let be_wrapped = Box::into_inner(be_wrapped);
let tee = Box::new(crate::cli::asciicast::Asciicast::build(be_wrapped));
let tee = tee as TtyType;
*inner = Some(PyTtyWrapper { tty: heap_raw(tee) });
*inner = Some(py_tty_inner(heap_raw(tee)));
Ok(())
}

Expand Down
8 changes: 3 additions & 5 deletions src/pythonapi/deansi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use pyo3::{exceptions::PyRuntimeError, pyclass, pymethods, PyResult};

use crate::{cli::tty::Tty, util::anybase::heap_raw};

use super::shell_like::{handle_wrap, PyTty, PyTtyWrapper, TtyType};
use super::shell_like::{handle_wrap, py_tty_inner, PyTty, PyTtyInner, TtyType};

pub fn handle_deansi(inner: &mut Option<PyTtyWrapper>) -> PyResult<()> {
pub fn handle_deansi(inner: &mut Option<PyTtyInner>) -> PyResult<()> {
if inner.is_none() {
return Err(PyRuntimeError::new_err(
"You must define at least one valid object",
Expand All @@ -15,9 +15,7 @@ pub fn handle_deansi(inner: &mut Option<PyTtyWrapper>) -> PyResult<()> {
let be_wrapped = Box::into_inner(be_wrapped);
let dean = Box::new(crate::cli::deansi::DeANSI::build(be_wrapped));
let dean: Box<dyn Tty + Send> = dean as TtyType;
*inner = Some(PyTtyWrapper {
tty: heap_raw(dean),
});
*inner = Some(py_tty_inner(heap_raw(dean)));
Ok(())
}

Expand Down
11 changes: 3 additions & 8 deletions src/pythonapi/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,15 @@ use crate::{
util::anybase::heap_raw,
};

use super::shell_like::{handle_wrap, PyTty, PyTtyWrapper, TtyType};
use super::shell_like::{handle_wrap, py_tty_inner, PyTty, PyTtyInner, TtyType};

pub fn handle_clitester(inner: &mut Option<PyTtyWrapper>, need_sudo: Option<bool>) -> PyResult<()> {
pub fn handle_clitester(inner: &mut Option<PyTtyInner>, need_sudo: Option<bool>) -> PyResult<()> {
if inner.is_none() {
return Err(PyRuntimeError::new_err(
"You must define at least one valid object",
));
}
let mut be_wrapped = inner.take().unwrap();
if be_wrapped.tty.is_null() {
return Err(PyRuntimeError::new_err(
"You gave me it, you will never own it again.",
));
}
let tty = be_wrapped.safe_take()?;
let tty = Box::into_inner(tty);
let need_sudo = need_sudo.unwrap_or(true);
Expand All @@ -33,7 +28,7 @@ pub fn handle_clitester(inner: &mut Option<PyTtyWrapper>, need_sudo: Option<bool
let res = Box::new(CliTester::build(tty));
res as TtyType
};
*inner = Some(PyTtyWrapper { tty: heap_raw(res) });
*inner = Some(py_tty_inner(heap_raw(res)));
Ok(())
}

Expand Down
18 changes: 7 additions & 11 deletions src/pythonapi/hook.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
use std::error::Error;

use pyo3::{
pyfunction, types::{PyByteArray, PyByteArrayMethods}, Py, PyAny, Python
pyfunction,
types::{PyByteArray, PyByteArrayMethods},
Py, PyAny, Python,
};

use crate::{
cli::tty::Tty, impl_any, util::anybase::heap_raw
};
use crate::{cli::tty::Tty, impl_any, util::anybase::heap_raw};

use super::shell_like::{PyTty, PyTtyWrapper};
use super::shell_like::{py_tty_inner, PyTty};

#[pyfunction]
pub fn build_ttyhook(inner: Py<PyAny>) -> PyTty {
let inner = TtyHook::build(inner);
let inner = Box::new(inner);
let inner = PyTtyWrapper {
tty: heap_raw(inner)
};
PyTty {
inner
}
let inner = py_tty_inner(heap_raw(inner));
PyTty { inner }
}

pub struct TtyHook {
Expand Down
9 changes: 2 additions & 7 deletions src/pythonapi/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use pyo3::{exceptions::PyRuntimeError, pyclass, pymethods, PyResult};

use crate::util::anybase::heap_raw;

use super::shell_like::{PyTty, PyTtyWrapper, TtyType};
use super::shell_like::{py_tty_inner, PyTty, TtyType};

#[pyclass(extends=PyTty, subclass)]
pub struct Serial {}
Expand All @@ -15,11 +15,6 @@ impl Serial {
let serial = crate::cli::serial::Serial::build(port, baud)
.map_err(|e| PyRuntimeError::new_err(e.to_string()))?;
let serial = Box::new(serial) as TtyType;
Ok((
Serial {},
PyTty::build(PyTtyWrapper {
tty: heap_raw(serial),
}),
))
Ok((Serial {}, PyTty::build(py_tty_inner(heap_raw(serial)))))
}
}
15 changes: 4 additions & 11 deletions src/pythonapi/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ use serde::Deserialize;

use crate::util::anybase::heap_raw;

use super::shell_like::{PyTty, PyTtyWrapper, TtyType};
use super::shell_like::{py_tty_inner, PyTty, PyTtyInner, TtyType};

#[derive(Deserialize)]
pub struct ShellConf {
pub shell: Option<String>,
}

pub fn handle_shell(inner: &mut Option<PyTtyWrapper>, shell_conf: ShellConf) -> PyResult<()> {
pub fn handle_shell(inner: &mut Option<PyTtyInner>, shell_conf: ShellConf) -> PyResult<()> {
let shell = shell_conf.shell.as_deref();
let shell = crate::cli::shell::Shell::build(shell)
.map_err(|e| PyRuntimeError::new_err(e.to_string()))?;
Expand All @@ -20,9 +20,7 @@ pub fn handle_shell(inner: &mut Option<PyTtyWrapper>, shell_conf: ShellConf) ->
));
}
let shell = Box::new(shell) as TtyType;
*inner = Some(PyTtyWrapper {
tty: heap_raw(shell),
});
*inner = Some(py_tty_inner(heap_raw(shell)));
Ok(())
}

Expand All @@ -37,11 +35,6 @@ impl Shell {
let shell = crate::cli::shell::Shell::build(shell)
.map_err(|e| PyRuntimeError::new_err(e.to_string()))?;
let shell = Box::new(shell) as TtyType;
Ok((
Shell {},
PyTty::build(PyTtyWrapper {
tty: heap_raw(shell),
}),
))
Ok((Shell {}, PyTty::build(py_tty_inner(heap_raw(shell)))))
}
}
89 changes: 48 additions & 41 deletions src/pythonapi/shell_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,20 @@ use super::{

pub type TtyType = DynTty;

pub struct PyTtyWrapper {
pub tty: *mut TtyType,
pub trait PyTtyWrapper: Send {
fn take(&mut self) -> PyResult<*mut TtyType>;
fn safe_take(&mut self) -> PyResult<Box<TtyType>>;
fn get(&self) -> PyResult<&TtyType>;
fn get_mut(&mut self) -> PyResult<&mut TtyType>;
fn put(&mut self, tty: *mut TtyType) -> PyResult<()>;
}

impl PyTtyWrapper {
pub fn take(&mut self) -> PyResult<*mut TtyType> {
pub struct PyTtyWrapperBasic {
tty: *mut TtyType,
}

impl PyTtyWrapper for PyTtyWrapperBasic {
fn take(&mut self) -> PyResult<*mut TtyType> {
if self.tty.is_null() {
return Err(PyRuntimeError::new_err(
"You gave me it, you will never own it again.",
Expand All @@ -41,37 +49,55 @@ impl PyTtyWrapper {
self.tty = null_mut();
Ok(res)
}
pub fn safe_take(&mut self) -> PyResult<Box<TtyType>> {
fn safe_take(&mut self) -> PyResult<Box<TtyType>> {
let res = self.take()?;
Ok(unsafe { Box::from_raw(res) })
}
pub fn get(&self) -> PyResult<&TtyType> {
fn get(&self) -> PyResult<&TtyType> {
if self.tty.is_null() {
return Err(PyRuntimeError::new_err(
"You gave me it, you will never own it again.",
));
}
Ok(unsafe { &*self.tty })
}
pub fn get_mut(&self) -> PyResult<&mut TtyType> {
fn get_mut(&mut self) -> PyResult<&mut TtyType> {
if self.tty.is_null() {
return Err(PyRuntimeError::new_err(
"You gave me it, you will never own it again.",
));
}
Ok(unsafe { &mut *self.tty })
}
fn put(&mut self, tty: *mut TtyType) -> PyResult<()> {
if !self.tty.is_null() {
return Err(PyRuntimeError::new_err(
"You must take the object before you put another one.",
));
}
self.tty = tty;
Ok(())
}
}

unsafe impl Send for PyTtyWrapper {}
unsafe impl Send for PyTtyWrapperBasic {}
unsafe impl Sync for PyTtyWrapperBasic {}

pub type PyTtyInner = Box<dyn PyTtyWrapper + Send + Sync>;

pub fn py_tty_inner(tty: *mut TtyType) -> PyTtyInner {
let inner = PyTtyWrapperBasic { tty };
let inner = Box::new(inner);
inner as PyTtyInner
}

#[pyclass(subclass)]
pub struct PyTty {
pub inner: PyTtyWrapper,
pub inner: PyTtyInner,
}

impl PyTty {
pub fn build(inner: PyTtyWrapper) -> Self {
pub fn build(inner: PyTtyInner) -> Self {
PyTty { inner }
}
}
Expand All @@ -95,24 +121,19 @@ struct PyTtyExecConf {
sudo: Option<bool>,
}

pub fn handle_wrap(
inner: &mut Option<PyTtyWrapper>,
be_wrapped: Option<&mut PyTty>,
) -> PyResult<()> {
pub fn handle_wrap(inner: &mut Option<PyTtyInner>, be_wrapped: Option<&mut PyTty>) -> PyResult<()> {
if be_wrapped.is_none() {
return Err(PyRuntimeError::new_err(
"be_wrapped must be provided when wrap is true",
));
}
let be_wrapped = be_wrapped.unwrap();

*inner = Some(PyTtyWrapper {
tty: be_wrapped.inner.take()?,
});
*inner = Some(py_tty_inner(be_wrapped.inner.take()?));
Ok(())
}

pub fn handle_simple_recorder(inner: &mut Option<PyTtyWrapper>) -> PyResult<()> {
pub fn handle_simple_recorder(inner: &mut Option<PyTtyInner>) -> PyResult<()> {
if inner.is_none() {
return Err(PyRuntimeError::new_err(
"You must define at least one valid object",
Expand All @@ -123,9 +144,7 @@ pub fn handle_simple_recorder(inner: &mut Option<PyTtyWrapper>) -> PyResult<()>
let tty = Box::into_inner(tty);
let recorder = Box::new(SimpleRecorder::build(tty));
let recorder = recorder as TtyType;
*inner = Some(PyTtyWrapper {
tty: heap_raw(recorder),
});
*inner = Some(py_tty_inner(heap_raw(recorder)));

Ok(())
}
Expand Down Expand Up @@ -219,49 +238,37 @@ impl PyTty {
let inner = inner.downcast::<SimpleRecorder>().unwrap();
let inner = inner.exit();
Ok(PyTty {
inner: PyTtyWrapper {
tty: heap_raw(inner),
},
inner: py_tty_inner(heap_raw(inner)),
})
} else if inner.downcast_ref::<Asciicast>().is_some() {
let inner = inner.downcast::<Asciicast>().unwrap();
let inner = inner.exit();
Ok(PyTty {
inner: PyTtyWrapper {
tty: heap_raw(inner),
},
inner: py_tty_inner(heap_raw(inner)),
})
} else if inner.downcast_ref::<DeANSI>().is_some() {
let inner = inner.downcast::<DeANSI>().unwrap();
let inner = inner.exit();
Ok(PyTty {
inner: PyTtyWrapper {
tty: heap_raw(inner),
},
inner: py_tty_inner(heap_raw(inner)),
})
} else if inner.downcast_ref::<Tee>().is_some() {
let inner = inner.downcast::<Tee>().unwrap();
let inner = inner.exit();
Ok(PyTty {
inner: PyTtyWrapper {
tty: heap_raw(inner),
},
inner: py_tty_inner(heap_raw(inner)),
})
} else if inner.downcast_ref::<CliTester>().is_some() {
let inner = inner.downcast::<CliTester>().unwrap();
let inner = inner.exit();
Ok(PyTty {
inner: PyTtyWrapper {
tty: heap_raw(inner),
},
inner: py_tty_inner(heap_raw(inner)),
})
} else if inner.downcast_ref::<SudoCliTester>().is_some() {
let inner = inner.downcast::<SudoCliTester>().unwrap();
let inner = inner.exit();
Ok(PyTty {
inner: PyTtyWrapper {
tty: heap_raw(inner),
},
inner: py_tty_inner(heap_raw(inner)),
})
} else {
Err(PyRuntimeError::new_err(
Expand Down Expand Up @@ -369,7 +376,7 @@ impl PyTty {
return Err(PyRuntimeError::new_err(e.to_string()));
}
let target = target.unwrap();
other.inner.tty = heap_raw(target);
other.inner.put(heap_raw(target))?;
Ok(())
} else if inner.downcast_ref::<Asciicast>().is_some() {
let inner = inner.downcast_mut::<Asciicast>().unwrap();
Expand All @@ -380,7 +387,7 @@ impl PyTty {
return Err(PyRuntimeError::new_err(e.to_string()));
}
let target = target.unwrap();
other.inner.tty = heap_raw(target);
other.inner.put(heap_raw(target))?;
Ok(())
} else {
Err(PyRuntimeError::new_err(
Expand Down
Loading

0 comments on commit 33afac7

Please sign in to comment.