stable_inline_python/
lib.rs1use std::{str::FromStr, fs};
2
3use pyo3::{prelude::*, types::PyDict};
4
5#[macro_export]
6macro_rules! py_eval {
7 ($val:expr) => {
8 {
9 use pyo3::prelude::*;
10 pyo3::prepare_freethreaded_python();
11
12 Python::with_gil(|py| {
13 py.run($val, None, None)
14 })
15 }
16 };
17}
18
19pub struct PyContext {
21 pub variables: PyVar
23}
24
25impl Default for PyContext {
26 fn default() -> Self {
28 PyContext { variables: Default::default() }
29 }
30}
31
32pub struct PyVar {
34 pub locals: Py<PyDict>
36}
37
38impl Default for PyVar {
39 fn default() -> Self {
41 pyo3::prepare_freethreaded_python();
42 Python::with_gil(|py| {
43 Self { locals: PyDict::new(py).into() }
44 })
45 }
46}
47
48impl PyContext {
49 pub fn new() -> PyContext {
51 PyContext { ..Default::default() }
52
53 }
54
55 pub fn run(&self, input: &str) -> Result<(), pyo3::PyErr> {
61 self.execute_python(Some(&self.variables), &input)
62 }
63
64 pub fn run_file(&self, file: &str) -> Result<(), PyErr> {
74 let contents = fs::read_to_string(&file)?;
75 self.execute_python(Some(&self.variables), &contents)
76 }
77
78
79 pub fn get<T: FromStr>(&self, input: &str) -> Result<T, <T as FromStr>::Err> {
89
90 pyo3::prepare_freethreaded_python();
91
92 let out = Python::with_gil(|py| {
93 let locals: &PyDict = self._define(Some(&self.variables), &py);
94
95 let ret = locals.get_item(&input).unwrap().unwrap();
96 format!("{}",ret)
97 });
98 out.parse::<T>()
99 }
100
101 fn execute_python(&self, py_vars: Option<&PyVar>, input: &str) -> Result<(), pyo3::PyErr> {
102 pyo3::prepare_freethreaded_python();
103
104 Python::with_gil(|py| {
105 let locals: &PyDict = self._define(py_vars, &py);
106 py.run(&input, None, Some(locals))
107 })
108 }
109
110 fn _define<'a>(&self, py_vars: Option<&'a PyVar>, py: &Python<'a>) -> &'a PyDict {
121 if py_vars.is_none() {
122 PyDict::new(*py).into()
123 } else {
124 py_vars.unwrap().locals.as_ref(*py)
125 }
126 }
127
128}