@@ -2,48 +2,41 @@ use rustpython_vm::{Interpreter, PyRef, Settings, VirtualMachine, builtins::PyMo
22
33pub type InitHook = Box < dyn FnOnce ( & mut VirtualMachine ) > ;
44
5- /// The convenient way to create [rustpython_vm::Interpreter] with stdlib and other components .
5+ /// The convenient way to create [rustpython_vm::Interpreter] with stdlib and other stuffs .
66///
7- /// # Basic Usage
8- /// ```no_run
9- /// use rustpython::InterpreterConfig;
10- ///
11- /// let interpreter = InterpreterConfig::new()
7+ /// Basic usage:
8+ /// ```
9+ /// let interpreter = rustpython::InterpreterConfig::new()
1210/// .init_stdlib()
1311/// .interpreter();
1412/// ```
1513///
16- /// # Override Settings
17- /// ```no_run
14+ /// To override [rustpython_vm:: Settings]:
15+ /// ```
1816/// use rustpython_vm::Settings;
19- /// use rustpython::InterpreterConfig;
20- ///
17+ /// // Override your settings here.
2118/// let mut settings = Settings::default();
2219/// settings.debug = 1;
23- /// // Add paths to allow importing Python libraries
24- /// settings.path_list.push("Lib".to_owned()); // standard library directory
25- /// settings.path_list.push("".to_owned()); // current working directory
26- ///
27- /// let interpreter = InterpreterConfig::new()
20+ /// // You may want to add paths to `rustpython_vm::Settings::path_list` to allow import python libraries.
21+ /// settings.path_list.push("Lib".to_owned()); // add standard library directory
22+ /// settings.path_list.push("".to_owned()); // add current working directory
23+ /// let interpreter = rustpython::InterpreterConfig::new()
2824/// .settings(settings)
2925/// .interpreter();
3026/// ```
3127///
32- /// # Add Native Modules
33- /// ```no_run
34- /// use rustpython::InterpreterConfig;
35- /// use rustpython_vm::{VirtualMachine, PyRef, builtins::PyModule};
28+ /// To add native modules:
29+ /// ```
30+ /// use rustpython_vm::pymodule;
3631///
37- /// fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
38- /// // Your module implementation
39- /// # todo!()
40- /// }
32+ /// #[pymodule]
33+ /// mod your_module {}
4134///
42- /// let interpreter = InterpreterConfig::new()
35+ /// let interpreter = rustpython:: InterpreterConfig::new()
4336/// .init_stdlib()
4437/// .add_native_module(
4538/// "your_module_name".to_owned(),
46- /// make_module, // ← use make_module
39+ /// your_module:: make_module,
4740/// )
4841/// .interpreter();
4942/// ```
@@ -54,15 +47,12 @@ pub struct InterpreterConfig {
5447}
5548
5649impl InterpreterConfig {
57- /// Create a new interpreter configuration with default settings
50+ /// Creates a new interpreter configuration with default settings.
5851 pub fn new ( ) -> Self {
5952 Self :: default ( )
6053 }
6154
62- /// Build the interpreter with the current configuration
63- ///
64- /// # Panics
65- /// May panic if initialization hooks encounter fatal errors
55+ /// Builds the interpreter with the current configuration.
6656 pub fn interpreter ( self ) -> Interpreter {
6757 let settings = self . settings . unwrap_or_default ( ) ;
6858 Interpreter :: with_init ( settings, |vm| {
@@ -72,37 +62,23 @@ impl InterpreterConfig {
7262 } )
7363 }
7464
75- /// Set custom settings for the interpreter
65+ /// Sets custom settings for the interpreter.
7666 ///
77- /// If called multiple times, only the last settings will be used
67+ /// If called multiple times, only the last settings will be used.
7868 pub fn settings ( mut self , settings : Settings ) -> Self {
7969 self . settings = Some ( settings) ;
8070 self
8171 }
8272
83- /// Add a custom initialization hook
73+ /// Adds a custom initialization hook.
8474 ///
85- /// Hooks are executed in the order they are added during interpreter creation
75+ /// Hooks are executed in the order they are added during interpreter creation.
8676 pub fn init_hook ( mut self , hook : InitHook ) -> Self {
8777 self . init_hooks . push ( hook) ;
8878 self
8979 }
9080
91- /// Add a native module to the interpreter
92- ///
93- /// # Arguments
94- /// * `name` - The module name that will be used for imports
95- /// * `make_module` - Function that creates the module when called
96- ///
97- /// # Example
98- /// ```no_run
99- /// # use rustpython::InterpreterConfig;
100- /// # use rustpython_vm::{VirtualMachine, PyRef, builtins::PyModule};
101- /// # fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> { todo!() }
102- /// let interpreter = InterpreterConfig::new()
103- /// .add_native_module("mymodule".to_owned(), make_module)
104- /// .interpreter();
105- /// ```
81+ /// Adds a native module to the interpreter.
10682 pub fn add_native_module (
10783 self ,
10884 name : String ,
@@ -113,82 +89,16 @@ impl InterpreterConfig {
11389 } ) )
11490 }
11591
116- /// Initialize the Python standard library
92+ /// Initializes the Python standard library.
11793 ///
118- /// This adds all standard library modules to the interpreter.
119- /// Requires the `stdlib` feature to be enabled at compile time.
94+ /// Requires the `stdlib` feature to be enabled.
12095 #[ cfg( feature = "stdlib" ) ]
12196 pub fn init_stdlib ( self ) -> Self {
12297 self . init_hook ( Box :: new ( init_stdlib) )
12398 }
124-
125- /// Initialize the Python standard library (no-op without stdlib feature)
126- ///
127- /// When the `stdlib` feature is not enabled, this method does nothing
128- /// and prints a warning. Enable the `stdlib` feature to use the standard library.
129- #[ cfg( not( feature = "stdlib" ) ) ]
130- pub fn init_stdlib ( self ) -> Self {
131- eprintln ! (
132- "Warning: stdlib feature is not enabled. Standard library will not be available."
133- ) ;
134- self
135- }
136-
137- /// Convenience method to set the debug level
138- ///
139- /// # Example
140- /// ```no_run
141- /// # use rustpython::InterpreterConfig;
142- /// let interpreter = InterpreterConfig::new()
143- /// .with_debug(1)
144- /// .interpreter();
145- /// ```
146- pub fn with_debug ( mut self , level : u8 ) -> Self {
147- self . settings . get_or_insert_with ( Default :: default) . debug = level;
148- self
149- }
150-
151- /// Convenience method to add a single path to the module search paths
152- ///
153- /// # Example
154- /// ```no_run
155- /// # use rustpython::InterpreterConfig;
156- /// let interpreter = InterpreterConfig::new()
157- /// .add_path("Lib")
158- /// .add_path(".")
159- /// .interpreter();
160- /// ```
161- pub fn add_path ( mut self , path : impl Into < String > ) -> Self {
162- self . settings
163- . get_or_insert_with ( Default :: default)
164- . path_list
165- . push ( path. into ( ) ) ;
166- self
167- }
168-
169- /// Add multiple paths to the module search paths at once
170- ///
171- /// # Example
172- /// ```no_run
173- /// # use rustpython::InterpreterConfig;
174- /// let interpreter = InterpreterConfig::new()
175- /// .add_paths(vec!["Lib", ".", "custom_modules"])
176- /// .interpreter();
177- /// ```
178- pub fn add_paths < I , S > ( mut self , paths : I ) -> Self
179- where
180- I : IntoIterator < Item = S > ,
181- S : Into < String > ,
182- {
183- let settings = self . settings . get_or_insert_with ( Default :: default) ;
184- settings. path_list . extend ( paths. into_iter ( ) . map ( Into :: into) ) ;
185- self
186- }
18799}
188100
189- /// Initialize the standard library modules
190- ///
191- /// This function sets up both native modules and handles frozen/dynamic stdlib loading
101+ /// Initializes all standard library modules for the given VM.
192102#[ cfg( feature = "stdlib" ) ]
193103pub fn init_stdlib ( vm : & mut VirtualMachine ) {
194104 vm. add_native_modules ( rustpython_stdlib:: get_module_inits ( ) ) ;
@@ -200,16 +110,13 @@ pub fn init_stdlib(vm: &mut VirtualMachine) {
200110 setup_dynamic_stdlib ( vm) ;
201111}
202112
203- /// Setup frozen standard library
204- ///
205- /// Used when the stdlib is compiled into the binary
113+ /// Setup frozen standard library (compiled into the binary)
206114#[ cfg( all( feature = "stdlib" , feature = "freeze-stdlib" ) ) ]
207115fn setup_frozen_stdlib ( vm : & mut VirtualMachine ) {
208116 vm. add_frozen ( rustpython_pylib:: FROZEN_STDLIB ) ;
209117
210118 // FIXME: Remove this hack once sys._stdlib_dir is properly implemented
211119 // or _frozen_importlib doesn't depend on it anymore.
212- // The assert ensures _stdlib_dir doesn't already exist before we set it
213120 assert ! ( vm. sys_module. get_attr( "_stdlib_dir" , vm) . is_err( ) ) ;
214121 vm. sys_module
215122 . set_attr (
@@ -221,82 +128,35 @@ fn setup_frozen_stdlib(vm: &mut VirtualMachine) {
221128}
222129
223130/// Setup dynamic standard library loading from filesystem
224- ///
225- /// Used when the stdlib is loaded from disk at runtime
226131#[ cfg( all( feature = "stdlib" , not( feature = "freeze-stdlib" ) ) ) ]
227132fn setup_dynamic_stdlib ( vm : & mut VirtualMachine ) {
228133 use rustpython_vm:: common:: rc:: PyRc ;
229134
230135 let state = PyRc :: get_mut ( & mut vm. state ) . unwrap ( ) ;
231-
232- let additional_paths = collect_stdlib_paths ( ) ;
136+ let paths = collect_stdlib_paths ( ) ;
233137
234138 // Insert at the beginning so stdlib comes before user paths
235- for path in additional_paths . into_iter ( ) . rev ( ) {
139+ for path in paths . into_iter ( ) . rev ( ) {
236140 state. config . paths . module_search_paths . insert ( 0 , path) ;
237141 }
238142}
239143
240144/// Collect standard library paths from build-time configuration
241- ///
242- /// Checks BUILDTIME_RUSTPYTHONPATH environment variable or uses default pylib path
243145#[ cfg( all( feature = "stdlib" , not( feature = "freeze-stdlib" ) ) ) ]
244146fn collect_stdlib_paths ( ) -> Vec < String > {
245- let mut additional_paths = Vec :: new ( ) ;
246-
247147 // BUILDTIME_RUSTPYTHONPATH should be set when distributing
248148 if let Some ( paths) = option_env ! ( "BUILDTIME_RUSTPYTHONPATH" ) {
249- additional_paths. extend ( crate :: settings:: split_paths ( paths) . map ( |path| {
250- path. into_os_string ( )
251- . into_string ( )
252- . unwrap_or_else ( |_| panic ! ( "BUILDTIME_RUSTPYTHONPATH isn't valid unicode" ) )
253- } ) )
149+ crate :: settings:: split_paths ( paths)
150+ . map ( |path| path. into_os_string ( ) . into_string ( ) . unwrap ( ) )
151+ . collect ( )
254152 } else {
255153 #[ cfg( feature = "rustpython-pylib" ) ]
256- additional_paths. push ( rustpython_pylib:: LIB_PATH . to_owned ( ) )
257- }
258-
259- additional_paths
260- }
261-
262- #[ cfg( test) ]
263- mod tests {
264- use super :: * ;
265-
266- #[ test]
267- fn test_default_config ( ) {
268- let config = InterpreterConfig :: new ( ) ;
269- assert ! ( config. settings. is_none( ) ) ;
270- assert ! ( config. init_hooks. is_empty( ) ) ;
271- }
272-
273- #[ test]
274- fn test_with_debug ( ) {
275- let config = InterpreterConfig :: new ( ) . with_debug ( 2 ) ;
276- let settings = config. settings . unwrap ( ) ;
277- assert_eq ! ( settings. debug, 2 ) ;
278- }
279-
280- #[ test]
281- fn test_add_single_path ( ) {
282- let config = InterpreterConfig :: new ( ) . add_path ( "test/path" ) ;
283- let settings = config. settings . unwrap ( ) ;
284- assert_eq ! ( settings. path_list. len( ) , 1 ) ;
285- assert_eq ! ( settings. path_list[ 0 ] , "test/path" ) ;
286- }
287-
288- #[ test]
289- fn test_add_multiple_paths_sequential ( ) {
290- let config = InterpreterConfig :: new ( ) . add_path ( "path1" ) . add_path ( "path2" ) ;
291- let settings = config. settings . unwrap ( ) ;
292- assert_eq ! ( settings. path_list. len( ) , 2 ) ;
293- }
294-
295- #[ test]
296- fn test_add_paths_batch ( ) {
297- let paths = vec ! [ "path1" , "path2" , "path3" ] ;
298- let config = InterpreterConfig :: new ( ) . add_paths ( paths) ;
299- let settings = config. settings . unwrap ( ) ;
300- assert_eq ! ( settings. path_list. len( ) , 3 ) ;
154+ {
155+ vec ! [ rustpython_pylib:: LIB_PATH . to_owned( ) ]
156+ }
157+ #[ cfg( not( feature = "rustpython-pylib" ) ) ]
158+ {
159+ vec ! [ ]
160+ }
301161 }
302162}
0 commit comments