Fix excepthook (#5830)

This commit is contained in:
Jeong, YunWon authored and GitHub committed 2025-06-24 16:58:27 +09:00
1 parent 638d2183dc
commit 9c2a4695c1
5 files changed
+50 -32

No files matched your search

-6
View File
@@ -701,8 +701,6 @@ class ExceptionTests(unittest.TestCase):
self.assertTrue(str(Exception('a')))
self.assertTrue(str(Exception('a', 'b')))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_exception_cleanup_names(self):
# Make sure the local variable bound to the exception instance by
# an "except" statement is only visible inside the except block.
@@ -725,8 +723,6 @@ class ExceptionTests(unittest.TestCase):
with self.assertRaises(UnboundLocalError):
e
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testExceptionCleanupState(self):
# Make sure exception state is cleaned up as soon as the except
# block is left. See #2507
@@ -1573,8 +1569,6 @@ class ExceptionTests(unittest.TestCase):
gc_collect() # For PyPy or other GCs.
self.assertEqual(wr(), None)
# TODO: RUSTPYTHON
@unittest.expectedFailure
@no_tracing
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON Windows')
def test_recursion_error_cleanup(self):
-2
View File
@@ -167,8 +167,6 @@ class ExceptHookTest(unittest.TestCase):
self.assertIn(""" text\n""", err)
self.assertTrue(err.endswith("SyntaxError: msg\n"))
# TODO: RUSTPYTHON, print argument error to stderr in sys.excepthook instead of throwing
@unittest.expectedFailure
def test_excepthook(self):
with test.support.captured_output("stderr") as stderr:
sys.excepthook(1, '1', 1)
+8
View File
@@ -1317,6 +1317,14 @@ impl Compiler<'_> {
self.compile_statements(body)?;
emit!(self, Instruction::PopException);
// Delete the exception variable if it was bound
if let Some(alias) = name {
// Set the variable to None before deleting (as CPython does)
self.emit_load_const(ConstantData::None);
self.store_name(alias.as_str())?;
self.compile_name(alias.as_str(), NameUsage::Delete)?;
}
if !finalbody.is_empty() {
emit!(self, Instruction::PopBlock); // pop excepthandler block
// We enter the finally block, without exception.
@@ -11,7 +11,7 @@ expression: "compile_exec(\"\\\nfor stop_exc in (StopIteration('spam'), StopAsyn
6 CallFunctionPositional(1)
7 BuildTuple (2)
8 GetIter
>> 9 ForIter (68)
>> 9 ForIter (71)
10 StoreLocal (2, stop_exc)
2 11 LoadNameAny (3, self)
@@ -21,7 +21,7 @@ expression: "compile_exec(\"\\\nfor stop_exc in (StopIteration('spam'), StopAsyn
15 CallFunctionPositional(1)
16 LoadConst (("type"))
17 CallMethodKeyword (1)
18 SetupWith (65)
18 SetupWith (68)
19 Pop
3 20 SetupExcept (40)
@@ -46,12 +46,12 @@ expression: "compile_exec(\"\\\nfor stop_exc in (StopIteration('spam'), StopAsyn
36 YieldFrom
37 WithCleanupFinish
38 PopBlock
39 Jump (54)
39 Jump (57)
>> 40 Duplicate
6 41 LoadNameAny (7, Exception)
42 TestOperation (ExceptionMatch)
43 JumpIfFalse (53)
43 JumpIfFalse (56)
44 StoreLocal (8, ex)
7 45 LoadNameAny (3, self)
@@ -61,23 +61,26 @@ expression: "compile_exec(\"\\\nfor stop_exc in (StopIteration('spam'), StopAsyn
49 CallMethodPositional (2)
50 Pop
51 PopException
52 Jump (63)
>> 53 Raise (Reraise)
52 LoadConst (None)
53 StoreLocal (8, ex)
54 DeleteLocal (8, ex)
55 Jump (66)
>> 56 Raise (Reraise)
9 >> 54 LoadNameAny (3, self)
55 LoadMethod (10, fail)
56 LoadConst ("")
57 LoadNameAny (2, stop_exc)
58 FormatValue (None)
59 LoadConst (" was suppressed")
60 BuildString (2)
61 CallMethodPositional (1)
62 Pop
9 >> 57 LoadNameAny (3, self)
58 LoadMethod (10, fail)
59 LoadConst ("")
60 LoadNameAny (2, stop_exc)
61 FormatValue (None)
62 LoadConst (" was suppressed")
63 BuildString (2)
64 CallMethodPositional (1)
65 Pop
2 >> 63 PopBlock
64 EnterFinally
>> 65 WithCleanupStart
66 WithCleanupFinish
67 Jump (9)
>> 68 PopBlock
69 ReturnConst (None)
2 >> 66 PopBlock
67 EnterFinally
>> 68 WithCleanupStart
69 WithCleanupFinish
70 Jump (9)
>> 71 PopBlock
72 ReturnConst (None)
+17 -2
View File
@@ -363,9 +363,24 @@ mod sys {
exc_tb: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()> {
let exc = vm.normalize_exception(exc_type, exc_val, exc_tb)?;
let stderr = super::get_stderr(vm)?;
vm.write_exception(&mut crate::py_io::PyWriter(stderr, vm), &exc)
// Try to normalize the exception. If it fails, print error to stderr like CPython
match vm.normalize_exception(exc_type.clone(), exc_val.clone(), exc_tb) {
Ok(exc) => vm.write_exception(&mut crate::py_io::PyWriter(stderr, vm), &exc),
Err(_) => {
// CPython prints error message to stderr instead of raising exception
let type_name = exc_val.class().name();
// TODO: fix error message
let msg = format!(
"TypeError: print_exception(): Exception expected for value, {} found\n",
type_name
);
use crate::py_io::Write;
write!(&mut crate::py_io::PyWriter(stderr, vm), "{}", msg)?;
Ok(())
}
}
}
#[pyfunction(name = "__breakpointhook__")]