Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 53 additions & 7 deletions crates/vm/src/vm/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ impl VirtualMachine {
compiler::compile(source, mode, &source_path, opts).map(|code| self.ctx.new_code(code))
}

// pymain_run_file_obj
pub fn run_script(&self, scope: Scope, path: &str) -> PyResult<()> {
// when pymain_run_module?
if get_importer(path, self)?.is_some() {
self.insert_sys_path(self.new_pyobj(path))?;
let runpy = self.import("runpy", 0)?;
Expand All @@ -35,6 +37,7 @@ impl VirtualMachine {
return Ok(());
}

// TODO: check if this is proper place
if !self.state.settings.safe_path {
let dir = std::path::Path::new(path)
.parent()
Expand All @@ -44,19 +47,62 @@ impl VirtualMachine {
self.insert_sys_path(self.new_pyobj(dir))?;
}

match std::fs::read_to_string(path) {
Ok(source) => {
self.run_code_string(scope, &source, path.to_owned())?;
self.run_any_file(scope, path)
}

// = _PyRun_AnyFileObject
fn run_any_file(&self, scope: Scope, path: &str) -> PyResult<()> {
let path = if path.is_empty() { "???" } else { path };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are those ??? is something that CPython is also doing?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, _PyRun_AnyFileObject does


self.run_simple_file(scope, path)
}

// = _PyRun_SimpleFileObject
fn run_simple_file(&self, scope: Scope, path: &str) -> PyResult<()> {
// __main__ is given by scope
let sys_modules = self.sys_module.get_attr(identifier!(self, modules), self)?;
let main_module = sys_modules.get_item(identifier!(self, __main__), self)?;
let module_dict = main_module.dict().expect("main module must have __dict__");
if !module_dict.contains_key(identifier!(self, __file__), self) {
module_dict.set_item(
identifier!(self, __file__),
self.ctx.new_str(path).into(),
self,
)?;
module_dict.set_item(identifier!(self, __cached__), self.ctx.none(), self)?;
}

// Consider to use enum to distinguish `path`
// https://github.com/RustPython/RustPython/pull/6276#discussion_r2529849479

// TODO: check .pyc here
let pyc = false;
if pyc {
todo!("running pyc is not implemented yet");
} else {
if path != "<stdin>" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How feasible doing something like:

enum InputFile {
    StdIn,
    Path(&str),
    Pyc(&str)
}

be?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that sounds like a good suggestion.
Currently, I am not sure how stdin can come here in RustPython. I ported a part of CLI run, but not entirely.
I will leave a comment about this to make sure it can be checked later.

// TODO: set_main_loader(dict, filename, "SourceFileLoader");
}
Err(err) => {
error!("Failed reading file '{path}': {err}");
// TODO: Need to change to ExitCode or Termination
std::process::exit(1);
// TODO: replace to something equivalent to py_run_file
match std::fs::read_to_string(path) {
Ok(source) => {
let code_obj = self
.compile(&source, compiler::Mode::Exec, path.to_owned())
.map_err(|err| self.new_syntax_error(&err, Some(&source)))?;
// trace!("Code object: {:?}", code_obj.borrow());
self.run_code_obj(code_obj, scope)?;
}
Err(err) => {
error!("Failed reading file '{path}': {err}");
// TODO: Need to change to ExitCode or Termination
std::process::exit(1);
}
}
}
Ok(())
}

// TODO: deprecate or reimplement using other primitive functions
pub fn run_code_string(&self, scope: Scope, source: &str, source_path: String) -> PyResult {
let code_obj = self
.compile(source, compiler::Mode::Exec, source_path.clone())
Expand Down
30 changes: 16 additions & 14 deletions crates/vm/src/vm/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,13 @@ declare_const_name! {
__build_class__,
__builtins__,
__bytes__,
__cached__,
__call__,
__ceil__,
__cformat__,
__class__,
__classcell__,
__class_getitem__,
__classcell__,
__complex__,
__contains__,
__copy__,
Expand Down Expand Up @@ -234,26 +235,27 @@ declare_const_name! {
_attributes,
_fields,
_showwarnmsg,
backslashreplace,
close,
copy,
decode,
encode,
keys,
items,
values,
version,
update,
copy,
flush,
close,
WarningMessage,
strict,
ignore,
replace,
xmlcharrefreplace,
backslashreplace,
items,
keys,
modules,
namereplace,
surrogatepass,
replace,
strict,
surrogateescape,
surrogatepass,
update,
utf_8: "utf-8",
values,
version,
WarningMessage,
xmlcharrefreplace,
}

// Basic objects:
Expand Down
5 changes: 5 additions & 0 deletions extra_tests/snippets/builtin___main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import sys

main_module = sys.modules["__main__"]
assert main_module.__file__.endswith("builtin___main__.py")
assert main_module.__cached__ is None
8 changes: 5 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ fn install_pip(installer: InstallPipMode, scope: Scope, vm: &VirtualMachine) ->
}
}

// pymain_run_python
fn run_rustpython(vm: &VirtualMachine, run_mode: RunMode) -> PyResult<()> {
#[cfg(feature = "flame-it")]
let main_guard = flame::start_guard("RustPython main");
Expand Down Expand Up @@ -206,9 +207,10 @@ fn run_rustpython(vm: &VirtualMachine, run_mode: RunMode) -> PyResult<()> {
vm.run_module(&module)
}
RunMode::InstallPip(installer) => install_pip(installer, scope.clone(), vm),
RunMode::Script(script) => {
debug!("Running script {}", &script);
vm.run_script(scope.clone(), &script)
RunMode::Script(script_path) => {
// pymain_run_file
debug!("Running script {}", &script_path);
vm.run_script(scope.clone(), &script_path)
}
RunMode::Repl => Ok(()),
};
Expand Down
Loading