Repository: RustPython/RustPython (language: rust)

Issue:
add some kind of setup hook to `rustpython::run` to allow things like module/variable populating
## Summary

Currently `rustpython:run` only accepts a closure that takes `&VirtualMachine` which is executed very early. During experimenting I find only modules can be added here. Things like setting up global variable from rust world, or pre-importing some modules to workaround "static type has not been initialized" error seems hard if not impossible. I suggest add a way to let user access to `vm` and current scope by adding a "late_setup" parameter, and call it before doing the real work.

Possibly here:

https://github.com/RustPython/RustPython/blob/98d09e781623ccec64643cf5412453cc78ba4f18/src/lib.rs#L184-L186

resulting `run` looks like this:
```
pub fn run(init: impl FnOnce(&mut VirtualMachine) + 'static, late_init: impl FnOnce(&VirtualMachine, &Scope) + 'static) -> ExitCode {
```
## Expected use case

We are creating native modules in rust so we can call our logic in python world. Use existing `rustpython::run` code can be an easy way if we also want interactive environment to quickly experiment with the resulting API.  For now two problems is blocking us:

- we need to add a "World" object to the environment (this is init from rust object) to allow script to use before passed to REPL or user script, so we want `scope.globals.set_item` which seems not accessible now
- there are multiple native modules and sometimes we encounter error: "static type has not been initialized". Just importing them beforehand seems to be a solution if we can



Discussion / hints:
If you like this idea I created a PR for this.
Could you share your use case of the function to let me understand better of the motivation?

`rustpython::run` is expected to be used only by RustPython CLI's. So it doesn't have that much customizable features. To run your own RustPython interpreters, creating Interpreter object is best to customize them. 
e.g. https://github.com/RustPython/RustPython/blob/main/example_projects/frozen_stdlib/src/main.rs

Hi,
`Interpreter` API indeed can resolve the problems mentioned above (in fact this is what we're using to test our code right now), previously I looked at rustpython::run because I also want an interactive environment without doing all the REPL stuffs myself.

Now to achieve this with the Interpreter api I think we can just call `shell::run_shell` under interpreter enter/run. However now shell is a non pub mod. Could you please change the `mod shell` to `pub mod shell` instead under src/lib.rs? `run_shell` is already a pub so no need to change.
That sounds like a good idea. I prefer to import `run_shell` from the top of `rustpython` crate rather than exposing the whole module.

@coolreader18 Could you give a comment about it?
gently ping @coolreader18 for a comment 
Sorry for the delay -- I agree with @youknowone; exposing `run_shell` seems like the most reasonable solution.

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index 326a3f174f..0e35a6ad83 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -58,6 +58,7 @@ use std::process::ExitCode;
 pub use interpreter::InterpreterConfig;
 pub use rustpython_vm as vm;
 pub use settings::{opts_with_clap, InstallPipMode, RunMode};
+pub use shell::run_shell;
 
 /// The main cli of the `rustpython` interpreter. This function will return `std::process::ExitCode`
 /// based on the return code of the python code ran through the cli.


Test patch: