Skip to content

CPython compatible Drop for PyObjectRc #2128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Sep 18, 2020
3 changes: 2 additions & 1 deletion Lib/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@ def Detach(self):
def __repr__(self):
return "%s(%d)" % (self.__class__.__name__, int(self))

__del__ = Close
# XXX: RustPython; OSError('The handle is invalid. (os error 6)')
# __del__ = Close
else:
# When select or poll has indicated that the file is writable,
# we can write up to _PIPE_BUF bytes without risk of blocking.
Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -1326,8 +1326,6 @@ def __hash__(self):
pair = [X(), 123]
dict([pair])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_oob_indexing_dictiter_iternextitem(self):
class X(int):
def __del__(self):
Expand Down
42 changes: 22 additions & 20 deletions benchmarks/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

extern crate test;

use test::Bencher;

use rustpython_compiler::compile;
use rustpython_vm::pyobject::PyResult;
use rustpython_vm::VirtualMachine;
use rustpython_vm::Interpreter;

const MINIDOM: &str = include_str!("./benchmarks/minidom.py");
const NBODY: &str = include_str!("./benchmarks/nbody.py");
const MANDELBROT: &str = include_str!("./benchmarks/mandelbrot.py");

#[bench]
fn bench_tokenization(b: &mut test::Bencher) {
fn bench_tokenization(b: &mut Bencher) {
use rustpython_parser::lexer::{make_tokenizer, Tok};

let source = MINIDOM;
Expand All @@ -26,7 +28,7 @@ fn bench_tokenization(b: &mut test::Bencher) {
}

#[bench]
fn bench_rustpy_parse_to_ast(b: &mut test::Bencher) {
fn bench_rustpy_parse_to_ast(b: &mut Bencher) {
use rustpython_parser::parser::parse_program;

let source = MINIDOM;
Expand All @@ -36,7 +38,7 @@ fn bench_rustpy_parse_to_ast(b: &mut test::Bencher) {
}

#[bench]
fn bench_cpython_parse_to_ast(b: &mut test::Bencher) {
fn bench_cpython_parse_to_ast(b: &mut Bencher) {
let source = MINIDOM;

let gil = cpython::Python::acquire_gil();
Expand All @@ -56,7 +58,7 @@ fn bench_cpython_parse_to_ast(b: &mut test::Bencher) {
})
}

fn bench_cpython(b: &mut test::Bencher, source: &str) {
fn bench_cpython(b: &mut Bencher, source: &str) {
let gil = cpython::Python::acquire_gil();
let python = gil.python();

Expand All @@ -70,36 +72,36 @@ fn bench_cpython(b: &mut test::Bencher, source: &str) {
}

#[bench]
fn bench_cpython_nbody(b: &mut test::Bencher) {
fn bench_cpython_nbody(b: &mut Bencher) {
bench_cpython(b, NBODY)
}

#[bench]
fn bench_cpython_mandelbrot(b: &mut test::Bencher) {
fn bench_cpython_mandelbrot(b: &mut Bencher) {
bench_cpython(b, MANDELBROT)
}

fn bench_rustpy(b: &mut test::Bencher, name: &str, source: &str) {
fn bench_rustpy(b: &mut Bencher, name: &str, source: &str) {
// NOTE: Take long time.
let vm = VirtualMachine::default();

let code = vm
.compile(source, compile::Mode::Exec, name.to_owned())
.unwrap();

b.iter(|| {
let scope = vm.new_scope_with_builtins();
let res: PyResult = vm.run_code_obj(code.clone(), scope);
vm.unwrap_pyresult(res);
Interpreter::default().enter(|vm| {
let code = vm
.compile(source, compile::Mode::Exec, name.to_owned())
.unwrap();

b.iter(|| {
let scope = vm.new_scope_with_builtins();
let res: PyResult = vm.run_code_obj(code.clone(), scope);
vm.unwrap_pyresult(res);
})
})
}

#[bench]
fn bench_rustpy_nbody(b: &mut test::Bencher) {
fn bench_rustpy_nbody(b: &mut Bencher) {
bench_rustpy(b, "nbody.py", NBODY)
}

#[bench]
fn bench_rustpy_mandelbrot(b: &mut test::Bencher) {
fn bench_rustpy_mandelbrot(b: &mut Bencher) {
bench_rustpy(b, "mandelbrot.py", MANDELBROT)
}
4 changes: 3 additions & 1 deletion examples/freeze/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ use std::collections::HashMap;
use rustpython_vm as vm;

fn main() -> vm::pyobject::PyResult<()> {
let vm = vm::VirtualMachine::new(vm::PySettings::default());
vm::Interpreter::default().enter(run)
}

fn run(vm: &vm::VirtualMachine) -> vm::pyobject::PyResult<()> {
let scope = vm.new_scope_with_builtins();

// the file parameter is relevant to the directory where the crate's Cargo.toml is located, see $CARGO_MANIFEST_DIR:
Expand Down
24 changes: 12 additions & 12 deletions examples/hello_embed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ use rustpython_compiler as compiler;
use rustpython_vm as vm;

fn main() -> vm::pyobject::PyResult<()> {
let vm = vm::VirtualMachine::new(vm::PySettings::default());
vm::Interpreter::default().enter(|vm| {
let scope = vm.new_scope_with_builtins();

let scope = vm.new_scope_with_builtins();
let code_obj = vm
.compile(
r#"print("Hello World!")"#,
compiler::compile::Mode::Exec,
"<embedded>".to_owned(),
)
.map_err(|err| vm.new_syntax_error(&err))?;

let code_obj = vm
.compile(
r#"print("Hello World!")"#,
compiler::compile::Mode::Exec,
"<embedded>".to_owned(),
)
.map_err(|err| vm.new_syntax_error(&err))?;
vm.run_code_obj(code_obj, scope)?;

vm.run_code_obj(code_obj, scope)?;

Ok(())
Ok(())
})
}
11 changes: 7 additions & 4 deletions examples/mini_repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,17 @@ fn on(b: bool) {
}

fn main() -> vm::pyobject::PyResult<()> {
vm::Interpreter::default().enter(run)
}

fn run(vm: &vm::VirtualMachine) -> vm::pyobject::PyResult<()> {
let mut input = String::with_capacity(50);
let stdin = std::io::stdin();

let vm = vm::VirtualMachine::new(vm::PySettings::default());
let scope: vm::scope::Scope = vm.new_scope_with_builtins();

// typing `quit()` is too long, let's make `on(False)` work instead.
scope.globals.set_item("on", vm.ctx.new_function(on), &vm)?;
scope.globals.set_item("on", vm.ctx.new_function(on), vm)?;

// let's include a fibonacci function, but let's be lazy and write it in Python
add_python_function!(
Expand Down Expand Up @@ -97,11 +100,11 @@ fn main() -> vm::pyobject::PyResult<()> {
Ok(output) => {
// store the last value in the "last" variable
if !vm.is_none(&output) {
scope.globals.set_item("last", output, &vm)?;
scope.globals.set_item("last", output, vm)?;
}
}
Err(e) => {
vm::exceptions::print_exception(&vm, e);
vm::exceptions::print_exception(vm, e);
}
}
}
Expand Down
118 changes: 61 additions & 57 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustpython_vm::{
obj::{objint::PyInt, objtype},
pyobject::{BorrowValue, ItemProtocol, PyResult},
scope::Scope,
util, InitParameter, PySettings, VirtualMachine,
util, InitParameter, Interpreter, PySettings, VirtualMachine,
};

use std::convert::TryInto;
Expand All @@ -29,12 +29,7 @@ fn main() {
env_logger::init();
let app = App::new("RustPython");
let matches = parse_arguments(app);
let mut settings = create_settings(&matches);

// We only include the standard library bytecode in WASI when initializing
if cfg!(target_os = "wasi") {
settings.initialization_parameter = InitParameter::InitializeInternal;
}
let settings = create_settings(&matches);

// don't translate newlines (\r\n <=> \n)
#[cfg(windows)]
Expand All @@ -49,49 +44,58 @@ fn main() {
}
}

let vm = VirtualMachine::new(settings);
// We only include the standard library bytecode in WASI when initializing
let init = if cfg!(target_os = "wasi") {
InitParameter::Internal
} else {
InitParameter::External
};

let interp = Interpreter::new(settings, init);

let res = run_rustpython(&vm, &matches);
interp.enter(move |vm| {
let res = run_rustpython(vm, &matches);

#[cfg(feature = "flame-it")]
{
main_guard.end();
if let Err(e) = write_profile(&matches) {
error!("Error writing profile information: {}", e);
#[cfg(feature = "flame-it")]
{
main_guard.end();
if let Err(e) = write_profile(&matches) {
error!("Error writing profile information: {}", e);
}
}
}

// See if any exception leaked out:
if let Err(err) = res {
if objtype::isinstance(&err, &vm.ctx.exceptions.system_exit) {
let args = err.args();
match args.borrow_value().len() {
0 => return,
1 => match_class!(match args.borrow_value()[0].clone() {
i @ PyInt => {
use num_traits::cast::ToPrimitive;
process::exit(i.borrow_value().to_i32().unwrap_or(0));
}
arg => {
if vm.is_none(&arg) {
return;
// See if any exception leaked out:
if let Err(err) = res {
if objtype::isinstance(&err, &vm.ctx.exceptions.system_exit) {
let args = err.args();
match args.borrow_value().len() {
0 => return,
1 => match_class!(match args.borrow_value()[0].clone() {
i @ PyInt => {
use num_traits::cast::ToPrimitive;
process::exit(i.borrow_value().to_i32().unwrap_or(0));
}
if let Ok(s) = vm.to_str(&arg) {
eprintln!("{}", s);
arg => {
if vm.is_none(&arg) {
return;
}
if let Ok(s) = vm.to_str(&arg) {
eprintln!("{}", s);
}
}
}),
_ => {
if let Ok(r) = vm.to_repr(args.as_object()) {
eprintln!("{}", r);
}
}
}),
_ => {
if let Ok(r) = vm.to_repr(args.as_object()) {
eprintln!("{}", r);
}
}
} else {
print_exception(&vm, err);
}
} else {
print_exception(&vm, err);
process::exit(1);
}
process::exit(1);
}
})
}

fn parse_arguments<'a>(app: App<'a, '_>) -> ArgMatches<'a> {
Expand Down Expand Up @@ -493,21 +497,21 @@ fn run_script(vm: &VirtualMachine, scope: Scope, script_file: &str) -> PyResult<

#[test]
fn test_run_script() {
let vm: VirtualMachine = Default::default();

// test file run
let r = run_script(
&vm,
vm.new_scope_with_builtins(),
"extra_tests/snippets/dir_main/__main__.py",
);
assert!(r.is_ok());

// test module run
let r = run_script(
&vm,
vm.new_scope_with_builtins(),
"extra_tests/snippets/dir_main",
);
assert!(r.is_ok());
Interpreter::default().enter(|vm| {
// test file run
let r = run_script(
vm,
vm.new_scope_with_builtins(),
"extra_tests/snippets/dir_main/__main__.py",
);
assert!(r.is_ok());

// test module run
let r = run_script(
vm,
vm.new_scope_with_builtins(),
"extra_tests/snippets/dir_main",
);
assert!(r.is_ok());
})
}
Loading