From a5276df980ac02473e428ecfe3f5d0755aff5f28 Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 21 Jun 2019 11:34:44 +0300 Subject: [PATCH 1/4] Support relative import --- vm/src/frame.rs | 7 +++++-- vm/src/vm.rs | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 8ea1148547..7844902dc8 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -912,7 +912,9 @@ impl Frame { .iter() .map(|symbol| vm.ctx.new_str(symbol.to_string())) .collect(); - let module = vm.import(module, &vm.ctx.new_tuple(from_list))?; + let level = module.chars().take_while(|char| *char == '.').count(); + let module_name = &module[level..]; + let module = vm.import(module_name, &vm.ctx.new_tuple(from_list), level)?; if symbols.is_empty() { self.push_value(module); @@ -928,7 +930,8 @@ impl Frame { } fn import_star(&self, vm: &VirtualMachine, module: &str) -> FrameResult { - let module = vm.import(module, &vm.ctx.new_tuple(vec![]))?; + let level = module.chars().take_while(|char| *char == '.').count(); + let module = vm.import(module, &vm.ctx.new_tuple(vec![]), level)?; // Grab all the names from the module and put them in the context if let Some(dict) = &module.dict { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 1857307588..3691c2c87c 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -136,7 +136,7 @@ impl VirtualMachine { pub fn try_class(&self, module: &str, class: &str) -> PyResult { let class = self - .get_attribute(self.import(module, &self.ctx.new_tuple(vec![]))?, class)? + .get_attribute(self.import(module, &self.ctx.new_tuple(vec![]), 0)?, class)? .downcast() .expect("not a class"); Ok(class) @@ -144,7 +144,7 @@ impl VirtualMachine { pub fn class(&self, module: &str, class: &str) -> PyClassRef { let module = self - .import(module, &self.ctx.new_tuple(vec![])) + .import(module, &self.ctx.new_tuple(vec![]), 0) .unwrap_or_else(|_| panic!("unable to import {}", module)); let class = self .get_attribute(module.clone(), class) @@ -302,7 +302,7 @@ impl VirtualMachine { TryFromObject::try_from_object(self, repr) } - pub fn import(&self, module: &str, from_list: &PyObjectRef) -> PyResult { + pub fn import(&self, module: &str, from_list: &PyObjectRef, level: usize) -> PyResult { let sys_modules = self .get_attribute(self.sys_module.clone(), "modules") .unwrap(); @@ -314,9 +314,10 @@ impl VirtualMachine { func, vec![ self.ctx.new_str(module.to_string()), - self.get_none(), + self.get_locals().clone().as_object().clone(), self.get_none(), from_list.clone(), + self.ctx.new_int(level), ], ), Err(_) => Err(self.new_exception( From ae5259670c665b40b805ca53e8886af5423c2da8 Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 21 Jun 2019 11:34:55 +0300 Subject: [PATCH 2/4] Test relative import --- tests/snippets/dir_module/__init__.py | 1 + tests/snippets/dir_module/relative.py | 1 + tests/snippets/import_module.py | 2 ++ 3 files changed, 4 insertions(+) create mode 100644 tests/snippets/dir_module/__init__.py create mode 100644 tests/snippets/dir_module/relative.py create mode 100644 tests/snippets/import_module.py diff --git a/tests/snippets/dir_module/__init__.py b/tests/snippets/dir_module/__init__.py new file mode 100644 index 0000000000..8783d6d154 --- /dev/null +++ b/tests/snippets/dir_module/__init__.py @@ -0,0 +1 @@ +from .relative import value \ No newline at end of file diff --git a/tests/snippets/dir_module/relative.py b/tests/snippets/dir_module/relative.py new file mode 100644 index 0000000000..78ed77f40c --- /dev/null +++ b/tests/snippets/dir_module/relative.py @@ -0,0 +1 @@ +value = 5 diff --git a/tests/snippets/import_module.py b/tests/snippets/import_module.py new file mode 100644 index 0000000000..5570fe0d1a --- /dev/null +++ b/tests/snippets/import_module.py @@ -0,0 +1,2 @@ +import dir_module +assert dir_module.value == 5 From e8c0644a0489432e3aa2f978238522aa29c16b5b Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Fri, 21 Jun 2019 11:40:32 +0300 Subject: [PATCH 3/4] Test relative import from upper level --- tests/snippets/dir_module/__init__.py | 3 ++- tests/snippets/dir_module/dir_module_inner/__init__.py | 3 +++ tests/snippets/import_module.py | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 tests/snippets/dir_module/dir_module_inner/__init__.py diff --git a/tests/snippets/dir_module/__init__.py b/tests/snippets/dir_module/__init__.py index 8783d6d154..5d9faff33d 100644 --- a/tests/snippets/dir_module/__init__.py +++ b/tests/snippets/dir_module/__init__.py @@ -1 +1,2 @@ -from .relative import value \ No newline at end of file +from .relative import value +from .dir_module_inner import value2 diff --git a/tests/snippets/dir_module/dir_module_inner/__init__.py b/tests/snippets/dir_module/dir_module_inner/__init__.py new file mode 100644 index 0000000000..20e95590f1 --- /dev/null +++ b/tests/snippets/dir_module/dir_module_inner/__init__.py @@ -0,0 +1,3 @@ +from ..relative import value + +value2 = value + 2 diff --git a/tests/snippets/import_module.py b/tests/snippets/import_module.py index 5570fe0d1a..b82aad5091 100644 --- a/tests/snippets/import_module.py +++ b/tests/snippets/import_module.py @@ -1,2 +1,3 @@ import dir_module assert dir_module.value == 5 +assert dir_module.value2 == 7 From da4c0bccfad8484f871c34bfa863ee86ada4ba04 Mon Sep 17 00:00:00 2001 From: Aviv Palivoda Date: Tue, 25 Jun 2019 18:14:29 +0300 Subject: [PATCH 4/4] pass local variables to __import__ only if there is a frame --- vm/src/vm.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 3691c2c87c..9bcb77128c 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -314,7 +314,11 @@ impl VirtualMachine { func, vec![ self.ctx.new_str(module.to_string()), - self.get_locals().clone().as_object().clone(), + if self.current_frame().is_some() { + self.get_locals().into_object() + } else { + self.get_none() + }, self.get_none(), from_list.clone(), self.ctx.new_int(level),