From ac7b551bde7a362bc77d2cb84accf755ac30eb09 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 14 Jun 2023 04:46:47 +0200 Subject: [PATCH] gh-105751: test_ctypes gets Windows attrs from ctypes (#105758) test_ctypes now gets attributes specific to Windows from the ctypes module, rather than relying on "from ctypes import *". Attributes: * ctypes.FormatError * ctypes.WINFUNCTYPE * ctypes.WinError * ctypes.WinDLL * ctypes.windll * ctypes.oledll * ctypes.get_last_error() * ctypes.set_last_error() --- Lib/test/test_ctypes/test_as_parameter.py | 5 ++-- Lib/test/test_ctypes/test_callbacks.py | 18 +++++++-------- Lib/test/test_ctypes/test_cfuncs.py | 14 ++++------- Lib/test/test_ctypes/test_checkretval.py | 6 ++--- Lib/test/test_ctypes/test_errno.py | 19 +++++++-------- Lib/test/test_ctypes/test_funcptr.py | 9 ++++---- Lib/test/test_ctypes/test_functions.py | 7 +++--- Lib/test/test_ctypes/test_loading.py | 27 ++++++++++++---------- Lib/test/test_ctypes/test_pointers.py | 3 ++- Lib/test/test_ctypes/test_random_things.py | 15 +++++++----- Lib/test/test_ctypes/test_win32.py | 16 ++++++++----- 11 files changed, 75 insertions(+), 64 deletions(-) diff --git a/Lib/test/test_ctypes/test_as_parameter.py b/Lib/test/test_ctypes/test_as_parameter.py index e9ec9ad847b..fcf99ff0579 100644 --- a/Lib/test/test_ctypes/test_as_parameter.py +++ b/Lib/test/test_ctypes/test_as_parameter.py @@ -1,4 +1,5 @@ import unittest +import ctypes from ctypes import * from test.test_ctypes import need_symbol import _ctypes_test @@ -6,8 +7,8 @@ import _ctypes_test dll = CDLL(_ctypes_test.__file__) try: - CALLBACK_FUNCTYPE = WINFUNCTYPE -except NameError: + CALLBACK_FUNCTYPE = ctypes.WINFUNCTYPE +except AttributeError: # fake to enable this test on Linux CALLBACK_FUNCTYPE = CFUNCTYPE diff --git a/Lib/test/test_ctypes/test_callbacks.py b/Lib/test/test_ctypes/test_callbacks.py index b185e388ab1..a5c2e430d85 100644 --- a/Lib/test/test_ctypes/test_callbacks.py +++ b/Lib/test/test_ctypes/test_callbacks.py @@ -2,6 +2,7 @@ import functools import unittest from test import support +import ctypes from ctypes import * from test.test_ctypes import need_symbol from _ctypes import CTYPES_MAX_ARGCOUNT @@ -152,7 +153,7 @@ class Callbacks(unittest.TestCase): @need_symbol('WINFUNCTYPE') def test_i38748_stackCorruption(self): - callback_funcType = WINFUNCTYPE(c_long, c_long, c_longlong) + callback_funcType = ctypes.WINFUNCTYPE(c_long, c_long, c_longlong) @callback_funcType def callback(a, b): c = a + b @@ -163,12 +164,10 @@ class Callbacks(unittest.TestCase): self.assertEqual(dll._test_i38748_runCallback(callback, 5, 10), 15) -@need_symbol('WINFUNCTYPE') -class StdcallCallbacks(Callbacks): - try: - functype = WINFUNCTYPE - except NameError: - pass +if hasattr(ctypes, 'WINFUNCTYPE'): + class StdcallCallbacks(Callbacks): + functype = ctypes.WINFUNCTYPE + ################################################################ @@ -216,13 +215,14 @@ class SampleCallbacksTestCase(unittest.TestCase): global windowCount windowCount = 0 - @WINFUNCTYPE(BOOL, HWND, LPARAM) + @ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM) def EnumWindowsCallbackFunc(hwnd, lParam): global windowCount windowCount += 1 return True #Allow windows to keep enumerating - windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0) + user32 = ctypes.windll.user32 + user32.EnumWindows(EnumWindowsCallbackFunc, 0) def test_callback_register_int(self): # Issue #8275: buggy handling of callback args under Win64 diff --git a/Lib/test/test_ctypes/test_cfuncs.py b/Lib/test/test_ctypes/test_cfuncs.py index 7cba4b0e527..d66e679799c 100644 --- a/Lib/test/test_ctypes/test_cfuncs.py +++ b/Lib/test/test_ctypes/test_cfuncs.py @@ -2,6 +2,7 @@ # Byte order related? import unittest +import ctypes from ctypes import * from test.test_ctypes import need_symbol @@ -197,12 +198,8 @@ class CFunctions(unittest.TestCase): # 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) @@ -210,9 +207,8 @@ else: 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() diff --git a/Lib/test/test_ctypes/test_checkretval.py b/Lib/test/test_ctypes/test_checkretval.py index 1492099f4b9..b4834322ea7 100644 --- a/Lib/test/test_ctypes/test_checkretval.py +++ b/Lib/test/test_ctypes/test_checkretval.py @@ -1,5 +1,6 @@ import unittest +import ctypes from ctypes import * from test.test_ctypes import need_symbol @@ -28,9 +29,8 @@ class Test(unittest.TestCase): @need_symbol('oledll') def test_oledll(self): - self.assertRaises(OSError, - oledll.oleaut32.CreateTypeLib2, - 0, None, None) + oleaut32 = ctypes.oledll.oleaut32 + self.assertRaises(OSError, oleaut32.CreateTypeLib2, 0, None, None) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_ctypes/test_errno.py b/Lib/test/test_ctypes/test_errno.py index 3685164dde6..bfc20bd68fc 100644 --- a/Lib/test/test_ctypes/test_errno.py +++ b/Lib/test/test_ctypes/test_errno.py @@ -1,6 +1,7 @@ import unittest, os, errno import threading +import ctypes from ctypes import * from ctypes.util import find_library @@ -44,33 +45,33 @@ class Test(unittest.TestCase): @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() diff --git a/Lib/test/test_ctypes/test_funcptr.py b/Lib/test/test_ctypes/test_funcptr.py index e0b9b54e97f..ef6772c6e88 100644 --- a/Lib/test/test_ctypes/test_funcptr.py +++ b/Lib/test/test_ctypes/test_funcptr.py @@ -1,9 +1,10 @@ import unittest +import ctypes from ctypes import * try: - WINFUNCTYPE -except NameError: + WINFUNCTYPE = ctypes.WINFUNCTYPE +except AttributeError: # fake to enable this test on Linux WINFUNCTYPE = CFUNCTYPE @@ -39,7 +40,7 @@ class CFuncPtrTestCase(unittest.TestCase): # possible, as in C, to call cdecl functions with more parameters. #self.assertRaises(TypeError, c, 1, 2, 3) self.assertEqual(c(1, 2, 3, 4, 5, 6), 3) - if not WINFUNCTYPE is CFUNCTYPE: + if WINFUNCTYPE is not CFUNCTYPE: self.assertRaises(TypeError, s, 1, 2, 3) def test_structures(self): @@ -91,7 +92,7 @@ class CFuncPtrTestCase(unittest.TestCase): def NoNullHandle(value): if not value: - raise WinError() + raise ctypes.WinError() return value strchr = lib.my_strchr diff --git a/Lib/test/test_ctypes/test_functions.py b/Lib/test/test_ctypes/test_functions.py index 703bd2c601c..3f331703a0d 100644 --- a/Lib/test/test_ctypes/test_functions.py +++ b/Lib/test/test_ctypes/test_functions.py @@ -5,20 +5,21 @@ show how the type behave. Later... """ +import ctypes from ctypes import * from test.test_ctypes import need_symbol import sys, unittest try: - WINFUNCTYPE -except NameError: + WINFUNCTYPE = ctypes.WINFUNCTYPE +except AttributeError: # fake to enable this test on Linux WINFUNCTYPE = CFUNCTYPE 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)] diff --git a/Lib/test/test_ctypes/test_loading.py b/Lib/test/test_ctypes/test_loading.py index f2434926a51..fec26aab1d8 100644 --- a/Lib/test/test_ctypes/test_loading.py +++ b/Lib/test/test_ctypes/test_loading.py @@ -1,4 +1,5 @@ from ctypes import * +import ctypes import os import shutil import subprocess @@ -72,18 +73,18 @@ class LoaderTest(unittest.TestCase): 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 @@ -114,14 +115,16 @@ class LoaderTest(unittest.TestCase): # 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,))) @@ -130,7 +133,7 @@ class LoaderTest(unittest.TestCase): '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') diff --git a/Lib/test/test_ctypes/test_pointers.py b/Lib/test/test_ctypes/test_pointers.py index e97515879f1..7b6c3f5babe 100644 --- a/Lib/test/test_ctypes/test_pointers.py +++ b/Lib/test/test_ctypes/test_pointers.py @@ -1,5 +1,6 @@ import unittest, sys +import ctypes from ctypes import * import _ctypes_test @@ -193,7 +194,7 @@ class PointersTestCase(unittest.TestCase): # COM methods are boolean True: if sys.platform == "win32": - mth = WINFUNCTYPE(None)(42, "name", (), None) + mth = ctypes.WINFUNCTYPE(None)(42, "name", (), None) self.assertEqual(bool(mth), True) def test_pointer_type_name(self): diff --git a/Lib/test/test_ctypes/test_random_things.py b/Lib/test/test_ctypes/test_random_things.py index 2988e275cf4..cfd355a7f08 100644 --- a/Lib/test/test_ctypes/test_random_things.py +++ b/Lib/test/test_ctypes/test_random_things.py @@ -1,4 +1,5 @@ from ctypes import * +import ctypes import contextlib from test import support import unittest @@ -16,15 +17,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 diff --git a/Lib/test/test_ctypes/test_win32.py b/Lib/test/test_ctypes/test_win32.py index e51bdc8ad6b..43ed9dbe10c 100644 --- a/Lib/test/test_ctypes/test_win32.py +++ b/Lib/test/test_ctypes/test_win32.py @@ -1,5 +1,6 @@ # Windows specific tests +import ctypes from ctypes import * import unittest, sys from test import support @@ -14,15 +15,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') @@ -73,17 +76,18 @@ class TestWinError(unittest.TestCase): # see Issue 16169 import errno ERROR_INVALID_PARAMETER = 87 - msg = FormatError(ERROR_INVALID_PARAMETER).strip() + msg = ctypes.FormatError(ERROR_INVALID_PARAMETER).strip() args = (errno.EINVAL, msg, None, ERROR_INVALID_PARAMETER) - e = WinError(ERROR_INVALID_PARAMETER) + e = ctypes.WinError(ERROR_INVALID_PARAMETER) self.assertEqual(e.args, args) 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() + raise ctypes.WinError() except OSError as exc: e = exc self.assertEqual(e.args, args)