diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 1225db997e3..6316f937e21 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -374,7 +374,6 @@ def test_enable_single_thread(self): 'Segmentation fault', all_threads=False) - @unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; AttributeError: module 'msvcrt' has no attribute 'GetErrorMode'") @skip_segfault_on_android def test_disable(self): code = """ diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 1fe2aef39de..91bc986aab5 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -739,7 +739,6 @@ def test_copytree_dirs_exist_ok(self): with self.assertRaises(FileExistsError): shutil.copytree(src_dir, dst_dir, dirs_exist_ok=False) - @unittest.expectedFailureIfWindows("TODO: RUSTPYTHON") @os_helper.skip_unless_symlink def test_copytree_symlinks(self): tmp_dir = self.mkdtemp() @@ -1007,7 +1006,6 @@ def test_copytree_dangling_symlinks(self): shutil.copytree(src_dir, dst_dir, symlinks=True) self.assertIn('test.txt', os.listdir(dst_dir)) - @unittest.expectedFailureIfWindows("TODO: RUSTPYTHON") @os_helper.skip_unless_symlink def test_copytree_symlink_dir(self): src_dir = self.mkdtemp() diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 5a75971be65..e2aabf3dcf1 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1337,7 +1337,6 @@ def _test_bufsize_equal_one(self, line, expected, universal_newlines): self.assertEqual(p.returncode, 0) self.assertEqual(read_line, expected) - @unittest.expectedFailureIfWindows("TODO: RUSTPYTHON") def test_bufsize_equal_one_text_mode(self): # line is flushed in text mode with bufsize=1. # we should get the full line in return diff --git a/crates/vm/src/stdlib/msvcrt.rs b/crates/vm/src/stdlib/msvcrt.rs index 3eff6849e4c..aee36adcf22 100644 --- a/crates/vm/src/stdlib/msvcrt.rs +++ b/crates/vm/src/stdlib/msvcrt.rs @@ -109,6 +109,12 @@ mod msvcrt { .map_err(|e| e.into_pyexception(vm)) } + #[allow(non_snake_case)] + #[pyfunction] + fn GetErrorMode() -> u32 { + unsafe { suppress_iph!(Debug::GetErrorMode()) } + } + #[allow(non_snake_case)] #[pyfunction] fn SetErrorMode(mode: Debug::THREAD_ERROR_MODE, _: &VirtualMachine) -> u32 { diff --git a/crates/vm/src/stdlib/stat.rs b/crates/vm/src/stdlib/stat.rs index f7b3abb4325..90f045fcaf0 100644 --- a/crates/vm/src/stdlib/stat.rs +++ b/crates/vm/src/stdlib/stat.rs @@ -237,6 +237,17 @@ mod stat { FILE_ATTRIBUTE_TEMPORARY, FILE_ATTRIBUTE_VIRTUAL, }; + // Windows reparse point tags + #[cfg(windows)] + #[pyattr] + pub const IO_REPARSE_TAG_SYMLINK: u32 = 0xA000000C; + #[cfg(windows)] + #[pyattr] + pub const IO_REPARSE_TAG_MOUNT_POINT: u32 = 0xA0000003; + #[cfg(windows)] + #[pyattr] + pub const IO_REPARSE_TAG_APPEXECLINK: u32 = 0x8000001B; + // Unix file flags (if on Unix) #[pyattr] diff --git a/crates/vm/src/stdlib/winapi.rs b/crates/vm/src/stdlib/winapi.rs index 10a14acbc95..58bfdf61d4f 100644 --- a/crates/vm/src/stdlib/winapi.rs +++ b/crates/vm/src/stdlib/winapi.rs @@ -19,7 +19,7 @@ mod _winapi { Win32::Foundation::{HANDLE, HINSTANCE, MAX_PATH}, core::PCWSTR, }; - use windows_sys::Win32::Foundation::{BOOL, HANDLE as RAW_HANDLE}; + use windows_sys::Win32::Foundation::{BOOL, INVALID_HANDLE_VALUE}; #[pyattr] use windows_sys::Win32::{ @@ -87,8 +87,18 @@ mod _winapi { #[pyfunction] fn GetStdHandle( std_handle: windows_sys::Win32::System::Console::STD_HANDLE, - ) -> WindowsSysResult { - WindowsSysResult(unsafe { windows_sys::Win32::System::Console::GetStdHandle(std_handle) }) + vm: &VirtualMachine, + ) -> PyResult> { + let handle = unsafe { windows_sys::Win32::System::Console::GetStdHandle(std_handle) }; + if handle == INVALID_HANDLE_VALUE { + return Err(errno_err(vm)); + } + Ok(if handle.is_null() { + // NULL handle - return None + None + } else { + Some(HANDLE(handle as isize)) + }) } #[pyfunction] @@ -114,7 +124,8 @@ mod _winapi { #[pyfunction] fn DuplicateHandle( - (src_process, src): (HANDLE, HANDLE), + src_process: HANDLE, + src: HANDLE, target_process: HANDLE, access: u32, inherit: BOOL, @@ -294,6 +305,11 @@ mod _winapi { } } + #[pyfunction] + fn ExitProcess(exit_code: u32) { + unsafe { windows_sys::Win32::System::Threading::ExitProcess(exit_code) } + } + #[pyfunction] fn NeedCurrentDirectoryForExePath(exe_name: PyStrRef) -> bool { let exe_name = exe_name.as_str().to_wide_with_nul();