mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Fix excepthook (#5830)
This commit is contained in:
1 parent
638d2183dc
commit
9c2a4695c1
5 files changed
+50
-32
No files matched your search
Vendored
-6
@@ -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):
|
||||
|
||||
Vendored
-2
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
Generated
+25
-22
@@ -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
@@ -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__")]
|
||||
|
||||
Reference in new issue
Block a user