mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Merge pull request #1313 from RustPython/coolreader18/keyboardinterrupt
Raise a KeyboardInterrupt on a SIGINT
This commit is contained in:
6 files changed
+209
-127
No files matched your search
+74
-55
@@ -9,9 +9,9 @@ use rustpython_compiler::{compile, error::CompileError, error::CompileErrorType}
|
||||
use rustpython_parser::error::ParseErrorType;
|
||||
use rustpython_vm::{
|
||||
import,
|
||||
obj::objstr,
|
||||
obj::objstr::PyStringRef,
|
||||
print_exception,
|
||||
pyobject::{ItemProtocol, PyResult},
|
||||
pyobject::{ItemProtocol, PyObjectRef, PyResult},
|
||||
scope::Scope,
|
||||
util, PySettings, VirtualMachine,
|
||||
};
|
||||
@@ -434,40 +434,32 @@ fn test_run_script() {
|
||||
assert!(r.is_ok());
|
||||
}
|
||||
|
||||
fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> Result<(), CompileError> {
|
||||
enum ShellExecResult {
|
||||
Ok,
|
||||
PyErr(PyObjectRef),
|
||||
Continue,
|
||||
}
|
||||
|
||||
fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> ShellExecResult {
|
||||
match vm.compile(source, compile::Mode::Single, "<stdin>".to_string()) {
|
||||
Ok(code) => {
|
||||
match vm.run_code_obj(code, scope.clone()) {
|
||||
Ok(value) => {
|
||||
// Save non-None values as "_"
|
||||
|
||||
use rustpython_vm::pyobject::IdProtocol;
|
||||
|
||||
if !value.is(&vm.get_none()) {
|
||||
if !vm.is_none(&value) {
|
||||
let key = "_";
|
||||
scope.globals.set_item(key, value, vm).unwrap();
|
||||
}
|
||||
ShellExecResult::Ok
|
||||
}
|
||||
|
||||
Err(err) => {
|
||||
print_exception(vm, &err);
|
||||
}
|
||||
Err(err) => ShellExecResult::PyErr(err),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// Don't inject syntax errors for line continuation
|
||||
Err(
|
||||
err @ CompileError {
|
||||
error: CompileErrorType::Parse(ParseErrorType::EOF),
|
||||
..
|
||||
},
|
||||
) => Err(err),
|
||||
Err(err) => {
|
||||
let exc = vm.new_syntax_error(&err);
|
||||
print_exception(vm, &exc);
|
||||
Err(err)
|
||||
}
|
||||
Err(CompileError {
|
||||
error: CompileErrorType::Parse(ParseErrorType::EOF),
|
||||
..
|
||||
}) => ShellExecResult::Continue,
|
||||
Err(err) => ShellExecResult::PyErr(vm.new_syntax_error(&err)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,12 +478,10 @@ fn get_history_path() -> PathBuf {
|
||||
xdg_dirs.place_cache_file("repl_history.txt").unwrap()
|
||||
}
|
||||
|
||||
fn get_prompt(vm: &VirtualMachine, prompt_name: &str) -> String {
|
||||
fn get_prompt(vm: &VirtualMachine, prompt_name: &str) -> Option<PyStringRef> {
|
||||
vm.get_attribute(vm.sys_module.clone(), prompt_name)
|
||||
.and_then(|prompt| vm.to_str(&prompt))
|
||||
.ok()
|
||||
.as_ref()
|
||||
.map(objstr::get_value)
|
||||
.unwrap_or_else(String::new)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
@@ -521,15 +511,27 @@ fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
|
||||
} else {
|
||||
get_prompt(vm, "ps1")
|
||||
};
|
||||
match repl.readline(&prompt) {
|
||||
let prompt = match prompt {
|
||||
Some(ref s) => s.as_str(),
|
||||
None => "",
|
||||
};
|
||||
let result = match repl.readline(prompt) {
|
||||
Ok(line) => {
|
||||
debug!("You entered {:?}", line);
|
||||
input.push_str(&line);
|
||||
input.push('\n');
|
||||
|
||||
repl.add_history_entry(line.trim_end());
|
||||
|
||||
let stop_continuing = line.is_empty();
|
||||
|
||||
if input.is_empty() {
|
||||
input = line;
|
||||
} else {
|
||||
input.push_str(&line);
|
||||
}
|
||||
input.push_str("\n");
|
||||
|
||||
if continuing {
|
||||
if line.is_empty() {
|
||||
if stop_continuing {
|
||||
continuing = false;
|
||||
} else {
|
||||
continue;
|
||||
@@ -537,32 +539,39 @@ fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
|
||||
}
|
||||
|
||||
match shell_exec(vm, &input, scope.clone()) {
|
||||
Err(CompileError {
|
||||
error: CompileErrorType::Parse(ParseErrorType::EOF),
|
||||
..
|
||||
}) => {
|
||||
continuing = true;
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
ShellExecResult::Ok => {
|
||||
input = String::new();
|
||||
Ok(())
|
||||
}
|
||||
ShellExecResult::Continue => {
|
||||
continuing = true;
|
||||
Ok(())
|
||||
}
|
||||
ShellExecResult::PyErr(err) => {
|
||||
input = String::new();
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ReadlineError::Interrupted) => {
|
||||
// TODO: Raise a real KeyboardInterrupt exception
|
||||
println!("^C");
|
||||
continuing = false;
|
||||
continue;
|
||||
let keyboard_interrupt = vm
|
||||
.new_empty_exception(vm.ctx.exceptions.keyboard_interrupt.clone())
|
||||
.unwrap();
|
||||
Err(keyboard_interrupt)
|
||||
}
|
||||
Err(ReadlineError::Eof) => {
|
||||
break;
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
eprintln!("Readline error: {:?}", err);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(exc) = result {
|
||||
print_exception(vm, &exc);
|
||||
}
|
||||
}
|
||||
repl.save_history(repl_history_path_str).unwrap();
|
||||
|
||||
@@ -574,22 +583,32 @@ fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
|
||||
use std::io::{self, BufRead, Write};
|
||||
|
||||
println!(
|
||||
"Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596}",
|
||||
"Welcome to the magnificent Rust Python {} interpreter!",
|
||||
crate_version!()
|
||||
);
|
||||
|
||||
let stdin = io::stdin();
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
fn print_prompt() {
|
||||
let prompt = get_prompt(vm, "ps1");
|
||||
let prompt = match prompt {
|
||||
Some(ref s) => s.as_str(),
|
||||
None => "",
|
||||
};
|
||||
print!("{}", prompt);
|
||||
io::stdout().lock().flush().expect("flush failed");
|
||||
}
|
||||
|
||||
print!("{}", get_prompt(vm, "ps1"));
|
||||
stdout.flush().expect("flush failed");
|
||||
let stdin = io::stdin();
|
||||
|
||||
print_prompt();
|
||||
for line in stdin.lock().lines() {
|
||||
let mut line = line.expect("line failed");
|
||||
line.push('\n');
|
||||
let _ = shell_exec(vm, &line, scope.clone());
|
||||
print!("{}", get_prompt(vm, "ps1"));
|
||||
stdout.flush().expect("flush failed");
|
||||
line.push_str("\n");
|
||||
match shell_exec(vm, &line, scope.clone()) {
|
||||
ShellExecResult::Ok => {}
|
||||
ShellExecResult::Continue => println!("Unexpected EOF"),
|
||||
ShellExecResult::PyErr(exc) => print_exception(vm, &exc),
|
||||
}
|
||||
print_prompt();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -15,8 +15,8 @@ fn exception_init(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let exc_args = vm.ctx.new_tuple(args.args[1..].to_vec());
|
||||
vm.set_attr(&exc_self, "args", exc_args)?;
|
||||
|
||||
let traceback = vm.ctx.new_list(Vec::new());
|
||||
vm.set_attr(&exc_self, "__traceback__", traceback)?;
|
||||
// TODO: have an actual `traceback` object for __traceback__
|
||||
vm.set_attr(&exc_self, "__traceback__", vm.ctx.new_list(vec![]))?;
|
||||
vm.set_attr(&exc_self, "__cause__", vm.get_none())?;
|
||||
vm.set_attr(&exc_self, "__context__", vm.get_none())?;
|
||||
vm.set_attr(&exc_self, "__suppress_context__", vm.new_bool(false))?;
|
||||
@@ -101,11 +101,13 @@ fn print_traceback_entry(vm: &VirtualMachine, tb_entry: &PyObjectRef) {
|
||||
/// Print exception with traceback
|
||||
pub fn print_exception_inner(vm: &VirtualMachine, exc: &PyObjectRef) {
|
||||
if let Ok(tb) = vm.get_attribute(exc.clone(), "__traceback__") {
|
||||
println!("Traceback (most recent call last):");
|
||||
if objtype::isinstance(&tb, &vm.ctx.list_type()) {
|
||||
let mut tb_entries = objsequence::get_elements_list(&tb).to_vec();
|
||||
tb_entries.reverse();
|
||||
|
||||
if !tb_entries.is_empty() {
|
||||
println!("Traceback (most recent call last):");
|
||||
}
|
||||
for exc_location in tb_entries.iter() {
|
||||
print_traceback_entry(vm, exc_location);
|
||||
}
|
||||
|
||||
+2
-3
@@ -167,9 +167,8 @@ impl Frame {
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn execute_instruction(&self, vm: &VirtualMachine) -> FrameResult {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
check_signals(vm);
|
||||
}
|
||||
check_signals(vm)?;
|
||||
|
||||
let instruction = self.fetch_instruction();
|
||||
|
||||
flame_guard!(format!("Frame::execute_instruction({:?})", instruction));
|
||||
|
||||
+90
-58
@@ -1,6 +1,6 @@
|
||||
use crate::obj::objint::PyIntRef;
|
||||
use crate::pyobject::{IdProtocol, PyObjectRef, PyResult};
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::pyobject::{PyObjectRef, PyResult, TryFromObject};
|
||||
use crate::vm::{VirtualMachine, NSIG};
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
@@ -23,51 +23,65 @@ const SIG_IGN: libc::sighandler_t = 1;
|
||||
#[cfg(windows)]
|
||||
const SIG_ERR: libc::sighandler_t = !0;
|
||||
|
||||
const NSIG: usize = 64;
|
||||
|
||||
// We cannot use the NSIG const in the arr macro. This will fail compilation if NSIG is different.
|
||||
static mut TRIGGERS: [AtomicBool; NSIG] = arr![AtomicBool::new(false); 64];
|
||||
static TRIGGERS: [AtomicBool; NSIG] = arr![AtomicBool::new(false); 64];
|
||||
|
||||
static ANY_TRIGGERED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
extern "C" fn run_signal(signum: i32) {
|
||||
unsafe {
|
||||
TRIGGERS[signum as usize].store(true, Ordering::Relaxed);
|
||||
ANY_TRIGGERED.store(true, Ordering::Relaxed);
|
||||
TRIGGERS[signum as usize].store(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn assert_in_range(signum: i32, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if (1..NSIG as i32).contains(&signum) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(vm.new_value_error("signal number out of range".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
fn signal(
|
||||
signalnum: PyIntRef,
|
||||
handler: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Option<PyObjectRef>> {
|
||||
if !vm.isinstance(&handler, &vm.ctx.function_type())?
|
||||
&& !vm.isinstance(&handler, &vm.ctx.bound_method_type())?
|
||||
&& !vm.isinstance(&handler, &vm.ctx.builtin_function_or_method_type())?
|
||||
{
|
||||
return Err(vm.new_type_error("Hanlder must be callable".to_string()));
|
||||
}
|
||||
let signal_module = vm.import("signal", &vm.ctx.new_tuple(vec![]), 0)?;
|
||||
let sig_dfl = vm.get_attribute(signal_module.clone(), "SIG_DFL")?;
|
||||
let sig_ign = vm.get_attribute(signal_module, "SIG_IGN")?;
|
||||
let signalnum = signalnum.as_bigint().to_i32().unwrap();
|
||||
check_signals(vm);
|
||||
let sig_handler = if handler.is(&sig_dfl) {
|
||||
SIG_DFL
|
||||
} else if handler.is(&sig_ign) {
|
||||
SIG_IGN
|
||||
} else {
|
||||
run_signal as libc::sighandler_t
|
||||
fn signal(signalnum: i32, handler: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
assert_in_range(signalnum, vm)?;
|
||||
|
||||
let sig_handler = match usize::try_from_object(vm, handler.clone()).ok() {
|
||||
Some(SIG_DFL) => SIG_DFL,
|
||||
Some(SIG_IGN) => SIG_IGN,
|
||||
None if vm.is_callable(&handler) => run_signal as libc::sighandler_t,
|
||||
_ => {
|
||||
return Err(vm.new_type_error(
|
||||
"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object"
|
||||
.to_owned(),
|
||||
))
|
||||
}
|
||||
};
|
||||
check_signals(vm)?;
|
||||
|
||||
let old = unsafe { libc::signal(signalnum, sig_handler) };
|
||||
if old == SIG_ERR {
|
||||
return Err(vm.new_os_error("Failed to set signal".to_string()));
|
||||
}
|
||||
let old_handler = vm.signal_handlers.borrow_mut().insert(signalnum, handler);
|
||||
#[cfg(unix)]
|
||||
{
|
||||
extern "C" {
|
||||
fn siginterrupt(sig: i32, flag: i32);
|
||||
}
|
||||
unsafe {
|
||||
siginterrupt(signalnum, 1);
|
||||
}
|
||||
}
|
||||
|
||||
let mut old_handler = handler;
|
||||
std::mem::swap(
|
||||
&mut vm.signal_handlers.borrow_mut()[signalnum as usize],
|
||||
&mut old_handler,
|
||||
);
|
||||
Ok(old_handler)
|
||||
}
|
||||
|
||||
fn getsignal(signalnum: PyIntRef, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
|
||||
let signalnum = signalnum.as_bigint().to_i32().unwrap();
|
||||
Ok(vm.signal_handlers.borrow_mut().get(&signalnum).cloned())
|
||||
fn getsignal(signalnum: i32, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
assert_in_range(signalnum, vm)?;
|
||||
Ok(vm.signal_handlers.borrow()[signalnum as usize].clone())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
@@ -81,50 +95,72 @@ fn alarm(time: PyIntRef, _vm: &VirtualMachine) -> u32 {
|
||||
prev_time.unwrap_or(0)
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
pub fn check_signals(vm: &VirtualMachine) {
|
||||
for signum in 1..NSIG {
|
||||
let triggerd = unsafe { TRIGGERS[signum].swap(false, Ordering::Relaxed) };
|
||||
#[cfg_attr(feature = "flame-it", flame)]
|
||||
pub fn check_signals(vm: &VirtualMachine) -> PyResult<()> {
|
||||
if !ANY_TRIGGERED.swap(false, Ordering::Relaxed) {
|
||||
return Ok(());
|
||||
}
|
||||
for (signum, trigger) in TRIGGERS.iter().enumerate().skip(1) {
|
||||
let triggerd = trigger.swap(false, Ordering::Relaxed);
|
||||
if triggerd {
|
||||
let handler = vm
|
||||
.signal_handlers
|
||||
.borrow()
|
||||
.get(&(signum as i32))
|
||||
.expect("Handler should be set")
|
||||
.clone();
|
||||
vm.invoke(&handler, vec![vm.new_int(signum), vm.get_none()])
|
||||
.expect("Test");
|
||||
let handler = &vm.signal_handlers.borrow()[signum];
|
||||
if vm.is_callable(handler) {
|
||||
vm.invoke(handler, vec![vm.new_int(signum), vm.get_none()])?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stub_func(_vm: &VirtualMachine) -> PyResult {
|
||||
panic!("Do not use directly");
|
||||
fn default_int_handler(_signum: PyObjectRef, _arg: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_empty_exception(vm.ctx.exceptions.keyboard_interrupt.clone())?)
|
||||
}
|
||||
|
||||
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
let sig_dfl = ctx.new_rustfunc(stub_func);
|
||||
let sig_ign = ctx.new_rustfunc(stub_func);
|
||||
let int_handler = ctx.new_rustfunc(default_int_handler);
|
||||
|
||||
let sig_dfl = ctx.new_int(SIG_DFL as u8);
|
||||
let sig_ign = ctx.new_int(SIG_IGN as u8);
|
||||
|
||||
let module = py_module!(vm, "signal", {
|
||||
"signal" => ctx.new_rustfunc(signal),
|
||||
"getsignal" => ctx.new_rustfunc(getsignal),
|
||||
"SIG_DFL" => sig_dfl,
|
||||
"SIG_IGN" => sig_ign,
|
||||
"SIG_DFL" => sig_dfl.clone(),
|
||||
"SIG_IGN" => sig_ign.clone(),
|
||||
"SIGABRT" => ctx.new_int(libc::SIGABRT as u8),
|
||||
"SIGFPE" => ctx.new_int(libc::SIGFPE as u8),
|
||||
"SIGILL" => ctx.new_int(libc::SIGILL as u8),
|
||||
"SIGINT" => ctx.new_int(libc::SIGINT as u8),
|
||||
"SIGSEGV" => ctx.new_int(libc::SIGSEGV as u8),
|
||||
"SIGTERM" => ctx.new_int(libc::SIGTERM as u8),
|
||||
"default_int_handler" => int_handler.clone(),
|
||||
});
|
||||
extend_module_platform_specific(vm, module)
|
||||
extend_module_platform_specific(vm, &module);
|
||||
|
||||
for signum in 1..NSIG {
|
||||
let handler = unsafe { libc::signal(signum as i32, SIG_IGN) };
|
||||
if handler != SIG_ERR {
|
||||
unsafe { libc::signal(signum as i32, handler) };
|
||||
}
|
||||
let py_handler = if handler == SIG_DFL {
|
||||
sig_dfl.clone()
|
||||
} else if handler == SIG_IGN {
|
||||
sig_ign.clone()
|
||||
} else {
|
||||
vm.get_none()
|
||||
};
|
||||
vm.signal_handlers.borrow_mut()[signum] = py_handler;
|
||||
}
|
||||
|
||||
signal(libc::SIGINT, int_handler, vm).expect("Failed to set sigint handler");
|
||||
|
||||
module
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) -> PyObjectRef {
|
||||
fn extend_module_platform_specific(vm: &VirtualMachine, module: &PyObjectRef) {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
extend_module!(vm, module, {
|
||||
@@ -161,11 +197,7 @@ fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) ->
|
||||
"SIGSTKFLT" => ctx.new_int(libc::SIGSTKFLT as u8),
|
||||
});
|
||||
}
|
||||
|
||||
module
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn extend_module_platform_specific(_vm: &VirtualMachine, module: PyObjectRef) -> PyObjectRef {
|
||||
module
|
||||
}
|
||||
fn extend_module_platform_specific(_vm: &VirtualMachine, _module: &PyObjectRef) {}
|
||||
@@ -3,10 +3,10 @@
|
||||
/// https://docs.python.org/3/library/time.html
|
||||
use std::fmt;
|
||||
use std::ops::Range;
|
||||
use std::thread;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use crate::function::{OptionalArg, PyFuncArgs};
|
||||
use crate::obj::objfloat::PyFloatRef;
|
||||
use crate::obj::objint::PyInt;
|
||||
use crate::obj::objsequence::get_sequence_index;
|
||||
use crate::obj::objsequence::PySliceableSequence;
|
||||
@@ -22,14 +22,35 @@ use num_traits::cast::ToPrimitive;
|
||||
use chrono::naive::NaiveDateTime;
|
||||
use chrono::{Datelike, Timelike};
|
||||
|
||||
fn time_sleep(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(seconds, Some(vm.ctx.float_type()))]);
|
||||
let seconds = objfloat::get_value(seconds);
|
||||
#[cfg(unix)]
|
||||
fn time_sleep(seconds: PyFloatRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
// this is basically std::thread::sleep, but that catches interrupts and we don't want to
|
||||
let seconds = seconds.to_f64();
|
||||
let secs = seconds.trunc() as u64;
|
||||
let nsecs = (seconds.fract() * 1e9) as i64;
|
||||
|
||||
let mut ts = libc::timespec {
|
||||
tv_sec: std::cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
|
||||
tv_nsec: nsecs,
|
||||
};
|
||||
let res = unsafe { libc::nanosleep(&ts, &mut ts) };
|
||||
let interrupted = res == -1 && nix::errno::errno() == libc::EINTR;
|
||||
|
||||
if interrupted {
|
||||
crate::stdlib::signal::check_signals(vm)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn time_sleep(seconds: PyFloatRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let seconds = seconds.to_f64();
|
||||
let secs: u64 = seconds.trunc() as u64;
|
||||
let nanos: u32 = (seconds.fract() * 1e9) as u32;
|
||||
let duration = Duration::new(secs, nanos);
|
||||
thread::sleep(duration);
|
||||
Ok(vm.get_none())
|
||||
std::thread::sleep(duration);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn duration_to_f64(d: Duration) -> f64 {
|
||||
|
||||
+11
-2
@@ -39,6 +39,7 @@ use crate::pyobject::{
|
||||
use crate::scope::Scope;
|
||||
use crate::stdlib;
|
||||
use crate::sysmodule;
|
||||
use arr_macro::arr;
|
||||
use num_bigint::BigInt;
|
||||
#[cfg(feature = "rustpython-compiler")]
|
||||
use rustpython_compiler::{compile, error::CompileError};
|
||||
@@ -62,10 +63,12 @@ pub struct VirtualMachine {
|
||||
pub profile_func: RefCell<PyObjectRef>,
|
||||
pub trace_func: RefCell<PyObjectRef>,
|
||||
pub use_tracing: RefCell<bool>,
|
||||
pub signal_handlers: RefCell<[PyObjectRef; NSIG]>,
|
||||
pub settings: PySettings,
|
||||
pub signal_handlers: RefCell<HashMap<i32, PyObjectRef>>,
|
||||
}
|
||||
|
||||
pub const NSIG: usize = 64;
|
||||
|
||||
/// Struct containing all kind of settings for the python vm.
|
||||
pub struct PySettings {
|
||||
/// -d command line switch
|
||||
@@ -166,6 +169,8 @@ impl VirtualMachine {
|
||||
let import_func = RefCell::new(ctx.none());
|
||||
let profile_func = RefCell::new(ctx.none());
|
||||
let trace_func = RefCell::new(ctx.none());
|
||||
let signal_handlers = RefCell::new(arr![ctx.none(); 64]);
|
||||
|
||||
let vm = VirtualMachine {
|
||||
builtins: builtins.clone(),
|
||||
sys_module: sysmod.clone(),
|
||||
@@ -179,8 +184,8 @@ impl VirtualMachine {
|
||||
profile_func,
|
||||
trace_func,
|
||||
use_tracing: RefCell::new(false),
|
||||
signal_handlers,
|
||||
settings,
|
||||
signal_handlers: Default::default(),
|
||||
};
|
||||
|
||||
objmodule::init_module_dict(
|
||||
@@ -198,6 +203,10 @@ impl VirtualMachine {
|
||||
|
||||
builtins::make_module(&vm, builtins.clone());
|
||||
sysmodule::make_module(&vm, sysmod, builtins);
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
import::import_builtin(&vm, "signal").expect("Couldn't initialize signal module");
|
||||
|
||||
vm
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user