Skip to content

Commit d3aff65

Browse files
Merge pull request RustPython#1614 from yanganto/update-sys-module
Update sys module when stdlib_inits is changed
2 parents 2cf92a9 + 4c3642d commit d3aff65

File tree

5 files changed

+80
-32
lines changed

5 files changed

+80
-32
lines changed

src/main.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ extern crate log;
77
use clap::{App, AppSettings, Arg, ArgMatches};
88
use rustpython_compiler::compile;
99
use rustpython_vm::{
10-
import, match_class,
10+
match_class,
1111
obj::{objint::PyInt, objtuple::PyTuple, objtype},
1212
print_exception,
1313
pyobject::{ItemProtocol, PyResult},
1414
scope::Scope,
15-
util, PySettings, VirtualMachine,
15+
util, InitParameter, PySettings, VirtualMachine,
1616
};
1717

1818
use std::convert::TryInto;
@@ -29,7 +29,13 @@ fn main() {
2929
env_logger::init();
3030
let app = App::new("RustPython");
3131
let matches = parse_arguments(app);
32-
let settings = create_settings(&matches);
32+
let mut settings = create_settings(&matches);
33+
34+
// We only include the standard library bytecode in WASI when initializing
35+
if cfg!(target_os = "wasi") {
36+
settings.initialization_parameter = InitParameter::InitializeInternal;
37+
}
38+
3339
let vm = VirtualMachine::new(settings);
3440

3541
let res = run_rustpython(&vm, &matches);
@@ -324,9 +330,6 @@ fn write_profile(matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>>
324330
}
325331

326332
fn run_rustpython(vm: &VirtualMachine, matches: &ArgMatches) -> PyResult<()> {
327-
// We only include the standard library bytecode in WASI
328-
import::init_importlib(&vm, cfg!(not(target_os = "wasi")))?;
329-
330333
if let Some(paths) = option_env!("BUILDTIME_RUSTPYTHONPATH") {
331334
let sys_path = vm.get_attribute(vm.sys_module.clone(), "path")?;
332335
for (i, path) in std::env::split_paths(paths).enumerate() {

vm/src/import.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,38 @@ use crate::obj::{objcode, objtype};
99
use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, PyValue};
1010
use crate::scope::Scope;
1111
use crate::version::get_git_revision;
12-
use crate::vm::VirtualMachine;
12+
use crate::vm::{InitParameter, VirtualMachine};
1313
#[cfg(feature = "rustpython-compiler")]
1414
use rustpython_compiler::compile;
1515

16-
pub fn init_importlib(vm: &VirtualMachine, external: bool) -> PyResult {
16+
pub fn init_importlib(vm: &VirtualMachine, initialize_parameter: InitParameter) -> PyResult {
1717
flame_guard!("init importlib");
1818
let importlib = import_frozen(vm, "_frozen_importlib")?;
1919
let impmod = import_builtin(vm, "_imp")?;
2020
let install = vm.get_attribute(importlib.clone(), "_install")?;
2121
vm.invoke(&install, vec![vm.sys_module.clone(), impmod])?;
2222
vm.import_func
2323
.replace(vm.get_attribute(importlib.clone(), "__import__")?);
24-
if external && cfg!(feature = "rustpython-compiler") {
25-
flame_guard!("install_external");
26-
let install_external =
27-
vm.get_attribute(importlib.clone(), "_install_external_importers")?;
28-
vm.invoke(&install_external, vec![])?;
29-
// Set pyc magic number to commit hash. Should be changed when bytecode will be more stable.
30-
let importlib_external = vm.import("_frozen_importlib_external", &[], 0)?;
31-
let mut magic = get_git_revision().into_bytes();
32-
magic.truncate(4);
33-
if magic.len() != 4 {
34-
magic = rand::thread_rng().gen::<[u8; 4]>().to_vec();
24+
25+
match initialize_parameter {
26+
InitParameter::InitializeExternal if cfg!(feature = "rustpython-compiler") => {
27+
flame_guard!("install_external");
28+
let install_external =
29+
vm.get_attribute(importlib.clone(), "_install_external_importers")?;
30+
vm.invoke(&install_external, vec![])?;
31+
// Set pyc magic number to commit hash. Should be changed when bytecode will be more stable.
32+
let importlib_external = vm.import("_frozen_importlib_external", &[], 0)?;
33+
let mut magic = get_git_revision().into_bytes();
34+
magic.truncate(4);
35+
if magic.len() != 4 {
36+
magic = rand::thread_rng().gen::<[u8; 4]>().to_vec();
37+
}
38+
vm.set_attr(&importlib_external, "MAGIC_NUMBER", vm.ctx.new_bytes(magic))?;
39+
}
40+
InitParameter::NoInitialize => {
41+
panic!("Import library initialize should be InitializeInternal or InitializeExternal");
3542
}
36-
vm.set_attr(&importlib_external, "MAGIC_NUMBER", vm.ctx.new_bytes(magic))?;
43+
_ => {}
3744
}
3845
Ok(vm.get_none())
3946
}

vm/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ mod vm;
7373

7474
// pub use self::pyobject::Executor;
7575
pub use self::exceptions::{print_exception, write_exception};
76-
pub use self::vm::{PySettings, VirtualMachine};
76+
pub use self::vm::{InitParameter, PySettings, VirtualMachine};
7777
pub use rustpython_bytecode::*;
7878

7979
#[doc(hidden)]

vm/src/vm.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,18 @@ pub struct VirtualMachine {
6969
pub settings: PySettings,
7070
pub recursion_limit: Cell<usize>,
7171
pub codec_registry: RefCell<Vec<PyObjectRef>>,
72+
pub initialized: bool,
7273
}
7374

7475
pub const NSIG: usize = 64;
7576

77+
#[derive(Copy, Clone)]
78+
pub enum InitParameter {
79+
NoInitialize,
80+
InitializeInternal,
81+
InitializeExternal,
82+
}
83+
7684
/// Struct containing all kind of settings for the python vm.
7785
pub struct PySettings {
7886
/// -d command line switch
@@ -107,6 +115,10 @@ pub struct PySettings {
107115

108116
/// sys.argv
109117
pub argv: Vec<String>,
118+
119+
/// Initialization parameter to decide to initialize or not,
120+
/// and to decide the importer required external filesystem access or not
121+
pub initialization_parameter: InitParameter,
110122
}
111123

112124
/// Trace events for sys.settrace and sys.setprofile.
@@ -140,14 +152,15 @@ impl Default for PySettings {
140152
dont_write_bytecode: false,
141153
path_list: vec![],
142154
argv: vec![],
155+
initialization_parameter: InitParameter::InitializeExternal,
143156
}
144157
}
145158
}
146159

147160
impl VirtualMachine {
148161
/// Create a new `VirtualMachine` structure.
149162
pub fn new(settings: PySettings) -> VirtualMachine {
150-
flame_guard!("init VirtualMachine");
163+
flame_guard!("new VirtualMachine");
151164
let ctx = PyContext::new();
152165

153166
// make a new module without access to the vm; doesn't
@@ -167,8 +180,9 @@ impl VirtualMachine {
167180
let profile_func = RefCell::new(ctx.none());
168181
let trace_func = RefCell::new(ctx.none());
169182
let signal_handlers = RefCell::new(arr![ctx.none(); 64]);
183+
let initialize_parameter = settings.initialization_parameter;
170184

171-
let vm = VirtualMachine {
185+
let mut vm = VirtualMachine {
172186
builtins: builtins.clone(),
173187
sys_module: sysmod.clone(),
174188
stdlib_inits,
@@ -185,6 +199,7 @@ impl VirtualMachine {
185199
settings,
186200
recursion_limit: Cell::new(512),
187201
codec_registry: RefCell::default(),
202+
initialized: false,
188203
};
189204

190205
objmodule::init_module_dict(
@@ -199,14 +214,32 @@ impl VirtualMachine {
199214
vm.new_str("sys".to_owned()),
200215
vm.get_none(),
201216
);
217+
vm.initialize(initialize_parameter);
218+
vm
219+
}
202220

203-
builtins::make_module(&vm, builtins.clone());
204-
sysmodule::make_module(&vm, sysmod, builtins);
221+
pub fn initialize(&mut self, initialize_parameter: InitParameter) {
222+
flame_guard!("init VirtualMachine");
205223

206-
#[cfg(not(target_arch = "wasm32"))]
207-
import::import_builtin(&vm, "signal").expect("Couldn't initialize signal module");
224+
match initialize_parameter {
225+
InitParameter::NoInitialize => {}
226+
_ => {
227+
if self.initialized {
228+
panic!("Double Initialize Error");
229+
}
208230

209-
vm
231+
builtins::make_module(self, self.builtins.clone());
232+
sysmodule::make_module(self, self.sys_module.clone(), self.builtins.clone());
233+
234+
#[cfg(not(target_arch = "wasm32"))]
235+
import::import_builtin(self, "signal").expect("Couldn't initialize signal module");
236+
237+
import::init_importlib(self, initialize_parameter)
238+
.expect("Initialize importlib fail");
239+
240+
self.initialized = true;
241+
}
242+
}
210243
}
211244

212245
pub fn run_code_obj(&self, code: PyCodeRef, scope: Scope) -> PyResult {

wasm/lib/src/vm_class.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ use wasm_bindgen::prelude::*;
77

88
use rustpython_compiler::compile;
99
use rustpython_vm::function::PyFuncArgs;
10-
use rustpython_vm::import;
1110
use rustpython_vm::pyobject::{PyObject, PyObjectPayload, PyObjectRef, PyResult, PyValue};
1211
use rustpython_vm::scope::{NameProtocol, Scope};
13-
use rustpython_vm::VirtualMachine;
12+
use rustpython_vm::{InitParameter, PySettings, VirtualMachine};
1413

1514
use crate::browser_module::setup_browser_module;
1615
use crate::convert;
@@ -27,7 +26,13 @@ pub(crate) struct StoredVirtualMachine {
2726

2827
impl StoredVirtualMachine {
2928
fn new(id: String, inject_browser_module: bool) -> StoredVirtualMachine {
30-
let mut vm: VirtualMachine = Default::default();
29+
let mut settings = PySettings::default();
30+
31+
// After js, browser modules injected, the VM will not be initialized.
32+
settings.initialization_parameter = InitParameter::NoInitialize;
33+
34+
let mut vm: VirtualMachine = VirtualMachine::new(settings);
35+
3136
vm.wasm_id = Some(id);
3237
let scope = vm.new_scope_with_builtins();
3338

@@ -44,7 +49,7 @@ impl StoredVirtualMachine {
4449
setup_browser_module(&vm);
4550
}
4651

47-
import::init_importlib(&vm, false).unwrap();
52+
vm.initialize(InitParameter::InitializeInternal);
4853

4954
StoredVirtualMachine {
5055
vm,

0 commit comments

Comments
 (0)