Thanks to visit codestin.com
Credit goes to docs.rs

rustpython/
interpreter.rs

1use rustpython_vm::{builtins::PyModule, Interpreter, PyRef, Settings, VirtualMachine};
2
3pub type InitHook = Box<dyn FnOnce(&mut VirtualMachine)>;
4
5/// The convenient way to create [rustpython_vm::Interpreter] with stdlib and other stuffs.
6///
7/// Basic usage:
8/// ```
9/// let interpreter = rustpython::InterpreterConfig::new()
10///     .init_stdlib()
11///     .interpreter();
12/// ```
13///
14/// To override [rustpython_vm::Settings]:
15/// ```
16/// use rustpython_vm::Settings;
17/// // Override your settings here.
18/// let mut settings = Settings::default();
19/// settings.debug = true;
20/// // You may want to add paths to `rustpython_vm::Settings::path_list` to allow import python libraries.
21/// settings.path_list.push("".to_owned());  // add current working directory
22/// let interpreter = rustpython::InterpreterConfig::new()
23///     .settings(settings)
24///     .interpreter();
25/// ```
26///
27/// To add native modules:
28/// ```compile_fail
29/// let interpreter = rustpython::InterpreterConfig::new()
30///     .init_stdlib()
31///     .init_hook(Box::new(|vm| {
32///         vm.add_native_module(
33///             "your_module_name".to_owned(),
34///             Box::new(your_module::make_module),
35///         );
36///     }))
37///     .interpreter();
38/// ```
39#[derive(Default)]
40pub struct InterpreterConfig {
41    settings: Option<Settings>,
42    init_hooks: Vec<InitHook>,
43}
44
45impl InterpreterConfig {
46    pub fn new() -> Self {
47        Self::default()
48    }
49    pub fn interpreter(self) -> Interpreter {
50        let settings = self.settings.unwrap_or_default();
51        Interpreter::with_init(settings, |vm| {
52            for hook in self.init_hooks {
53                hook(vm);
54            }
55        })
56    }
57
58    pub fn settings(mut self, settings: Settings) -> Self {
59        self.settings = Some(settings);
60        self
61    }
62    pub fn init_hook(mut self, hook: InitHook) -> Self {
63        self.init_hooks.push(hook);
64        self
65    }
66    pub fn add_native_module(
67        self,
68        name: String,
69        make_module: fn(&VirtualMachine) -> PyRef<PyModule>,
70    ) -> Self {
71        self.init_hook(Box::new(move |vm| {
72            vm.add_native_module(name, Box::new(make_module))
73        }))
74    }
75    #[cfg(feature = "stdlib")]
76    pub fn init_stdlib(self) -> Self {
77        self.init_hook(Box::new(init_stdlib))
78    }
79}
80
81#[cfg(feature = "stdlib")]
82pub fn init_stdlib(vm: &mut VirtualMachine) {
83    vm.add_native_modules(rustpython_stdlib::get_module_inits());
84
85    // if we're on freeze-stdlib, the core stdlib modules will be included anyway
86    #[cfg(feature = "freeze-stdlib")]
87    {
88        vm.add_frozen(rustpython_pylib::FROZEN_STDLIB);
89
90        // FIXME: Remove this hack once sys._stdlib_dir is properly implemented or _frozen_importlib doesn't depend on it anymore.
91        assert!(vm.sys_module.get_attr("_stdlib_dir", vm).is_err());
92        vm.sys_module
93            .set_attr(
94                "_stdlib_dir",
95                vm.new_pyobj(rustpython_pylib::LIB_PATH.to_owned()),
96                vm,
97            )
98            .unwrap();
99    }
100
101    #[cfg(not(feature = "freeze-stdlib"))]
102    {
103        use rustpython_vm::common::rc::PyRc;
104
105        let state = PyRc::get_mut(&mut vm.state).unwrap();
106        let settings = &mut state.settings;
107
108        let path_list = std::mem::take(&mut settings.path_list);
109
110        // BUILDTIME_RUSTPYTHONPATH should be set when distributing
111        if let Some(paths) = option_env!("BUILDTIME_RUSTPYTHONPATH") {
112            settings.path_list.extend(
113                crate::settings::split_paths(paths)
114                    .map(|path| path.into_os_string().into_string().unwrap()),
115            )
116        } else {
117            #[cfg(feature = "rustpython-pylib")]
118            settings
119                .path_list
120                .push(rustpython_pylib::LIB_PATH.to_owned())
121        }
122
123        settings.path_list.extend(path_list);
124    }
125}