Skip to content

Commit 946df53

Browse files
Merge pull request RustPython#237 from johndaniels/add-star-import
Add 'from x import *' syntax.
2 parents 366f3e2 + ac3da8b commit 946df53

File tree

6 files changed

+64
-15
lines changed

6 files changed

+64
-15
lines changed

tests/snippets/import.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import import_target, import_target as aliased
22
from import_target import func, other_func
33
from import_target import func as aliased_func, other_func as aliased_other_func
4+
from import_star import *
45

56
assert import_target.X == import_target.func()
67
assert import_target.X == func()
@@ -13,6 +14,8 @@
1314
assert import_target.X == aliased_func()
1415
assert import_target.Y == aliased_other_func()
1516

17+
assert STAR_IMPORT == '123'
18+
1619
# TODO: Once we can determine current directory, use that to construct this
1720
# path:
1821
#import sys

tests/snippets/import_star.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This is used by import.py; the two should be modified in concert
2+
3+
STAR_IMPORT = '123'

vm/src/bytecode.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ pub enum Instruction {
6666
name: String,
6767
symbol: Option<String>,
6868
},
69+
ImportStar {
70+
name: String,
71+
},
6972
LoadName {
7073
name: String,
7174
},

vm/src/compile.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -156,19 +156,28 @@ impl Compiler {
156156
alias,
157157
} in import_parts
158158
{
159-
self.emit(Instruction::Import {
160-
name: module.clone(),
161-
symbol: symbol.clone().map(|s| s.clone()),
162-
});
163-
self.emit(Instruction::StoreName {
164-
name: match alias {
165-
Some(alias) => alias.clone(),
166-
None => match symbol {
167-
Some(symbol) => symbol.clone(),
168-
None => module.clone(),
169-
},
170-
},
171-
});
159+
match symbol {
160+
Some(name) if name == "*" => {
161+
self.emit(Instruction::ImportStar {
162+
name: module.clone(),
163+
});
164+
}
165+
_ => {
166+
self.emit(Instruction::Import {
167+
name: module.clone(),
168+
symbol: symbol.clone().map(|s| s.clone()),
169+
});
170+
self.emit(Instruction::StoreName {
171+
name: match alias {
172+
Some(alias) => alias.clone(),
173+
None => match symbol {
174+
Some(symbol) => symbol.clone(),
175+
None => module.clone(),
176+
},
177+
},
178+
});
179+
}
180+
}
172181
}
173182
}
174183
ast::Statement::Expression { expression } => {

vm/src/frame.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::path::PathBuf;
77

88
use super::builtins;
99
use super::bytecode;
10-
use super::import::import;
10+
use super::import::{import, import_module};
1111
use super::obj::objbool;
1212
use super::obj::objcode;
1313
use super::obj::objdict;
@@ -182,6 +182,7 @@ impl Frame {
182182
ref name,
183183
ref symbol,
184184
} => self.import(vm, name, symbol),
185+
bytecode::Instruction::ImportStar { ref name } => self.import_star(vm, name),
185186
bytecode::Instruction::LoadName { ref name } => self.load_name(vm, name),
186187
bytecode::Instruction::StoreName { ref name } => self.store_name(vm, name),
187188
bytecode::Instruction::DeleteName { ref name } => self.delete_name(vm, name),
@@ -677,6 +678,26 @@ impl Frame {
677678
Ok(None)
678679
}
679680

681+
fn import_star(&mut self, vm: &mut VirtualMachine, module: &str) -> FrameResult {
682+
let current_path = match &self.code.source_path {
683+
Some(source_path) => {
684+
let mut source_pathbuf = PathBuf::from(source_path);
685+
source_pathbuf.pop();
686+
source_pathbuf
687+
}
688+
None => PathBuf::from("."),
689+
};
690+
691+
// Grab all the names from the module and put them in the context
692+
let obj = import_module(vm, current_path, module)?;
693+
694+
for (k, v) in obj.get_key_value_pairs().iter() {
695+
vm.ctx
696+
.set_item(&self.locals, &objstr::get_value(k), v.clone());
697+
}
698+
Ok(None)
699+
}
700+
680701
// Unwind all blocks:
681702
fn unwind_blocks(&mut self, vm: &mut VirtualMachine) -> Option<PyObjectRef> {
682703
loop {

vm/src/pyobject.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use super::vm::VirtualMachine;
2525
use num_bigint::BigInt;
2626
use num_complex::Complex64;
2727
use num_traits::{One, Zero};
28-
use std::cell::RefCell;
28+
use std::cell::{Ref, RefCell};
2929
use std::collections::HashMap;
3030
use std::fmt;
3131
use std::rc::{Rc, Weak};
@@ -681,6 +681,7 @@ impl AttributeProtocol for PyObjectRef {
681681
pub trait DictProtocol {
682682
fn contains_key(&self, k: &str) -> bool;
683683
fn get_item(&self, k: &str) -> Option<PyObjectRef>;
684+
fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)>;
684685
}
685686

686687
impl DictProtocol for PyObjectRef {
@@ -701,6 +702,15 @@ impl DictProtocol for PyObjectRef {
701702
_ => panic!("TODO"),
702703
}
703704
}
705+
706+
fn get_key_value_pairs(&self) -> Vec<(PyObjectRef, PyObjectRef)> {
707+
match self.borrow().kind {
708+
PyObjectKind::Dict { elements: _ } => objdict::get_key_value_pairs(self),
709+
PyObjectKind::Module { name: _, ref dict } => dict.get_key_value_pairs(),
710+
PyObjectKind::Scope { ref scope } => scope.locals.get_key_value_pairs(),
711+
_ => panic!("TODO"),
712+
}
713+
}
704714
}
705715

706716
impl fmt::Debug for PyObject {

0 commit comments

Comments
 (0)