Skip to content

Commit e6200f0

Browse files
committed
Fix os_helper.subst_drive()
Reuse os_helper.handle_count() in test_os.test_windows.
1 parent 37c29f3 commit e6200f0

2 files changed

Lines changed: 35 additions & 45 deletions

File tree

Lib/test/support/os_helper.py

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -797,51 +797,61 @@ def __exit__(self, *ignore_exc):
797797

798798
try:
799799
if support.MS_WINDOWS:
800-
import ctypes
800+
import ctypes.util
801801
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
802-
803-
ERROR_FILE_NOT_FOUND = 2
804-
DDD_REMOVE_DEFINITION = 2
805-
DDD_EXACT_MATCH_ON_REMOVE = 4
806-
DDD_NO_BROADCAST_SYSTEM = 8
807802
else:
808803
raise AttributeError
809804
except (ImportError, AttributeError):
810805
def subst_drive(path):
811806
raise unittest.SkipTest('ctypes or kernel32 is not available')
807+
808+
def handle_count():
809+
return 0
812810
else:
811+
ERROR_FILE_NOT_FOUND = 2
812+
DDD_REMOVE_DEFINITION = 2
813+
DDD_EXACT_MATCH_ON_REMOVE = 4
814+
DDD_NO_BROADCAST_SYSTEM = 8
815+
816+
817+
@ctypes.util.wrap_dll_function(kernel32)
818+
def DefineDosDeviceW(
819+
dwFlags: ctypes.wintypes.DWORD,
820+
lpDeviceName: ctypes.c_wchar_p,
821+
lpTargetPath: ctypes.c_wchar_p,
822+
) -> ctypes.wintypes.BOOL:
823+
pass
824+
825+
@ctypes.util.wrap_dll_function(kernel32)
826+
def QueryDosDeviceW(
827+
lpDeviceName: ctypes.c_wchar_p,
828+
lpTargetPath: ctypes.c_wchar_p,
829+
ucchMax: ctypes.wintypes.DWORD,
830+
) -> ctypes.wintypes.DWORD:
831+
pass
832+
813833
@contextlib.contextmanager
814834
def subst_drive(path):
815835
"""Temporarily yield a substitute drive for a given path."""
816836
for c in reversed(string.ascii_uppercase):
817837
drive = f'{c}:'
818-
if (not kernel32.QueryDosDeviceW(drive, None, 0) and
838+
if (not QueryDosDeviceW(drive, None, 0) and
819839
ctypes.get_last_error() == ERROR_FILE_NOT_FOUND):
820840
break
821841
else:
822842
raise unittest.SkipTest('no available logical drive')
823-
if not kernel32.DefineDosDeviceW(
824-
DDD_NO_BROADCAST_SYSTEM, drive, path):
843+
844+
if not DefineDosDeviceW(DDD_NO_BROADCAST_SYSTEM, drive, path):
825845
raise ctypes.WinError(ctypes.get_last_error())
846+
826847
try:
827848
yield drive
828849
finally:
829-
if not kernel32.DefineDosDeviceW(
830-
DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
831-
drive, path):
850+
flags = DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE
851+
if not DefineDosDeviceW(flags, drive, path):
832852
raise ctypes.WinError(ctypes.get_last_error())
833853

834854

835-
try:
836-
if support.MS_WINDOWS:
837-
import ctypes.util
838-
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
839-
else:
840-
raise AttributeError
841-
except (ImportError, AttributeError):
842-
def handle_count():
843-
return 0
844-
else:
845855
@ctypes.util.wrap_dll_function(kernel32)
846856
def GetCurrentProcess() -> ctypes.wintypes.HANDLE:
847857
pass
@@ -859,6 +869,6 @@ def handle_count():
859869

860870
handle_count = ctypes.wintypes.DWORD()
861871
if not GetProcessHandleCount(hproc, ctypes.byref(handle_count)):
862-
raise ctypes.WinError()
872+
raise ctypes.WinError(ctypes.get_last_error())
863873

864874
return handle_count.value

Lib/test/test_os/test_windows.py

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -453,25 +453,8 @@ def test_unlink_removes_junction(self):
453453
class Win32NtTests(unittest.TestCase):
454454
def test_getfinalpathname_handles(self):
455455
nt = import_helper.import_module('nt')
456-
ctypes = import_helper.import_module('ctypes')
457-
# Ruff false positive -- it thinks we're redefining `ctypes` here
458-
import ctypes.wintypes # noqa: F811
459456

460-
kernel = ctypes.WinDLL('Kernel32.dll', use_last_error=True)
461-
kernel.GetCurrentProcess.restype = ctypes.wintypes.HANDLE
462-
463-
kernel.GetProcessHandleCount.restype = ctypes.wintypes.BOOL
464-
kernel.GetProcessHandleCount.argtypes = (ctypes.wintypes.HANDLE,
465-
ctypes.wintypes.LPDWORD)
466-
467-
# This is a pseudo-handle that doesn't need to be closed
468-
hproc = kernel.GetCurrentProcess()
469-
470-
handle_count = ctypes.wintypes.DWORD()
471-
ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count))
472-
self.assertEqual(1, ok)
473-
474-
before_count = handle_count.value
457+
before_count = os_helper.handle_count()
475458

476459
# The first two test the error path, __file__ tests the success path
477460
filenames = [
@@ -493,10 +476,7 @@ def test_getfinalpathname_handles(self):
493476
except Exception:
494477
pass
495478

496-
ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count))
497-
self.assertEqual(1, ok)
498-
499-
handle_delta = handle_count.value - before_count
479+
handle_delta = os_helper.handle_count() - before_count
500480

501481
self.assertEqual(0, handle_delta)
502482

0 commit comments

Comments
 (0)