diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 2991e3c626..b6e85b9540 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -96,7 +96,7 @@ Run `./whats_left.py` to get a list of unimplemented methods, which is helpful w ### Rust Code - Follow the default rustfmt code style (`cargo fmt` to format) -- Use clippy to lint code (`cargo clippy`) +- **IMPORTANT**: Always run clippy to lint code (`cargo clippy`) before completing tasks. Fix any warnings or lints that are introduced by your changes - Follow Rust best practices for error handling and memory management - Use the macro system (`pyclass`, `pymodule`, `pyfunction`, etc.) when implementing Python functionality in Rust diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index b3f5e0650d..fec040716b 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -425,8 +425,6 @@ def test_windows_message(self): with self.assertRaisesRegex(OSError, 'Windows Error 0x%x' % code): ctypes.pythonapi.PyErr_SetFromWindowsErr(code) - # TODO: RUSTPYTHON - @unittest.expectedFailure def testAttributes(self): # test that exception attributes are happy @@ -2351,8 +2349,6 @@ def __getattribute__(self, attr): class ImportErrorTests(unittest.TestCase): - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_attributes(self): # Setting 'name' and 'path' should not be a problem. exc = ImportError('test') @@ -2387,8 +2383,6 @@ def test_attributes(self): with self.assertRaisesRegex(TypeError, msg): ImportError('test', invalid='keyword', another=True) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_reset_attributes(self): exc = ImportError('test', name='name', path='path') self.assertEqual(exc.args, ('test',)) @@ -2567,8 +2561,6 @@ def test_non_utf8(self): finally: unlink(TESTFN) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_attributes_new_constructor(self): args = ("bad.py", 1, 2, "abcdefg", 1, 100) the_exception = SyntaxError("bad bad", args) @@ -2581,8 +2573,6 @@ def test_attributes_new_constructor(self): self.assertEqual(error, the_exception.text) self.assertEqual("bad bad", the_exception.msg) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_attributes_old_constructor(self): args = ("bad.py", 1, 2, "abcdefg") the_exception = SyntaxError("bad bad", args) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 28a8697235..30a13587a2 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -93,8 +93,6 @@ def test_caret(self): self.assertEqual(err[1].find("("), err[2].find("^")) # in the right place self.assertEqual(err[2].count("^"), 1) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_nocaret(self): exc = SyntaxError("error", ("x.py", 23, None, "bad syntax")) err = traceback.format_exception_only(SyntaxError, exc) @@ -748,8 +746,6 @@ def outer_raise(): self.assertIn('inner_raise() # Marker', blocks[2]) self.check_zero_div(blocks[2]) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_syntax_error_offset_at_eol(self): # See #10186. def e(): @@ -808,8 +804,6 @@ def __str__(self): exp = f'.{X.__qualname__}: I am X\n' self.assertEqual(exp, err) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_syntax_error_various_offsets(self): for offset in range(-5, 10): for add in [0, 2]: diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index e28121f94b..3c822c430c 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -1308,17 +1308,21 @@ pub(super) mod types { args: ::rustpython_vm::function::FuncArgs, vm: &::rustpython_vm::VirtualMachine, ) -> ::rustpython_vm::PyResult<()> { - zelf.set_attr( - "name", - vm.unwrap_or_none(args.kwargs.get("name").cloned()), - vm, - )?; - zelf.set_attr( - "path", - vm.unwrap_or_none(args.kwargs.get("path").cloned()), - vm, - )?; - Ok(()) + let mut kwargs = args.kwargs.clone(); + let name = kwargs.swap_remove("name"); + let path = kwargs.swap_remove("path"); + + // Check for any remaining invalid keyword arguments + if let Some(invalid_key) = kwargs.keys().next() { + return Err(vm.new_type_error(format!( + "'{}' is an invalid keyword argument for ImportError", + invalid_key + ))); + } + + zelf.set_attr("name", vm.unwrap_or_none(name), vm)?; + zelf.set_attr("path", vm.unwrap_or_none(path), vm)?; + PyBaseException::slot_init(zelf, args, vm) } #[pymethod(magic)] fn reduce(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyTupleRef { @@ -1602,6 +1606,44 @@ pub(super) mod types { #[pyexception] impl PySyntaxError { + #[pyslot] + #[pymethod(name = "__init__")] + fn slot_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { + let len = args.args.len(); + let new_args = args; + + zelf.set_attr("print_file_and_line", vm.ctx.none(), vm)?; + + if len == 2 { + if let Ok(location_tuple) = new_args.args[1] + .clone() + .downcast::() + { + #[allow(clippy::len_zero)] + if location_tuple.len() >= 1 { + zelf.set_attr("filename", location_tuple.fast_getitem(0).clone(), vm)?; + } + if location_tuple.len() >= 2 { + zelf.set_attr("lineno", location_tuple.fast_getitem(1).clone(), vm)?; + } + if location_tuple.len() >= 3 { + zelf.set_attr("offset", location_tuple.fast_getitem(2).clone(), vm)?; + } + if location_tuple.len() >= 4 { + zelf.set_attr("text", location_tuple.fast_getitem(3).clone(), vm)?; + } + if location_tuple.len() >= 5 { + zelf.set_attr("end_lineno", location_tuple.fast_getitem(4).clone(), vm)?; + } + if location_tuple.len() >= 6 { + zelf.set_attr("end_offset", location_tuple.fast_getitem(5).clone(), vm)?; + } + } + } + + PyBaseException::slot_init(zelf, new_args, vm) + } + #[pymethod(magic)] fn str(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyStrRef { fn basename(filename: &str) -> &str { @@ -1712,7 +1754,8 @@ pub(super) mod types { type Args = (PyStrRef, ArgBytesLike, isize, isize, PyStrRef); let (encoding, object, start, end, reason): Args = args.bind(vm)?; zelf.set_attr("encoding", encoding, vm)?; - zelf.set_attr("object", object, vm)?; + let object_as_bytes = vm.ctx.new_bytes(object.borrow_buf().to_vec()); + zelf.set_attr("object", object_as_bytes, vm)?; zelf.set_attr("start", vm.ctx.new_int(start), vm)?; zelf.set_attr("end", vm.ctx.new_int(end), vm)?; zelf.set_attr("reason", reason, vm)?; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy