mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Add built-in breakpoint function (#4122)
This commit is contained in:
1 parent
e34d8b184c
commit
e9970edd77
3 files changed
+80
-5
No files matched your search
Vendored
+4
-1
@@ -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):
|
||||
|
||||
@@ -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
@@ -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() {
|
||||
|
||||
Reference in new issue
Block a user