77 lines
1.7 KiB
Rust
77 lines
1.7 KiB
Rust
|
use pyo3::{
|
||
|
prelude::*,
|
||
|
types::{PyModule, PyTuple},
|
||
|
};
|
||
|
|
||
|
use anyhow::Result;
|
||
|
|
||
|
pub enum PythonScript<'a> {
|
||
|
File(&'a [u8]),
|
||
|
Path(&'a str),
|
||
|
}
|
||
|
|
||
|
impl<'a> From<&'a [u8]> for PythonScript<'a> {
|
||
|
fn from(content: &'a [u8]) -> Self {
|
||
|
PythonScript::File(content)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl<'a> From<&'a str> for PythonScript<'a> {
|
||
|
fn from(path: &'a str) -> Self {
|
||
|
PythonScript::Path(path)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub struct PythonObject {
|
||
|
script: String,
|
||
|
}
|
||
|
|
||
|
impl PythonObject {
|
||
|
pub fn new<'a>(script: impl Into<PythonScript<'a>>) -> Result<Self> {
|
||
|
Ok(Self {
|
||
|
script: match script.into() {
|
||
|
PythonScript::File(file) => std::str::from_utf8(file)?.to_string(),
|
||
|
PythonScript::Path(path) => std::fs::read_to_string(path)?,
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
|
||
|
pub fn execute_script<D, F, O, I>(&self, function_name: &str, i: I, f: F) -> Result<O>
|
||
|
where
|
||
|
I: ToPyObject,
|
||
|
D: for<'a> FromPyObject<'a>,
|
||
|
F: FnOnce(D) -> Result<O>,
|
||
|
{
|
||
|
Ok(Python::with_gil(|py| -> Result<O> {
|
||
|
let module = PyModule::from_code(py, &self.script, "dummy", "dummy")?;
|
||
|
|
||
|
let args = PyTuple::new(py, [i]);
|
||
|
|
||
|
Ok(f(module.getattr(function_name)?.call1(args)?.extract()?)?)
|
||
|
})?)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod test {
|
||
|
use anyhow::Result;
|
||
|
use std::collections::HashMap;
|
||
|
|
||
|
use super::PythonObject;
|
||
|
|
||
|
#[test]
|
||
|
fn verify_python() -> Result<()> {
|
||
|
let cepi_reader = PythonObject::new("resources/cepi_read_function.py")?;
|
||
|
|
||
|
let cepi_data = cepi_reader.execute_script(
|
||
|
"read",
|
||
|
"resources/dummy.xlsx",
|
||
|
|r: HashMap<String, HashMap<String, String>>| Ok(r),
|
||
|
)?;
|
||
|
|
||
|
println!("{:#?}", cepi_data);
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
}
|