Skip to content

Commit 175ca34

Browse files
committed
Add __import__
1 parent ded7acc commit 175ca34

File tree

5 files changed

+59
-44
lines changed

5 files changed

+59
-44
lines changed

tests/snippets/import.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
except ImportError:
2323
pass
2424

25+
26+
test = __import__("import_target")
27+
assert test.X == import_target.X
28+
29+
2530
# TODO: Once we can determine current directory, use that to construct this
2631
# path:
2732
#import sys

vm/src/builtins.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
// use std::ops::Deref;
66
use std::char;
77
use std::io::{self, Write};
8+
use std::path::PathBuf;
89

910
use crate::compile;
11+
use crate::import::import_module;
1012
use crate::obj::objbool;
1113
use crate::obj::objdict;
1214
use crate::obj::objint;
@@ -713,8 +715,27 @@ fn builtin_sum(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
713715
Ok(sum)
714716
}
715717

718+
// Should be renamed to builtin___import__?
719+
fn builtin_import(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
720+
arg_check!(
721+
vm,
722+
args,
723+
required = [(name, Some(vm.ctx.str_type()))],
724+
optional = [
725+
(_globals, Some(vm.ctx.dict_type())),
726+
(_locals, Some(vm.ctx.dict_type()))
727+
]
728+
);
729+
let current_path = {
730+
let mut source_pathbuf = PathBuf::from(&vm.current_frame().code.source_path);
731+
source_pathbuf.pop();
732+
source_pathbuf
733+
};
734+
735+
import_module(vm, current_path, &objstr::get_value(name))
736+
}
737+
716738
// builtin_vars
717-
// builtin___import__
718739

719740
pub fn make_module(ctx: &PyContext) -> PyObjectRef {
720741
let py_mod = py_module!(ctx, "__builtins__", {
@@ -783,6 +804,7 @@ pub fn make_module(ctx: &PyContext) -> PyObjectRef {
783804
"tuple" => ctx.tuple_type(),
784805
"type" => ctx.type_type(),
785806
"zip" => ctx.zip_type(),
807+
"__import__" => ctx.new_rustfunc(builtin_import),
786808

787809
// Constants
788810
"NotImplemented" => ctx.not_implemented.clone(),

vm/src/frame.rs

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::cell::RefCell;
22
use std::fmt;
3-
use std::path::PathBuf;
43
use std::rc::Rc;
54

65
use num_bigint::BigInt;
@@ -9,7 +8,6 @@ use rustpython_parser::ast;
98

109
use crate::builtins;
1110
use crate::bytecode;
12-
use crate::import::{import, import_module};
1311
use crate::obj::objbool;
1412
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
1513
use crate::obj::objcode;
@@ -22,8 +20,8 @@ use crate::obj::objslice::PySlice;
2220
use crate::obj::objstr;
2321
use crate::obj::objtype;
2422
use crate::pyobject::{
25-
DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2,
26-
PyObjectRef, PyResult, TryFromObject, TypeProtocol,
23+
AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectPayload,
24+
PyObjectPayload2, PyObjectRef, PyResult, TryFromObject, TypeProtocol,
2725
};
2826
use crate::vm::VirtualMachine;
2927

@@ -815,30 +813,39 @@ impl Frame {
815813
module: &str,
816814
symbol: &Option<String>,
817815
) -> FrameResult {
818-
let current_path = {
819-
let mut source_pathbuf = PathBuf::from(&self.code.source_path);
820-
source_pathbuf.pop();
821-
source_pathbuf
816+
let import = vm.builtins.get_item("__import__");
817+
let module = match import {
818+
Some(func) => vm.invoke(func, vec![vm.ctx.new_str(module.to_string())])?,
819+
None => panic!("No __import__ in builtins"),
822820
};
823821

824-
let obj = import(vm, current_path, module, symbol)?;
822+
// If we're importing a symbol, look it up and use it, otherwise construct a module and return
823+
// that
824+
let obj = match symbol {
825+
Some(symbol) => module.get_attr(symbol).map_or_else(
826+
|| {
827+
let import_error = vm.context().exceptions.import_error.clone();
828+
Err(vm.new_exception(import_error, format!("cannot import name '{}'", symbol)))
829+
},
830+
Ok,
831+
),
832+
None => Ok(module),
833+
};
825834

826835
// Push module on stack:
827-
self.push_value(obj);
836+
self.push_value(obj?);
828837
Ok(None)
829838
}
830839

831840
fn import_star(&self, vm: &mut VirtualMachine, module: &str) -> FrameResult {
832-
let current_path = {
833-
let mut source_pathbuf = PathBuf::from(&self.code.source_path);
834-
source_pathbuf.pop();
835-
source_pathbuf
841+
let import = vm.builtins.get_item("__import__");
842+
let module = match import {
843+
Some(func) => vm.invoke(func, vec![vm.ctx.new_str(module.to_string())])?,
844+
None => panic!("No __import__ in builtins"),
836845
};
837846

838847
// Grab all the names from the module and put them in the context
839-
let obj = import_module(vm, current_path, module)?;
840-
841-
for (k, v) in obj.get_key_value_pairs().iter() {
848+
for (k, v) in module.get_key_value_pairs().iter() {
842849
self.scope.store_name(&vm, &objstr::get_value(k), v.clone());
843850
}
844851
Ok(None)

vm/src/import.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,28 +63,6 @@ pub fn import_module(
6363
Ok(module)
6464
}
6565

66-
pub fn import(
67-
vm: &mut VirtualMachine,
68-
current_path: PathBuf,
69-
module_name: &str,
70-
symbol: &Option<String>,
71-
) -> PyResult {
72-
let module = import_module(vm, current_path, module_name)?;
73-
// If we're importing a symbol, look it up and use it, otherwise construct a module and return
74-
// that
75-
if let Some(symbol) = symbol {
76-
module.get_attr(symbol).map_or_else(
77-
|| {
78-
let import_error = vm.context().exceptions.import_error.clone();
79-
Err(vm.new_exception(import_error, format!("cannot import name '{}'", symbol)))
80-
},
81-
Ok,
82-
)
83-
} else {
84-
Ok(module)
85-
}
86-
}
87-
8866
fn find_source(vm: &VirtualMachine, current_path: PathBuf, name: &str) -> Result<PathBuf, String> {
8967
let sys_path = vm.sys_module.get_attr("path").unwrap();
9068
let mut paths: Vec<PathBuf> = objsequence::get_elements(&sys_path)

vm/src/vm.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ use std::sync::{Mutex, MutexGuard};
1313

1414
use crate::builtins;
1515
use crate::bytecode;
16-
use crate::frame::ExecutionResult;
17-
use crate::frame::Scope;
16+
use crate::frame::{ExecutionResult, Frame, Scope};
1817
use crate::obj::objbool;
1918
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
2019
use crate::obj::objcode;
@@ -94,9 +93,13 @@ impl VirtualMachine {
9493
result
9594
}
9695

97-
pub fn current_scope(&self) -> &Scope {
96+
pub fn current_frame(&self) -> &Frame {
9897
let current_frame = &self.frames[self.frames.len() - 1];
99-
let frame = objframe::get_value(current_frame);
98+
objframe::get_value(current_frame)
99+
}
100+
101+
pub fn current_scope(&self) -> &Scope {
102+
let frame = self.current_frame();
100103
&frame.scope
101104
}
102105

0 commit comments

Comments
 (0)