diff --git a/Lib/test/test_exception_hierarchy.py b/Lib/test/test_exception_hierarchy.py index e2f2844512a..e8c1c7fd1e7 100644 --- a/Lib/test/test_exception_hierarchy.py +++ b/Lib/test/test_exception_hierarchy.py @@ -136,8 +136,6 @@ def test_posix_error(self): if os.name == "nt": self.assertEqual(e.winerror, None) - # TODO: RUSTPYTHON - @unittest.expectedFailure @unittest.skipUnless(os.name == "nt", "Windows-specific test") def test_errno_translation(self): # ERROR_ALREADY_EXISTS (183) -> EEXIST diff --git a/crates/vm/src/exceptions.rs b/crates/vm/src/exceptions.rs index a8b55ae8a4d..1916972a799 100644 --- a/crates/vm/src/exceptions.rs +++ b/crates/vm/src/exceptions.rs @@ -1501,6 +1501,14 @@ pub(super) mod types { #[cfg(windows)] if let Some(winerror) = new_args.args.get(3) { zelf.set_attr("winerror", winerror.clone(), vm)?; + // Convert winerror to errno and replace args[0] (CPython behavior) + if let Some(winerror_int) = winerror + .downcast_ref::() + .and_then(|w| w.try_to_primitive::(vm).ok()) + { + let errno = crate::common::os::winerror_to_errno(winerror_int); + new_args.args[0] = vm.new_pyobj(errno); + } } if let Some(filename2) = new_args.args.get(4) { zelf.set_attr("filename2", filename2.clone(), vm)?; @@ -1521,19 +1529,29 @@ pub(super) mod types { let errno = exc.get_arg(0).unwrap().str(vm)?; let msg = exc.get_arg(1).unwrap().str(vm)?; + // On Windows, use [WinError X] format when winerror is set + #[cfg(windows)] + let (label, code) = match obj.get_attr("winerror", vm) { + Ok(winerror) if !vm.is_none(&winerror) => ("WinError", winerror.str(vm)?), + _ => ("Errno", errno.clone()), + }; + #[cfg(not(windows))] + let (label, code) = ("Errno", errno.clone()); + let s = match obj.get_attr("filename", vm) { Ok(filename) if !vm.is_none(&filename) => match obj.get_attr("filename2", vm) { Ok(filename2) if !vm.is_none(&filename2) => format!( - "[Errno {}] {}: '{}' -> '{}'", - errno, + "[{} {}] {}: '{}' -> '{}'", + label, + code, msg, filename.str(vm)?, filename2.str(vm)? ), - _ => format!("[Errno {}] {}: '{}'", errno, msg, filename.str(vm)?), + _ => format!("[{} {}] {}: '{}'", label, code, msg, filename.str(vm)?), }, _ => { - format!("[Errno {errno}] {msg}") + format!("[{label} {code}] {msg}") } }; vm.ctx.new_str(s) diff --git a/crates/vm/src/stdlib/builtins.rs b/crates/vm/src/stdlib/builtins.rs index d115c027955..fb665dbdefb 100644 --- a/crates/vm/src/stdlib/builtins.rs +++ b/crates/vm/src/stdlib/builtins.rs @@ -1187,4 +1187,10 @@ pub fn init_module(vm: &VirtualMachine, module: &Py) { extend_module!(vm, module, { "JitError" => ctx.exceptions.jit_error.to_owned(), }); + + #[cfg(windows)] + extend_module!(vm, module, { + // OSError alias for Windows + "WindowsError" => ctx.exceptions.os_error.to_owned(), + }); }