Skip to content

Commit b74a5a6

Browse files
committed
relocate run functions to vm
1 parent 4c39668 commit b74a5a6

File tree

2 files changed

+93
-94
lines changed

2 files changed

+93
-94
lines changed

src/lib.rs

Lines changed: 12 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,13 @@ mod shell;
4747

4848
use clap::{App, AppSettings, Arg, ArgMatches};
4949
use rustpython_vm::{
50-
builtins::{PyDictRef, PyInt},
51-
compile, match_class,
50+
builtins::PyInt,
51+
match_class,
5252
scope::Scope,
5353
stdlib::{atexit, sys},
54-
AsObject, InitParameter, Interpreter, PyObjectRef, PyResult, Settings, TryFromObject,
55-
VirtualMachine,
54+
AsObject, InitParameter, Interpreter, PyResult, Settings, VirtualMachine,
5655
};
57-
use std::{env, path::Path, process, str::FromStr};
56+
use std::{env, process, str::FromStr};
5857

5958
pub use rustpython_vm as vm;
6059

@@ -599,13 +598,16 @@ fn run_rustpython(vm: &VirtualMachine, matches: &ArgMatches) -> PyResult<()> {
599598

600599
// Figure out if a -c option was given:
601600
if let Some(command) = matches.value_of("c") {
602-
run_command(vm, scope, command.to_owned())?;
601+
debug!("Running command {}", command);
602+
vm.run_code_string(scope, &command, "<stdin>".to_owned())?;
603603
} else if let Some(module) = matches.value_of("m") {
604-
run_module(vm, module)?;
604+
debug!("Running module {}", module);
605+
vm.run_module(module)?;
605606
} else if matches.is_present("install_pip") {
606607
install_pip(scope, vm)?;
607608
} else if let Some(filename) = matches.value_of("script") {
608-
run_script(vm, scope.clone(), filename)?;
609+
debug!("Running file {}", filename);
610+
vm.run_script(scope.clone(), filename)?;
609611
if matches.is_present("inspect") {
610612
shell::run_shell(vm, scope)?;
611613
}
@@ -620,89 +622,6 @@ fn run_rustpython(vm: &VirtualMachine, matches: &ArgMatches) -> PyResult<()> {
620622
Ok(())
621623
}
622624

623-
fn _run_string(vm: &VirtualMachine, scope: Scope, source: &str, source_path: String) -> PyResult {
624-
let code_obj = vm
625-
.compile(source, compile::Mode::Exec, source_path.clone())
626-
.map_err(|err| vm.new_syntax_error(&err))?;
627-
// trace!("Code object: {:?}", code_obj.borrow());
628-
scope
629-
.globals
630-
.set_item("__file__", vm.new_pyobj(source_path), vm)?;
631-
vm.run_code_obj(code_obj, scope)
632-
}
633-
634-
fn run_command(vm: &VirtualMachine, scope: Scope, source: String) -> PyResult<()> {
635-
debug!("Running command {}", source);
636-
_run_string(vm, scope, &source, "<stdin>".to_owned())?;
637-
Ok(())
638-
}
639-
640-
fn run_module(vm: &VirtualMachine, module: &str) -> PyResult<()> {
641-
debug!("Running module {}", module);
642-
let runpy = vm.import("runpy", None, 0)?;
643-
let run_module_as_main = runpy.get_attr("_run_module_as_main", vm)?;
644-
vm.invoke(&run_module_as_main, (module,))?;
645-
Ok(())
646-
}
647-
648-
fn get_importer(path: &str, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
649-
let path_importer_cache = vm.sys_module.get_attr("path_importer_cache", vm)?;
650-
let path_importer_cache = PyDictRef::try_from_object(vm, path_importer_cache)?;
651-
if let Some(importer) = path_importer_cache.get_item_opt(path, vm)? {
652-
return Ok(Some(importer));
653-
}
654-
let path = vm.ctx.new_str(path);
655-
let path_hooks = vm.sys_module.get_attr("path_hooks", vm)?;
656-
let mut importer = None;
657-
let path_hooks: Vec<PyObjectRef> = path_hooks.try_into_value(vm)?;
658-
for path_hook in path_hooks {
659-
match vm.invoke(&path_hook, (path.clone(),)) {
660-
Ok(imp) => {
661-
importer = Some(imp);
662-
break;
663-
}
664-
Err(e) if e.fast_isinstance(&vm.ctx.exceptions.import_error) => continue,
665-
Err(e) => return Err(e),
666-
}
667-
}
668-
Ok(if let Some(imp) = importer {
669-
let imp = path_importer_cache.get_or_insert(vm, path.into(), || imp.clone())?;
670-
Some(imp)
671-
} else {
672-
None
673-
})
674-
}
675-
676-
fn insert_sys_path(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<()> {
677-
let sys_path = vm.sys_module.get_attr("path", vm).unwrap();
678-
vm.call_method(&sys_path, "insert", (0, obj))?;
679-
Ok(())
680-
}
681-
682-
fn run_script(vm: &VirtualMachine, scope: Scope, script_file: &str) -> PyResult<()> {
683-
debug!("Running file {}", script_file);
684-
if get_importer(script_file, vm)?.is_some() {
685-
insert_sys_path(vm, vm.ctx.new_str(script_file).into())?;
686-
let runpy = vm.import("runpy", None, 0)?;
687-
let run_module_as_main = runpy.get_attr("_run_module_as_main", vm)?;
688-
vm.invoke(&run_module_as_main, (vm.ctx.new_str("__main__"), false))?;
689-
return Ok(());
690-
}
691-
let dir = Path::new(script_file).parent().unwrap().to_str().unwrap();
692-
insert_sys_path(vm, vm.ctx.new_str(dir).into())?;
693-
694-
match std::fs::read_to_string(script_file) {
695-
Ok(source) => {
696-
_run_string(vm, scope, &source, script_file.to_owned())?;
697-
}
698-
Err(err) => {
699-
error!("Failed reading file '{}': {}", script_file, err);
700-
process::exit(1);
701-
}
702-
}
703-
Ok(())
704-
}
705-
706625
#[cfg(test)]
707626
mod tests {
708627
use super::*;
@@ -720,11 +639,11 @@ mod tests {
720639
vm.unwrap_pyresult((|| {
721640
let scope = setup_main_module(vm)?;
722641
// test file run
723-
run_script(vm, scope, "extra_tests/snippets/dir_main/__main__.py")?;
642+
vm.run_script(scope, "extra_tests/snippets/dir_main/__main__.py")?;
724643

725644
let scope = setup_main_module(vm)?;
726645
// test module run
727-
run_script(vm, scope, "extra_tests/snippets/dir_main")?;
646+
vm.run_script(scope, "extra_tests/snippets/dir_main")?;
728647

729648
Ok(())
730649
})());

vm/src/vm/mod.rs

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::{
2424
bytecode,
2525
codecs::CodecsRegistry,
2626
common::{ascii, hash::HashSecret, lock::PyMutex, rc::PyRc},
27-
convert::ToPyObject,
27+
convert::{ToPyObject, TryFromObject},
2828
frame::{ExecutionResult, Frame, FrameRef},
2929
frozen,
3030
function::{ArgMapping, FuncArgs},
@@ -681,4 +681,84 @@ impl VirtualMachine {
681681
let val = attr_value.into();
682682
module.generic_setattr(attr_name.into_pystr_ref(self), Some(val), self)
683683
}
684+
685+
pub fn insert_sys_path(&self, obj: PyObjectRef) -> PyResult<()> {
686+
let sys_path = self.sys_module.get_attr("path", self).unwrap();
687+
self.call_method(&sys_path, "insert", (0, obj))?;
688+
Ok(())
689+
}
690+
691+
pub fn run_script(&self, scope: Scope, path: &str) -> PyResult<()> {
692+
if get_importer(path, self)?.is_some() {
693+
self.insert_sys_path(self.new_pyobj(path))?;
694+
let runpy = self.import("runpy", None, 0)?;
695+
let run_module_as_main = runpy.get_attr("_run_module_as_main", self)?;
696+
self.invoke(&run_module_as_main, (self.ctx.new_str("__main__"), false))?;
697+
return Ok(());
698+
}
699+
700+
let dir = std::path::Path::new(path)
701+
.parent()
702+
.unwrap()
703+
.to_str()
704+
.unwrap();
705+
self.insert_sys_path(self.new_pyobj(dir))?;
706+
707+
match std::fs::read_to_string(path) {
708+
Ok(source) => {
709+
self.run_code_string(scope, &source, path.to_owned())?;
710+
}
711+
Err(err) => {
712+
error!("Failed reading file '{}': {}", path, err);
713+
std::process::exit(1);
714+
}
715+
}
716+
Ok(())
717+
}
718+
719+
pub fn run_code_string(&self, scope: Scope, source: &str, source_path: String) -> PyResult {
720+
let code_obj = self
721+
.compile(source, crate::compile::Mode::Exec, source_path.clone())
722+
.map_err(|err| self.new_syntax_error(&err))?;
723+
// trace!("Code object: {:?}", code_obj.borrow());
724+
scope
725+
.globals
726+
.set_item("__file__", self.new_pyobj(source_path), self)?;
727+
self.run_code_obj(code_obj, scope)
728+
}
729+
730+
pub fn run_module(&self, module: &str) -> PyResult<()> {
731+
let runpy = self.import("runpy", None, 0)?;
732+
let run_module_as_main = runpy.get_attr("_run_module_as_main", self)?;
733+
self.invoke(&run_module_as_main, (module,))?;
734+
Ok(())
735+
}
736+
}
737+
738+
fn get_importer(path: &str, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
739+
let path_importer_cache = vm.sys_module.get_attr("path_importer_cache", vm)?;
740+
let path_importer_cache = PyDictRef::try_from_object(vm, path_importer_cache)?;
741+
if let Some(importer) = path_importer_cache.get_item_opt(path, vm)? {
742+
return Ok(Some(importer));
743+
}
744+
let path = vm.ctx.new_str(path);
745+
let path_hooks = vm.sys_module.get_attr("path_hooks", vm)?;
746+
let mut importer = None;
747+
let path_hooks: Vec<PyObjectRef> = path_hooks.try_into_value(vm)?;
748+
for path_hook in path_hooks {
749+
match vm.invoke(&path_hook, (path.clone(),)) {
750+
Ok(imp) => {
751+
importer = Some(imp);
752+
break;
753+
}
754+
Err(e) if e.fast_isinstance(&vm.ctx.exceptions.import_error) => continue,
755+
Err(e) => return Err(e),
756+
}
757+
}
758+
Ok(if let Some(imp) = importer {
759+
let imp = path_importer_cache.get_or_insert(vm, path.into(), || imp.clone())?;
760+
Some(imp)
761+
} else {
762+
None
763+
})
684764
}

0 commit comments

Comments
 (0)