Skip to content

Commit 937704f

Browse files
Merge pull request RustPython#881 from youknowone/globals-builtins
Add __builtins__ to globals()
2 parents 9f39fa5 + 5093940 commit 937704f

File tree

10 files changed

+65
-14
lines changed

10 files changed

+65
-14
lines changed

benchmarks/bench.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn bench_rustpy_nbody(b: &mut test::Bencher) {
9999
};
100100

101101
b.iter(|| {
102-
let scope = vm.ctx.new_scope();
102+
let scope = vm.new_scope_with_builtins();
103103
let res: PyResult = vm.run_code_obj(code.clone(), scope);
104104
assert!(res.is_ok());
105105
})
@@ -118,7 +118,7 @@ fn bench_rustpy_mandelbrot(b: &mut test::Bencher) {
118118
};
119119

120120
b.iter(|| {
121-
let scope = vm.ctx.new_scope();
121+
let scope = vm.new_scope_with_builtins();
122122
let res: PyResult = vm.run_code_obj(code.clone(), scope);
123123
assert!(res.is_ok());
124124
})

src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ fn _run_string(vm: &VirtualMachine, source: &str, source_path: String) -> PyResu
7777
// trace!("Code object: {:?}", code_obj.borrow());
7878
let attrs = vm.ctx.new_dict();
7979
attrs.set_item("__file__", vm.new_str(source_path), vm)?;
80-
vm.run_code_obj(code_obj, Scope::new(None, attrs))
80+
vm.run_code_obj(code_obj, Scope::with_builtins(None, attrs, vm))
8181
}
8282

8383
fn handle_exception(vm: &VirtualMachine, result: PyResult) {
@@ -217,7 +217,7 @@ fn run_shell(vm: &VirtualMachine) -> PyResult {
217217
"Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596}",
218218
crate_version!()
219219
);
220-
let vars = vm.ctx.new_scope();
220+
let vars = vm.new_scope_with_builtins();
221221

222222
// Read a single line:
223223
let mut input = String::new();

tests/snippets/builtins_module.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from testutils import assertRaises
2+
3+
assert '__builtins__' in globals()
4+
# assert type(__builtins__).__name__ == 'module'
5+
with assertRaises(AttributeError):
6+
__builtins__.__builtins__
7+
8+
__builtins__.x = 'new'
9+
assert x == 'new'
10+
11+
exec('assert "__builtins__" in globals()', dict())
12+
exec('assert __builtins__ == 7', {'__builtins__': 7})
13+
exec('assert not isinstance(__builtins__, dict)')
14+
exec('assert isinstance(__builtins__, dict)', {})
15+
16+
namespace = {}
17+
exec('', namespace)
18+
assert namespace['__builtins__'] == __builtins__.__dict__
19+
20+
# with assertRaises(NameError):
21+
# exec('print(__builtins__)', {'__builtins__': {}})
22+
23+
# __builtins__ is deletable but names are alive
24+
del __builtins__
25+
with assertRaises(NameError):
26+
__builtins__
27+
28+
assert print

vm/src/builtins.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,18 +218,27 @@ fn make_scope(
218218
}
219219
None => None,
220220
};
221-
222221
let current_scope = vm.current_scope();
223222
let globals = match globals {
224-
Some(dict) => dict.clone().downcast().unwrap(),
223+
Some(dict) => {
224+
let dict: PyDictRef = dict.clone().downcast().unwrap();
225+
if !dict.contains_key("__builtins__", vm) {
226+
let builtins_dict = vm.builtins.dict.as_ref().unwrap().as_object();
227+
dict.set_item("__builtins__", builtins_dict.clone(), vm)
228+
.unwrap();
229+
}
230+
dict
231+
}
225232
None => current_scope.globals.clone(),
226233
};
234+
227235
let locals = match locals {
228236
Some(dict) => dict.clone().downcast().ok(),
229237
None => current_scope.get_only_locals(),
230238
};
231239

232-
Ok(Scope::new(locals, globals))
240+
let scope = Scope::with_builtins(locals, globals, vm);
241+
Ok(scope)
233242
}
234243

235244
fn builtin_format(

vm/src/eval.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ mod tests {
2424
fn test_print_42() {
2525
let source = String::from("print('Hello world')\n");
2626
let mut vm = VirtualMachine::new();
27-
let vars = vm.ctx.new_scope();
27+
let vars = vm.new_scope_with_builtins();
2828
let _result = eval(&mut vm, &source, vars, "<unittest>");
2929

3030
// TODO: check result?

vm/src/frame.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ impl Scope {
9898
Scope { locals, globals }
9999
}
100100

101+
pub fn with_builtins(
102+
locals: Option<PyDictRef>,
103+
globals: PyDictRef,
104+
vm: &VirtualMachine,
105+
) -> Scope {
106+
if !globals.contains_key("__builtins__", vm) {
107+
globals
108+
.clone()
109+
.set_item("__builtins__", vm.builtins.clone(), vm)
110+
.unwrap();
111+
}
112+
Scope::new(locals, globals)
113+
}
114+
101115
pub fn get_locals(&self) -> PyDictRef {
102116
match self.locals.iter().next() {
103117
Some(dict) => dict.clone(),

vm/src/import.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub fn import_file(
6161
sys_modules.set_item(module_name, module.clone(), vm)?;
6262

6363
// Execute main code in module:
64-
vm.run_code_obj(code_obj, Scope::new(None, attrs))?;
64+
vm.run_code_obj(code_obj, Scope::with_builtins(None, attrs, vm))?;
6565
Ok(module)
6666
}
6767

vm/src/pyobject.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -648,10 +648,6 @@ impl PyContext {
648648
objtype::new(self.type_type(), name, vec![base], PyAttributes::new()).unwrap()
649649
}
650650

651-
pub fn new_scope(&self) -> Scope {
652-
Scope::new(None, self.new_dict())
653-
}
654-
655651
pub fn new_module(&self, name: &str, dict: PyDictRef) -> PyObjectRef {
656652
PyObject::new(
657653
PyModule {

vm/src/vm.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,10 @@ impl VirtualMachine {
250250
syntax_error
251251
}
252252

253+
pub fn new_scope_with_builtins(&self) -> Scope {
254+
Scope::with_builtins(None, self.ctx.new_dict(), self)
255+
}
256+
253257
pub fn get_none(&self) -> PyObjectRef {
254258
self.ctx.none()
255259
}

wasm/lib/src/vm_class.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub(crate) struct StoredVirtualMachine {
2626
impl StoredVirtualMachine {
2727
fn new(id: String, inject_browser_module: bool) -> StoredVirtualMachine {
2828
let mut vm = VirtualMachine::new();
29-
let scope = vm.ctx.new_scope();
29+
let scope = vm.new_scope_with_builtins();
3030
if inject_browser_module {
3131
setup_browser_module(&vm);
3232
}

0 commit comments

Comments
 (0)