Skip to content

Commit

Permalink
pythongh-105751: test_ctypes gets Windows attrs from ctypes
Browse files Browse the repository at this point in the history
test_ctypes now gets attributes specific to Windows from the ctypes
module, rather than relying on "from ctypes import *".
  • Loading branch information
vstinner committed Jun 13, 2023
1 parent 4cefe3c commit 6453eec
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Lib/test/test_ctypes/test_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def EnumWindowsCallbackFunc(hwnd, lParam):
windowCount += 1
return True #Allow windows to keep enumerating

windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0)
ctypes.windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0)

def test_callback_register_int(self):
# Issue #8275: buggy handling of callback args under Win64
Expand Down
14 changes: 5 additions & 9 deletions Lib/test/test_ctypes/test_cfuncs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Byte order related?

import unittest
import ctypes
from ctypes import *
from test.test_ctypes import need_symbol

Expand Down Expand Up @@ -197,22 +198,17 @@ def test_void(self):

# The following repeats the above tests with stdcall functions (where
# they are available)
try:
WinDLL
except NameError:
def stdcall_dll(*_): pass
else:
class stdcall_dll(WinDLL):
if hasattr(ctypes, 'WinDLL'):
class stdcall_dll(ctypes.WinDLL):
def __getattr__(self, name):
if name[:2] == '__' and name[-2:] == '__':
raise AttributeError(name)
func = self._FuncPtr(("s_" + name, self))
setattr(self, name, func)
return func

@need_symbol('WinDLL')
class stdcallCFunctions(CFunctions):
_dll = stdcall_dll(_ctypes_test.__file__)
class stdcallCFunctions(CFunctions):
_dll = stdcall_dll(_ctypes_test.__file__)

if __name__ == '__main__':
unittest.main()
19 changes: 10 additions & 9 deletions Lib/test/test_ctypes/test_errno.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import unittest, os, errno
import threading

import ctypes
from ctypes import *
from ctypes.util import find_library

Expand Down Expand Up @@ -44,33 +45,33 @@ def _worker():

@unittest.skipUnless(os.name == "nt", 'Test specific to Windows')
def test_GetLastError(self):
dll = WinDLL("kernel32", use_last_error=True)
dll = ctypes.WinDLL("kernel32", use_last_error=True)
GetModuleHandle = dll.GetModuleHandleA
GetModuleHandle.argtypes = [c_wchar_p]

self.assertEqual(0, GetModuleHandle("foo"))
self.assertEqual(get_last_error(), 126)
self.assertEqual(ctypes.get_last_error(), 126)

self.assertEqual(set_last_error(32), 126)
self.assertEqual(get_last_error(), 32)
self.assertEqual(ctypes.set_last_error(32), 126)
self.assertEqual(ctypes.get_last_error(), 32)

def _worker():
set_last_error(0)
ctypes.set_last_error(0)

dll = WinDLL("kernel32", use_last_error=False)
dll = ctypes.WinDLL("kernel32", use_last_error=False)
GetModuleHandle = dll.GetModuleHandleW
GetModuleHandle.argtypes = [c_wchar_p]
GetModuleHandle("bar")

self.assertEqual(get_last_error(), 0)
self.assertEqual(ctypes.get_last_error(), 0)

t = threading.Thread(target=_worker)
t.start()
t.join()

self.assertEqual(get_last_error(), 32)
self.assertEqual(ctypes.get_last_error(), 32)

set_last_error(0)
ctypes.set_last_error(0)

if __name__ == "__main__":
unittest.main()
3 changes: 2 additions & 1 deletion Lib/test/test_ctypes/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Later...
"""

import ctypes
from ctypes import *
from test.test_ctypes import need_symbol
import sys, unittest
Expand All @@ -18,7 +19,7 @@
import _ctypes_test
dll = CDLL(_ctypes_test.__file__)
if sys.platform == "win32":
windll = WinDLL(_ctypes_test.__file__)
windll = ctypes.WinDLL(_ctypes_test.__file__)

class POINT(Structure):
_fields_ = [("x", c_int), ("y", c_int)]
Expand Down
26 changes: 14 additions & 12 deletions Lib/test/test_ctypes/test_loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,18 @@ def test_load_library(self):
print(find_library("user32"))

if os.name == "nt":
windll.kernel32.GetModuleHandleW
windll["kernel32"].GetModuleHandleW
windll.LoadLibrary("kernel32").GetModuleHandleW
WinDLL("kernel32").GetModuleHandleW
ctypes.windll.kernel32.GetModuleHandleW
ctypes.windll["kernel32"].GetModuleHandleW
ctypes.windll.LoadLibrary("kernel32").GetModuleHandleW
ctypes.WinDLL("kernel32").GetModuleHandleW
# embedded null character
self.assertRaises(ValueError, windll.LoadLibrary, "kernel32\0")
self.assertRaises(ValueError, ctypes.windll.LoadLibrary, "kernel32\0")

@unittest.skipUnless(os.name == "nt",
'test specific to Windows')
def test_load_ordinal_functions(self):
import _ctypes_test
dll = WinDLL(_ctypes_test.__file__)
dll = ctypes.WinDLL(_ctypes_test.__file__)
# We load the same function both via ordinal and name
func_ord = dll[2]
func_name = dll.GetString
Expand Down Expand Up @@ -114,14 +114,16 @@ def test_1703286_B(self):
# also has a high address. 'call_function' should accept
# addresses so large.
from _ctypes import call_function
advapi32 = windll.advapi32

advapi32 = ctypes.windll.advapi32
# Calling CloseEventLog with a NULL argument should fail,
# but the call should not segfault or so.
self.assertEqual(0, advapi32.CloseEventLog(None))
windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p
windll.kernel32.GetProcAddress.restype = c_void_p
proc = windll.kernel32.GetProcAddress(advapi32._handle,
b"CloseEventLog")

kernel32 = ctypes.windll.kernel32
kernel32.GetProcAddress.argtypes = c_void_p, c_char_p
kernel32.GetProcAddress.restype = c_void_p
proc = kernel32.GetProcAddress(advapi32._handle, b"CloseEventLog")
self.assertTrue(proc)
# This is the real test: call the function via 'call_function'
self.assertEqual(0, call_function(proc, (None,)))
Expand All @@ -130,7 +132,7 @@ def test_1703286_B(self):
'test specific to Windows')
def test_load_hasattr(self):
# bpo-34816: shouldn't raise OSError
self.assertFalse(hasattr(windll, 'test'))
self.assertFalse(hasattr(ctypes.windll, 'test'))

@unittest.skipUnless(os.name == "nt",
'test specific to Windows')
Expand Down
14 changes: 8 additions & 6 deletions Lib/test/test_ctypes/test_random_things.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ class call_function_TestCase(unittest.TestCase):

def test(self):
from _ctypes import call_function
windll.kernel32.LoadLibraryA.restype = c_void_p
windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p
windll.kernel32.GetProcAddress.restype = c_void_p

hdll = windll.kernel32.LoadLibraryA(b"kernel32")
funcaddr = windll.kernel32.GetProcAddress(hdll, b"GetModuleHandleA")
kernel32 = ctypes.windll.kernel32
kernel32.LoadLibraryA.restype = c_void_p
kernel32.GetProcAddress.argtypes = c_void_p, c_char_p
kernel32.GetProcAddress.restype = c_void_p

hdll = kernel32.LoadLibraryA(b"kernel32")
funcaddr = kernel32.GetProcAddress(hdll, b"GetModuleHandleA")

self.assertEqual(call_function(funcaddr, (None,)),
windll.kernel32.GetModuleHandleA(None))
kernel32.GetModuleHandleA(None))

class CallbackTracbackTestCase(unittest.TestCase):
# When an exception is raised in a ctypes callback function, the C
Expand Down
9 changes: 6 additions & 3 deletions Lib/test/test_ctypes/test_win32.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ class FunctionCallTestCase(unittest.TestCase):
def test_SEH(self):
# Disable faulthandler to prevent logging the warning:
# "Windows fatal exception: access violation"
kernel32 = ctypes.windll.kernel32
with support.disable_faulthandler():
# Call functions with invalid arguments, and make sure
# that access violations are trapped and raise an
# exception.
self.assertRaises(OSError, windll.kernel32.GetModuleHandleA, 32)
self.assertRaises(OSError, kernel32.GetModuleHandleA, 32)

def test_noargs(self):
# This is a special case on win32 x64
windll.user32.GetDesktopWindow()
user32 = ctypes.windll.user32
user32.GetDesktopWindow()


@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
Expand Down Expand Up @@ -81,7 +83,8 @@ def test_winerror(self):
self.assertEqual(e.errno, errno.EINVAL)
self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER)

windll.kernel32.SetLastError(ERROR_INVALID_PARAMETER)
kernel32 = ctypes.windll.kernel32
kernel32.SetLastError(ERROR_INVALID_PARAMETER)
try:
raise WinError()
except OSError as exc:
Expand Down

0 comments on commit 6453eec

Please sign in to comment.