diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index dc2df795a7d..b7e995334fe 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -6747,8 +6747,6 @@ def test_ambiguous_option(self): "ambiguous option: --foob=1 could match --foobaz, --fooble$", self.parser.parse_args, ['--foob=1', '--foogle', '2']) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_os_error(self): self.parser.add_argument('file') self.assertRaisesRegex(argparse.ArgumentError, diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py index 6d10099c614..54302eba4df 100644 --- a/Lib/test/test_py_compile.py +++ b/Lib/test/test_py_compile.py @@ -266,7 +266,6 @@ def test_bad_syntax_with_quiet(self): self.assertEqual(stdout, b'') self.assertEqual(stderr, b'') - @unittest.expectedFailureIfWindows("TODO: RUSTPYTHON") def test_file_not_exists(self): should_not_exists = os.path.join(os.path.dirname(__file__), 'should_not_exists.py') rc, stdout, stderr = self.pycompilecmd_failure(self.source_path, should_not_exists) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index bf0099554b5..6b20a5c00a5 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1878,8 +1878,6 @@ def _get_chdir_exception(self): self._nonexistent_dir) return desired_exception - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_exception_cwd(self): """Test error in the child raised in the parent for a bad cwd.""" desired_exception = self._get_chdir_exception() @@ -1895,8 +1893,6 @@ def test_exception_cwd(self): else: self.fail("Expected OSError: %s" % desired_exception) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_exception_bad_executable(self): """Test error in the child raised in the parent for a bad executable.""" desired_exception = self._get_chdir_exception() @@ -1912,8 +1908,6 @@ def test_exception_bad_executable(self): else: self.fail("Expected OSError: %s" % desired_exception) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_exception_bad_args_0(self): """Test error in the child raised in the parent for a bad args[0].""" desired_exception = self._get_chdir_exception() diff --git a/crates/vm/src/stdlib/io.rs b/crates/vm/src/stdlib/io.rs index c54f3b853dc..e5a438b86de 100644 --- a/crates/vm/src/stdlib/io.rs +++ b/crates/vm/src/stdlib/io.rs @@ -20,10 +20,41 @@ pub use _io::{OpenArgs, io_open as open}; impl ToPyException for std::io::Error { fn to_pyexception(&self, vm: &VirtualMachine) -> PyBaseExceptionRef { let errno = self.posix_errno(); + #[cfg(windows)] + let msg = 'msg: { + // On Windows, use C runtime's strerror for POSIX errno values + // For Windows-specific error codes, fall back to FormatMessage + + // UCRT's strerror returns "Unknown error" for invalid errno values + // Windows UCRT defines errno values 1-42 plus some more up to ~127 + const MAX_POSIX_ERRNO: i32 = 127; + if errno > 0 && errno <= MAX_POSIX_ERRNO { + let ptr = unsafe { libc::strerror(errno) }; + if !ptr.is_null() { + let s = unsafe { std::ffi::CStr::from_ptr(ptr) }.to_string_lossy(); + if !s.starts_with("Unknown error") { + break 'msg s.into_owned(); + } + } + } + self.to_string() + }; + #[cfg(unix)] + let msg = { + let ptr = unsafe { libc::strerror(errno) }; + if !ptr.is_null() { + unsafe { std::ffi::CStr::from_ptr(ptr) } + .to_string_lossy() + .into_owned() + } else { + self.to_string() + } + }; + #[cfg(not(any(windows, unix)))] let msg = self.to_string(); + #[allow(clippy::let_and_return)] let exc = vm.new_errno_error(errno, msg); - #[cfg(windows)] { use crate::object::AsObject;