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}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy