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>) -> Result { 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(&self, function_name: &str, i: I, f: F) -> Result where I: ToPyObject, D: for<'a> FromPyObject<'a>, F: FnOnce(D) -> Result, { Ok(Python::with_gil(|py| -> Result { 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>| Ok(r), )?; println!("{:#?}", cepi_data); Ok(()) } }