Skip to content

Commit da34b86

Browse files
committed
Implement PYTHONPATH
This modifies the import logic to use sys.path, and uses PYTHONPATH to generate the initial contents of sys.path.
1 parent 42f7eca commit da34b86

4 files changed

Lines changed: 41 additions & 14 deletions

File tree

tests/snippets/import.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
assert import_target.X == aliased_func()
1414
assert import_target.Y == aliased_other_func()
1515

16+
# TODO: Once we can determine current directory, use that to construct this
17+
# path:
18+
#import sys
19+
#sys.path.append("snippets/import_directory")
20+
#import nested_target
21+
1622
#try:
1723
# X
1824
#except NameError:

tests/test_snippets.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,9 @@ def run_via_rustpython(filename, test_type):
7878
log_level = 'info' if test_type == _TestType.benchmark else 'trace'
7979
env['RUST_LOG'] = '{},cargo=error,jobserver=error'.format(log_level)
8080
env['RUST_BACKTRACE'] = '1'
81-
# XXX: Once we support PYTHONPATH (or similar), we should use that instead
82-
# of changing directory
83-
cwd = os.path.dirname(filename)
84-
with pushd(RUSTPYTHON_RUNNER_DIR):
85-
subprocess.check_call(
86-
['cargo', 'run', '--release', filename], env=env, cwd=cwd)
81+
env['PYTHONPATH'] = os.path.dirname(filename)
82+
subprocess.check_call(
83+
['cargo', 'run', '--release', filename], env=env)
8784

8885

8986
def create_test_function(cls, filename, method, test_type):

vm/src/import.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ fn import_module(vm: &mut VirtualMachine, module: &String) -> PyResult {
2121
}
2222

2323
// Time to search for module in any place:
24-
let filepath = find_source(module).map_err(|e| vm.new_exception(format!("Error: {:?}", e)))?;
24+
let filepath =
25+
find_source(vm, module).map_err(|e| vm.new_exception(format!("Error: {:?}", e)))?;
2526
let source = parser::read_file(filepath.as_path())
2627
.map_err(|e| vm.new_exception(format!("Error: {:?}", e)))?;
2728

@@ -62,14 +63,29 @@ pub fn import(vm: &mut VirtualMachine, module: &String, symbol: &Option<String>)
6263
Ok(obj)
6364
}
6465

65-
fn find_source(name: &String) -> io::Result<PathBuf> {
66+
fn find_source(vm: &VirtualMachine, name: &String) -> io::Result<PathBuf> {
67+
let sys_path = vm.sys_module.get_item("path").unwrap();
68+
let paths: Vec<PathBuf> = match sys_path.borrow().kind {
69+
PyObjectKind::List { ref elements } => elements
70+
.iter()
71+
.filter_map(|item| match item.borrow().kind {
72+
PyObjectKind::String { ref value } => Some(PathBuf::from(value)),
73+
_ => None,
74+
}).collect(),
75+
_ => panic!("sys.path unexpectedly not a list"),
76+
};
77+
6678
let suffixes = [".py", "/__init__.py"];
67-
let filepaths = suffixes
68-
.iter()
69-
.map(|suffix| format!("{}{}", name, suffix))
70-
.map(|filename| PathBuf::from(filename));
79+
let mut filepaths = vec![];
80+
for path in paths {
81+
for suffix in suffixes.iter() {
82+
let mut filepath = path.clone();
83+
filepath.push(format!("{}{}", name, suffix));
84+
filepaths.push(filepath);
85+
}
86+
}
7187

72-
match filepaths.filter(|p| p.exists()).next() {
88+
match filepaths.iter().filter(|p| p.exists()).next() {
7389
Some(path) => Ok(path.to_path_buf()),
7490
None => Err(io::Error::new(
7591
NotFound,

vm/src/sysmodule.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
/*
44
* The magic sys module.
55
*/
6+
use std::env;
67

78
use super::pyobject::{DictProtocol, PyContext, PyObjectRef};
89

910
pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
10-
let path = ctx.new_list(vec![]);
11+
let mut path_list = match env::var_os("PYTHONPATH") {
12+
Some(paths) => env::split_paths(&paths)
13+
.map(|path| ctx.new_str(path.to_str().unwrap().to_string()))
14+
.collect(),
15+
None => vec![],
16+
};
17+
path_list.insert(0, ctx.new_str("".to_string()));
18+
let path = ctx.new_list(path_list);
1119
let modules = ctx.new_dict();
1220
let sys_name = "sys".to_string();
1321
let sys_mod = ctx.new_module(&sys_name, ctx.new_scope(None));

0 commit comments

Comments
 (0)