use std::{
collections::{BTreeMap, HashSet},
default::Default,
};
use pyo3::{prelude::*, PyResult};
use std::ffi::CString;
#[derive(Clone, Debug, PartialEq)]
pub enum AsyncRuntime {
Tokio,
AsyncStd,
Smol,
Custom {
attribute: String,
import: String,
},
}
impl Default for AsyncRuntime {
fn default() -> Self {
AsyncRuntime::Tokio
}
}
impl AsyncRuntime {
pub fn main_attribute(&self) -> &str {
match self {
AsyncRuntime::Tokio => "tokio::main",
AsyncRuntime::AsyncStd => "async_std::main",
AsyncRuntime::Smol => "smol::main",
AsyncRuntime::Custom { attribute, .. } => attribute,
}
}
pub fn import(&self) -> &str {
match self {
AsyncRuntime::Tokio => "tokio",
AsyncRuntime::AsyncStd => "async_std",
AsyncRuntime::Smol => "smol",
AsyncRuntime::Custom { import, .. } => import,
}
}
}
pub fn sys_path() -> PyResult<Vec<String>> {
let pymodule_code = include_str!("path.py");
Python::attach(|py| -> PyResult<Vec<String>> {
let code_cstr = CString::new(pymodule_code)?;
let pymodule = PyModule::from_code(py, &code_cstr, c"path.py", c"path")?;
let t = pymodule.getattr("path")?;
assert!(t.is_callable());
let args = ();
let paths: Vec<String> = t.call1(args)?.extract()?;
Ok(paths)
})
}
#[derive(Clone, Debug)]
pub struct PythonOptions {
pub python_namespace: String,
pub python_path: Vec<String>,
pub imports: BTreeMap<String, HashSet<String>>,
pub stdpython: String,
pub with_std_python: bool,
pub allow_unsafe: bool,
pub async_runtime: AsyncRuntime,
pub lossy_warnings: bool,
pub optional_names: std::rc::Rc<std::collections::HashSet<String>>,
pub clone_str_attribute_returns: bool,
pub local_types:
std::rc::Rc<std::collections::HashMap<String, String>>,
pub no_std: bool,
}
impl Default for PythonOptions {
fn default() -> Self {
Self {
python_namespace: String::from("__python_namespace__"),
python_path: sys_path().unwrap_or_else(|e| {
tracing::warn!("could not read Python sys.path: {}; using empty path", e);
Vec::new()
}),
imports: BTreeMap::new(),
stdpython: "stdpython".to_string(),
with_std_python: true,
allow_unsafe: false,
async_runtime: AsyncRuntime::default(),
lossy_warnings: true,
optional_names: std::rc::Rc::new(std::collections::HashSet::new()),
clone_str_attribute_returns: false,
local_types: std::rc::Rc::new(std::collections::HashMap::new()),
no_std: false,
}
}
}
impl PythonOptions {
pub fn with_tokio() -> Self {
let mut options = Self::default();
options.async_runtime = AsyncRuntime::Tokio;
options
}
pub fn with_async_std() -> Self {
let mut options = Self::default();
options.async_runtime = AsyncRuntime::AsyncStd;
options
}
pub fn with_smol() -> Self {
let mut options = Self::default();
options.async_runtime = AsyncRuntime::Smol;
options
}
pub fn with_custom_runtime(attribute: impl Into<String>, import: impl Into<String>) -> Self {
let mut options = Self::default();
options.async_runtime = AsyncRuntime::Custom {
attribute: attribute.into(),
import: import.into(),
};
options
}
pub fn set_async_runtime(&mut self, runtime: AsyncRuntime) -> &mut Self {
self.async_runtime = runtime;
self
}
}