Add built-in breakpoint function (#4122)

This commit is contained in:
Gyubong authored and GitHub committed 2022-08-23 21:45:01 +09:00
1 parent e34d8b184c
commit e9970edd77
3 files changed
+80 -5

No files matched your search

+4 -1
View File
@@ -1900,7 +1900,6 @@ class BuiltinTest(unittest.TestCase):
self.assertFalse(not NotImplemented)
@unittest.skip("TODO: RUSTPYTHON, AttributeError: module 'sys' has no attribute '__breakpointhook__'")
class TestBreakpoint(unittest.TestCase):
def setUp(self):
# These tests require a clean slate environment. For example, if the
@@ -2005,6 +2004,10 @@ class TestBreakpoint(unittest.TestCase):
breakpoint()
mock.assert_not_called()
def test_runtime_error_when_hook_is_lost(self):
del sys.breakpointhook
with self.assertRaises(RuntimeError):
breakpoint()
@unittest.skipUnless(pty, "the pty and signal modules must be available")
class PtyTests(unittest.TestCase):
+10 -3
View File
@@ -80,8 +80,6 @@ mod builtins {
}
}
// builtin_breakpoint
#[pyfunction]
fn callable(obj: PyObjectRef, vm: &VirtualMachine) -> bool {
vm.is_callable(&obj)
@@ -363,7 +361,16 @@ mod builtins {
obj.hash(vm)
}
// builtin_help
#[pyfunction]
fn breakpoint(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
match vm
.sys_module
.get_attr(vm.ctx.intern_str("breakpointhook"), vm)
{
Ok(hook) => vm.invoke(hook.as_ref(), args),
Err(_) => Err(vm.new_runtime_error("lost sys.breakpointhook".to_owned())),
}
}
#[pyfunction]
fn hex(number: PyIntRef) -> String {
+66 -1
View File
@@ -13,13 +13,18 @@ mod sys {
frame::FrameRef,
function::{FuncArgs, OptionalArg, PosArgs},
stdlib::builtins,
stdlib::warnings::warn,
types::PyStructSequence,
version,
vm::{Settings, VirtualMachine},
AsObject, PyObjectRef, PyRef, PyRefExact, PyResult,
};
use num_traits::ToPrimitive;
use std::{env, mem, path, sync::atomic::Ordering};
use std::{
env::{self, VarError},
mem, path,
sync::atomic::Ordering,
};
// not the same as CPython (e.g. rust's x86_x64-unknown-linux-gnu is just x86_64-linux-gnu)
// but hopefully that's just an implementation detail? TODO: copy CPython's multiarch exactly,
@@ -316,6 +321,66 @@ mod sys {
vm.write_exception(&mut crate::py_io::PyWriter(stderr, vm), &exc)
}
#[pyfunction(name = "__breakpointhook__")]
#[pyfunction]
pub fn breakpointhook(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
let envar = std::env::var("PYTHONBREAKPOINT")
.and_then(|envar| {
if envar.is_empty() {
Err(VarError::NotPresent)
} else {
Ok(envar)
}
})
.unwrap_or_else(|_| "pdb.set_trace".to_owned());
if envar.eq("0") {
return Ok(vm.ctx.none());
};
let print_unimportable_module_warn = || {
warn(
vm.ctx.exceptions.runtime_warning,
format!(
"Ignoring unimportable $PYTHONBREAKPOINT: \"{}\"",
envar.to_owned(),
),
0,
vm,
)
.unwrap();
Ok(vm.ctx.none())
};
let last = match envar.split('.').last() {
Some(last) => last,
None => {
return print_unimportable_module_warn();
}
};
let (modulepath, attrname) = if last.eq(&envar) {
("builtins".to_owned(), envar.to_owned())
} else {
(
envar[..(envar.len() - last.len() - 1)].to_owned(),
last.to_owned(),
)
};
let module = match vm.import(modulepath, None, 0) {
Ok(module) => module,
Err(_) => {
return print_unimportable_module_warn();
}
};
match vm.get_attribute_opt(module, attrname) {
Ok(Some(hook)) => vm.invoke(hook.as_ref(), args),
_ => print_unimportable_module_warn(),
}
}
#[pyfunction]
fn exc_info(vm: &VirtualMachine) -> (PyObjectRef, PyObjectRef, PyObjectRef) {
match vm.topmost_exception() {