use std::{ffi::CString, sync::Once};
use pyo3::{PyErr, Python};
#[derive(Debug)]
pub struct Interpreter;
static GLOBAL_INIT: Once = Once::new();
impl Interpreter {
pub fn new() -> Result<Self, PyError> {
GLOBAL_INIT.call_once_force(|_| {
Python::with_gil(|py| {
py.import("decimal").unwrap();
});
});
Ok(Self)
}
pub fn with_gil<F, R>(&self, f: F) -> Result<R, PyError>
where
F: for<'py> FnOnce(Python<'py>) -> Result<R, PyError>,
{
Python::with_gil(f)
}
pub fn run(&self, code: &str) -> Result<(), PyError> {
let code = CString::new(code).unwrap();
self.with_gil(|py| py.run(&code, None, None).map_err(|e| e.into()))
}
}
#[derive(Debug)]
pub struct PyError {
anyhow: anyhow::Error,
}
impl From<PyErr> for PyError {
fn from(err: PyErr) -> Self {
Self {
anyhow: anyhow::anyhow!(err.to_string()),
}
}
}
impl From<anyhow::Error> for PyError {
fn from(err: anyhow::Error) -> Self {
Self { anyhow: err }
}
}
impl From<PyError> for anyhow::Error {
fn from(err: PyError) -> Self {
err.anyhow
}
}