diff options
Diffstat (limited to 'Lib/ctypes')
55 files changed, 1297 insertions, 2046 deletions
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 8f09911..88c85ff 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -16,7 +16,7 @@ from struct import calcsize as _calcsize if __version__ != _ctypes_version: raise Exception("Version number mismatch", __version__, _ctypes_version) -if _os.name == "nt": +if _os.name in ("nt", "ce"): from _ctypes import FormatError DEFAULT_MODE = RTLD_LOCAL @@ -26,7 +26,7 @@ if _os.name == "posix" and _sys.platform == "darwin": # libraries. OS X 10.3 is Darwin 7, so we check for # that. - if int(_os.uname().release.split('.')[0]) < 8: + if int(_os.uname()[2].split('.')[0]) < 8: DEFAULT_MODE = RTLD_GLOBAL from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \ @@ -34,31 +34,31 @@ from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \ FUNCFLAG_USE_ERRNO as _FUNCFLAG_USE_ERRNO, \ FUNCFLAG_USE_LASTERROR as _FUNCFLAG_USE_LASTERROR -# WINOLEAPI -> HRESULT -# WINOLEAPI_(type) -# -# STDMETHODCALLTYPE -# -# STDMETHOD(name) -# STDMETHOD_(type, name) -# -# STDAPICALLTYPE +""" +WINOLEAPI -> HRESULT +WINOLEAPI_(type) + +STDMETHODCALLTYPE + +STDMETHOD(name) +STDMETHOD_(type, name) + +STDAPICALLTYPE +""" def create_string_buffer(init, size=None): - """create_string_buffer(aBytes) -> character array + """create_string_buffer(aString) -> character array create_string_buffer(anInteger) -> character array - create_string_buffer(aBytes, anInteger) -> character array + create_string_buffer(aString, anInteger) -> character array """ - if isinstance(init, bytes): + if isinstance(init, (str, unicode)): if size is None: size = len(init)+1 - _sys.audit("ctypes.create_string_buffer", init, size) buftype = c_char * size buf = buftype() buf.value = init return buf - elif isinstance(init, int): - _sys.audit("ctypes.create_string_buffer", None, init) + elif isinstance(init, (int, long)): buftype = c_char * init buf = buftype() return buf @@ -105,9 +105,12 @@ def CFUNCTYPE(restype, *argtypes, **kw): _c_functype_cache[(restype, argtypes, flags)] = CFunctionType return CFunctionType -if _os.name == "nt": +if _os.name in ("nt", "ce"): from _ctypes import LoadLibrary as _dlopen from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL + if _os.name == "ce": + # 'ce' doesn't have the stdcall calling convention + _FUNCFLAG_STDCALL = _FUNCFLAG_CDECL _win_functype_cache = {} def WINFUNCTYPE(restype, *argtypes, **kw): @@ -154,7 +157,7 @@ class py_object(_SimpleCData): _type_ = "O" def __repr__(self): try: - return super().__repr__() + return super(py_object, self).__repr__() except ValueError: return "%s(<NULL>)" % type(self).__name__ _check_size(py_object, "P") @@ -236,8 +239,14 @@ _check_size(c_char) class c_char_p(_SimpleCData): _type_ = "z" - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, c_void_p.from_buffer(self).value) + if _os.name == "nt": + def __repr__(self): + if not windll.kernel32.IsBadStringPtrA(self, -1): + return "%s(%r)" % (self.__class__.__name__, self.value) + return "%s(%s)" % (self.__class__.__name__, cast(self, c_void_p).value) + else: + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, cast(self, c_void_p).value) _check_size(c_char_p, "P") class c_void_p(_SimpleCData): @@ -250,53 +259,55 @@ class c_bool(_SimpleCData): from _ctypes import POINTER, pointer, _pointer_type_cache -class c_wchar_p(_SimpleCData): - _type_ = "Z" - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, c_void_p.from_buffer(self).value) - -class c_wchar(_SimpleCData): - _type_ = "u" - def _reset_cache(): _pointer_type_cache.clear() _c_functype_cache.clear() - if _os.name == "nt": + if _os.name in ("nt", "ce"): _win_functype_cache.clear() # _SimpleCData.c_wchar_p_from_param POINTER(c_wchar).from_param = c_wchar_p.from_param # _SimpleCData.c_char_p_from_param POINTER(c_char).from_param = c_char_p.from_param _pointer_type_cache[None] = c_void_p + # XXX for whatever reasons, creating the first instance of a callback + # function is needed for the unittests on Win64 to succeed. This MAY + # be a compiler bug, since the problem occurs only when _ctypes is + # compiled with the MS SDK compiler. Or an uninitialized variable? + CFUNCTYPE(c_int)(lambda: None) -def create_unicode_buffer(init, size=None): - """create_unicode_buffer(aString) -> character array - create_unicode_buffer(anInteger) -> character array - create_unicode_buffer(aString, anInteger) -> character array - """ - if isinstance(init, str): - if size is None: - if sizeof(c_wchar) == 2: - # UTF-16 requires a surrogate pair (2 wchar_t) for non-BMP - # characters (outside [U+0000; U+FFFF] range). +1 for trailing - # NUL character. - size = sum(2 if ord(c) > 0xFFFF else 1 for c in init) + 1 - else: - # 32-bit wchar_t (1 wchar_t per Unicode character). +1 for - # trailing NUL character. - size = len(init) + 1 - _sys.audit("ctypes.create_unicode_buffer", init, size) - buftype = c_wchar * size - buf = buftype() - buf.value = init - return buf - elif isinstance(init, int): - _sys.audit("ctypes.create_unicode_buffer", None, init) - buftype = c_wchar * init - buf = buftype() - return buf - raise TypeError(init) +try: + from _ctypes import set_conversion_mode +except ImportError: + pass +else: + if _os.name in ("nt", "ce"): + set_conversion_mode("mbcs", "ignore") + else: + set_conversion_mode("ascii", "strict") + + class c_wchar_p(_SimpleCData): + _type_ = "Z" + class c_wchar(_SimpleCData): + _type_ = "u" + + def create_unicode_buffer(init, size=None): + """create_unicode_buffer(aString) -> character array + create_unicode_buffer(anInteger) -> character array + create_unicode_buffer(aString, anInteger) -> character array + """ + if isinstance(init, (str, unicode)): + if size is None: + size = len(init)+1 + buftype = c_wchar * size + buf = buftype() + buf.value = init + return buf + elif isinstance(init, (int, long)): + buftype = c_wchar * init + buf = buftype() + return buf + raise TypeError(init) # XXX Deprecated def SetPointerType(pointer, cls): @@ -338,31 +349,13 @@ class CDLL(object): def __init__(self, name, mode=DEFAULT_MODE, handle=None, use_errno=False, - use_last_error=False, - winmode=None): + use_last_error=False): self._name = name flags = self._func_flags_ if use_errno: flags |= _FUNCFLAG_USE_ERRNO if use_last_error: flags |= _FUNCFLAG_USE_LASTERROR - if _sys.platform.startswith("aix"): - """When the name contains ".a(" and ends with ")", - e.g., "libFOO.a(libFOO.so)" - this is taken to be an - archive(member) syntax for dlopen(), and the mode is adjusted. - Otherwise, name is presented to dlopen() as a file argument. - """ - if name and name.endswith(")") and ".a(" in name: - mode |= ( _os.RTLD_MEMBER | _os.RTLD_NOW ) - if _os.name == "nt": - if winmode is not None: - mode = winmode - else: - import nt - mode = nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS - if '/' in name or '\\' in name: - self._name = nt._getfullpathname(self._name) - mode |= nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR class _FuncPtr(_CFuncPtr): _flags_ = flags @@ -375,10 +368,10 @@ class CDLL(object): self._handle = handle def __repr__(self): - return "<%s '%s', handle %x at %#x>" % \ + return "<%s '%s', handle %x at %x>" % \ (self.__class__.__name__, self._name, - (self._handle & (_sys.maxsize*2 + 1)), - id(self) & (_sys.maxsize*2 + 1)) + (self._handle & (_sys.maxint*2 + 1)), + id(self) & (_sys.maxint*2 + 1)) def __getattr__(self, name): if name.startswith('__') and name.endswith('__'): @@ -389,7 +382,7 @@ class CDLL(object): def __getitem__(self, name_or_ordinal): func = self._FuncPtr((name_or_ordinal, self)) - if not isinstance(name_or_ordinal, int): + if not isinstance(name_or_ordinal, (int, long)): func.__name__ = name_or_ordinal return func @@ -400,7 +393,7 @@ class PyDLL(CDLL): """ _func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI -if _os.name == "nt": +if _os.name in ("nt", "ce"): class WinDLL(CDLL): """This class represents a dll exporting functions using the @@ -415,7 +408,7 @@ if _os.name == "nt": _type_ = "l" # _check_retval_ is called with the function's result when it # is used as restype. It checks for the FAILED bit, and - # raises an OSError if it is set. + # raises a WindowsError if it is set. # # The _check_retval_ method is implemented in C, so that the # method definition itself is not included in the traceback @@ -427,7 +420,7 @@ if _os.name == "nt": class OleDLL(CDLL): """This class represents a dll exporting functions using the Windows stdcall calling convention, and returning HRESULT. - HRESULT error values are automatically raised as OSError + HRESULT error values are automatically raised as WindowsError exceptions. """ _func_flags_ = _FUNCFLAG_STDCALL @@ -453,7 +446,7 @@ class LibraryLoader(object): cdll = LibraryLoader(CDLL) pydll = LibraryLoader(PyDLL) -if _os.name == "nt": +if _os.name in ("nt", "ce"): pythonapi = PyDLL("python dll", None, _sys.dllhandle) elif _sys.platform == "cygwin": pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2]) @@ -461,11 +454,14 @@ else: pythonapi = PyDLL(None) -if _os.name == "nt": +if _os.name in ("nt", "ce"): windll = LibraryLoader(WinDLL) oledll = LibraryLoader(OleDLL) - GetLastError = windll.kernel32.GetLastError + if _os.name == "nt": + GetLastError = windll.kernel32.GetLastError + else: + GetLastError = windll.coredll.GetLastError from _ctypes import get_last_error, set_last_error def WinError(code=None, descr=None): @@ -473,7 +469,7 @@ if _os.name == "nt": code = GetLastError() if descr is None: descr = FormatError(code).strip() - return OSError(None, descr, None, code) + return WindowsError(code, descr) if sizeof(c_uint) == sizeof(c_void_p): c_size_t = c_uint @@ -526,7 +522,7 @@ else: return _wstring_at(ptr, size) -if _os.name == "nt": # COM stuff +if _os.name in ("nt", "ce"): # COM stuff def DllGetClassObject(rclsid, riid, ppv): try: ccom = __import__("comtypes.server.inprocserver", globals(), locals(), ['*']) diff --git a/Lib/ctypes/_aix.py b/Lib/ctypes/_aix.py deleted file mode 100644 index 190cac6..0000000 --- a/Lib/ctypes/_aix.py +++ /dev/null @@ -1,331 +0,0 @@ -""" -Lib/ctypes.util.find_library() support for AIX -Similar approach as done for Darwin support by using separate files -but unlike Darwin - no extension such as ctypes.macholib.* - -dlopen() is an interface to AIX initAndLoad() - primary documentation at: -https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.basetrf1/dlopen.htm -https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.basetrf1/load.htm - -AIX supports two styles for dlopen(): svr4 (System V Release 4) which is common on posix -platforms, but also a BSD style - aka SVR3. - -From AIX 5.3 Difference Addendum (December 2004) -2.9 SVR4 linking affinity -Nowadays, there are two major object file formats used by the operating systems: -XCOFF: The COFF enhanced by IBM and others. The original COFF (Common -Object File Format) was the base of SVR3 and BSD 4.2 systems. -ELF: Executable and Linking Format that was developed by AT&T and is a -base for SVR4 UNIX. - -While the shared library content is identical on AIX - one is located as a filepath name -(svr4 style) and the other is located as a member of an archive (and the archive -is located as a filepath name). - -The key difference arises when supporting multiple abi formats (i.e., 32 and 64 bit). -For svr4 either only one ABI is supported, or there are two directories, or there -are different file names. The most common solution for multiple ABI is multiple -directories. - -For the XCOFF (aka AIX) style - one directory (one archive file) is sufficient -as multiple shared libraries can be in the archive - even sharing the same name. -In documentation the archive is also referred to as the "base" and the shared -library object is referred to as the "member". - -For dlopen() on AIX (read initAndLoad()) the calls are similar. -Default activity occurs when no path information is provided. When path -information is provided dlopen() does not search any other directories. - -For SVR4 - the shared library name is the name of the file expected: libFOO.so -For AIX - the shared library is expressed as base(member). The search is for the -base (e.g., libFOO.a) and once the base is found the shared library - identified by -member (e.g., libFOO.so, or shr.o) is located and loaded. - -The mode bit RTLD_MEMBER tells initAndLoad() that it needs to use the AIX (SVR3) -naming style. -""" -__author__ = "Michael Felt <aixtools@felt.demon.nl>" - -import re -from os import environ, path -from sys import executable -from ctypes import c_void_p, sizeof -from subprocess import Popen, PIPE, DEVNULL - -# Executable bit size - 32 or 64 -# Used to filter the search in an archive by size, e.g., -X64 -AIX_ABI = sizeof(c_void_p) * 8 - - -from sys import maxsize -def _last_version(libnames, sep): - def _num_version(libname): - # "libxyz.so.MAJOR.MINOR" => [MAJOR, MINOR] - parts = libname.split(sep) - nums = [] - try: - while parts: - nums.insert(0, int(parts.pop())) - except ValueError: - pass - return nums or [maxsize] - return max(reversed(libnames), key=_num_version) - -def get_ld_header(p): - # "nested-function, but placed at module level - ld_header = None - for line in p.stdout: - if line.startswith(('/', './', '../')): - ld_header = line - elif "INDEX" in line: - return ld_header.rstrip('\n') - return None - -def get_ld_header_info(p): - # "nested-function, but placed at module level - # as an ld_header was found, return known paths, archives and members - # these lines start with a digit - info = [] - for line in p.stdout: - if re.match("[0-9]", line): - info.append(line) - else: - # blank line (separator), consume line and end for loop - break - return info - -def get_ld_headers(file): - """ - Parse the header of the loader section of executable and archives - This function calls /usr/bin/dump -H as a subprocess - and returns a list of (ld_header, ld_header_info) tuples. - """ - # get_ld_headers parsing: - # 1. Find a line that starts with /, ./, or ../ - set as ld_header - # 2. If "INDEX" in occurs in a following line - return ld_header - # 3. get info (lines starting with [0-9]) - ldr_headers = [] - p = Popen(["/usr/bin/dump", f"-X{AIX_ABI}", "-H", file], - universal_newlines=True, stdout=PIPE, stderr=DEVNULL) - # be sure to read to the end-of-file - getting all entries - while True: - ld_header = get_ld_header(p) - if ld_header: - ldr_headers.append((ld_header, get_ld_header_info(p))) - else: - break - p.stdout.close() - p.wait() - return ldr_headers - -def get_shared(ld_headers): - """ - extract the shareable objects from ld_headers - character "[" is used to strip off the path information. - Note: the "[" and "]" characters that are part of dump -H output - are not removed here. - """ - shared = [] - for (line, _) in ld_headers: - # potential member lines contain "[" - # otherwise, no processing needed - if "[" in line: - # Strip off trailing colon (:) - shared.append(line[line.index("["):-1]) - return shared - -def get_one_match(expr, lines): - """ - Must be only one match, otherwise result is None. - When there is a match, strip leading "[" and trailing "]" - """ - # member names in the ld_headers output are between square brackets - expr = rf'\[({expr})\]' - matches = list(filter(None, (re.search(expr, line) for line in lines))) - if len(matches) == 1: - return matches[0].group(1) - else: - return None - -# additional processing to deal with AIX legacy names for 64-bit members -def get_legacy(members): - """ - This routine provides historical aka legacy naming schemes started - in AIX4 shared library support for library members names. - e.g., in /usr/lib/libc.a the member name shr.o for 32-bit binary and - shr_64.o for 64-bit binary. - """ - if AIX_ABI == 64: - # AIX 64-bit member is one of shr64.o, shr_64.o, or shr4_64.o - expr = r'shr4?_?64\.o' - member = get_one_match(expr, members) - if member: - return member - else: - # 32-bit legacy names - both shr.o and shr4.o exist. - # shr.o is the preffered name so we look for shr.o first - # i.e., shr4.o is returned only when shr.o does not exist - for name in ['shr.o', 'shr4.o']: - member = get_one_match(re.escape(name), members) - if member: - return member - return None - -def get_version(name, members): - """ - Sort list of members and return highest numbered version - if it exists. - This function is called when an unversioned libFOO.a(libFOO.so) has - not been found. - - Versioning for the member name is expected to follow - GNU LIBTOOL conventions: the highest version (x, then X.y, then X.Y.z) - * find [libFoo.so.X] - * find [libFoo.so.X.Y] - * find [libFoo.so.X.Y.Z] - - Before the GNU convention became the standard scheme regardless of - binary size AIX packagers used GNU convention "as-is" for 32-bit - archive members but used an "distinguishing" name for 64-bit members. - This scheme inserted either 64 or _64 between libFOO and .so - - generally libFOO_64.so, but occasionally libFOO64.so - """ - # the expression ending for versions must start as - # '.so.[0-9]', i.e., *.so.[at least one digit] - # while multiple, more specific expressions could be specified - # to search for .so.X, .so.X.Y and .so.X.Y.Z - # after the first required 'dot' digit - # any combination of additional 'dot' digits pairs are accepted - # anything more than libFOO.so.digits.digits.digits - # should be seen as a member name outside normal expectations - exprs = [rf'lib{name}\.so\.[0-9]+[0-9.]*', - rf'lib{name}_?64\.so\.[0-9]+[0-9.]*'] - for expr in exprs: - versions = [] - for line in members: - m = re.search(expr, line) - if m: - versions.append(m.group(0)) - if versions: - return _last_version(versions, '.') - return None - -def get_member(name, members): - """ - Return an archive member matching the request in name. - Name is the library name without any prefix like lib, suffix like .so, - or version number. - Given a list of members find and return the most appropriate result - Priority is given to generic libXXX.so, then a versioned libXXX.so.a.b.c - and finally, legacy AIX naming scheme. - """ - # look first for a generic match - prepend lib and append .so - expr = rf'lib{name}\.so' - member = get_one_match(expr, members) - if member: - return member - elif AIX_ABI == 64: - expr = rf'lib{name}64\.so' - member = get_one_match(expr, members) - if member: - return member - # since an exact match with .so as suffix was not found - # look for a versioned name - # If a versioned name is not found, look for AIX legacy member name - member = get_version(name, members) - if member: - return member - else: - return get_legacy(members) - -def get_libpaths(): - """ - On AIX, the buildtime searchpath is stored in the executable. - as "loader header information". - The command /usr/bin/dump -H extracts this info. - Prefix searched libraries with LD_LIBRARY_PATH (preferred), - or LIBPATH if defined. These paths are appended to the paths - to libraries the python executable is linked with. - This mimics AIX dlopen() behavior. - """ - libpaths = environ.get("LD_LIBRARY_PATH") - if libpaths is None: - libpaths = environ.get("LIBPATH") - if libpaths is None: - libpaths = [] - else: - libpaths = libpaths.split(":") - objects = get_ld_headers(executable) - for (_, lines) in objects: - for line in lines: - # the second (optional) argument is PATH if it includes a / - path = line.split()[1] - if "/" in path: - libpaths.extend(path.split(":")) - return libpaths - -def find_shared(paths, name): - """ - paths is a list of directories to search for an archive. - name is the abbreviated name given to find_library(). - Process: search "paths" for archive, and if an archive is found - return the result of get_member(). - If an archive is not found then return None - """ - for dir in paths: - # /lib is a symbolic link to /usr/lib, skip it - if dir == "/lib": - continue - # "lib" is prefixed to emulate compiler name resolution, - # e.g., -lc to libc - base = f'lib{name}.a' - archive = path.join(dir, base) - if path.exists(archive): - members = get_shared(get_ld_headers(archive)) - member = get_member(re.escape(name), members) - if member != None: - return (base, member) - else: - return (None, None) - return (None, None) - -def find_library(name): - """AIX implementation of ctypes.util.find_library() - Find an archive member that will dlopen(). If not available, - also search for a file (or link) with a .so suffix. - - AIX supports two types of schemes that can be used with dlopen(). - The so-called SystemV Release4 (svr4) format is commonly suffixed - with .so while the (default) AIX scheme has the library (archive) - ending with the suffix .a - As an archive has multiple members (e.g., 32-bit and 64-bit) in one file - the argument passed to dlopen must include both the library and - the member names in a single string. - - find_library() looks first for an archive (.a) with a suitable member. - If no archive+member pair is found, look for a .so file. - """ - - libpaths = get_libpaths() - (base, member) = find_shared(libpaths, name) - if base != None: - return f"{base}({member})" - - # To get here, a member in an archive has not been found - # In other words, either: - # a) a .a file was not found - # b) a .a file did not have a suitable member - # So, look for a .so file - # Check libpaths for .so file - # Note, the installation must prepare a link from a .so - # to a versioned file - # This is common practice by GNU libtool on other platforms - soname = f"lib{name}.so" - for dir in libpaths: - # /lib is a symbolic link to /usr/lib, skip it - if dir == "/lib": - continue - shlib = path.join(dir, soname) - if path.exists(shlib): - return soname - # if we are here, we have not found anything plausible - return None diff --git a/Lib/ctypes/_endian.py b/Lib/ctypes/_endian.py index 37444bd..c0ba646 100644 --- a/Lib/ctypes/_endian.py +++ b/Lib/ctypes/_endian.py @@ -30,7 +30,7 @@ class _swapped_meta(type(Structure)): rest = desc[2:] fields.append((name, _other_endian(typ)) + rest) value = fields - super().__setattr__(attrname, value) + super(_swapped_meta, self).__setattr__(attrname, value) ################################################################ @@ -43,18 +43,18 @@ if sys.byteorder == "little": LittleEndianStructure = Structure - class BigEndianStructure(Structure, metaclass=_swapped_meta): + class BigEndianStructure(Structure): """Structure with big endian byte order""" - __slots__ = () + __metaclass__ = _swapped_meta _swappedbytes_ = None elif sys.byteorder == "big": _OTHER_ENDIAN = "__ctype_le__" BigEndianStructure = Structure - class LittleEndianStructure(Structure, metaclass=_swapped_meta): + class LittleEndianStructure(Structure): """Structure with little endian byte order""" - __slots__ = () + __metaclass__ = _swapped_meta _swappedbytes_ = None else: diff --git a/Lib/ctypes/macholib/dyld.py b/Lib/ctypes/macholib/dyld.py index 9d86b05..1fdf8d6 100644 --- a/Lib/ctypes/macholib/dyld.py +++ b/Lib/ctypes/macholib/dyld.py @@ -3,8 +3,8 @@ dyld emulation """ import os -from ctypes.macholib.framework import framework_info -from ctypes.macholib.dylib import dylib_info +from framework import framework_info +from dylib import dylib_info from itertools import * __all__ = [ @@ -28,6 +28,12 @@ DEFAULT_LIBRARY_FALLBACK = [ "/usr/lib", ] +def ensure_utf8(s): + """Not all of PyObjC and Python understand unicode paths very well yet""" + if isinstance(s, unicode): + return s.encode('utf8') + return s + def dyld_env(env, var): if env is None: env = os.environ @@ -117,6 +123,8 @@ def dyld_find(name, executable_path=None, env=None): """ Find a library or framework using dyld semantics """ + name = ensure_utf8(name) + executable_path = ensure_utf8(executable_path) for path in dyld_image_suffix_search(chain( dyld_override_search(name, env), dyld_executable_path_search(name, executable_path), @@ -135,11 +143,10 @@ def framework_find(fn, executable_path=None, env=None): Python.framework Python.framework/Versions/Current """ - error = None try: return dyld_find(fn, executable_path=executable_path, env=env) - except ValueError as e: - error = e + except ValueError, e: + pass fmwk_index = fn.rfind('.framework') if fmwk_index == -1: fmwk_index = len(fn) @@ -148,9 +155,7 @@ def framework_find(fn, executable_path=None, env=None): try: return dyld_find(fn, executable_path=executable_path, env=env) except ValueError: - raise error - finally: - error = None + raise e def test_dyld_find(): env = {} diff --git a/Lib/ctypes/test/__init__.py b/Lib/ctypes/test/__init__.py index 26a70b7..f2cc143 100644 --- a/Lib/ctypes/test/__init__.py +++ b/Lib/ctypes/test/__init__.py @@ -1,14 +1,216 @@ -import os -import unittest -from test import support +import os, sys, unittest, getopt, time -# skip tests if _ctypes was not built -ctypes = support.import_module('ctypes') +use_resources = [] + +import ctypes ctypes_symbols = dir(ctypes) def need_symbol(name): return unittest.skipUnless(name in ctypes_symbols, '{!r} is required'.format(name)) -def load_tests(*args): - return support.load_package_tests(os.path.dirname(__file__), *args) + +class ResourceDenied(unittest.SkipTest): + """Test skipped because it requested a disallowed resource. + + This is raised when a test calls requires() for a resource that + has not be enabled. Resources are defined by test modules. + """ + +def is_resource_enabled(resource): + """Test whether a resource is enabled. + + If the caller's module is __main__ then automatically return True.""" + if sys._getframe().f_back.f_globals.get("__name__") == "__main__": + return True + result = use_resources is not None and \ + (resource in use_resources or "*" in use_resources) + if not result: + _unavail[resource] = None + return result + +_unavail = {} +def requires(resource, msg=None): + """Raise ResourceDenied if the specified resource is not available. + + If the caller's module is __main__ then automatically return True.""" + # see if the caller's module is __main__ - if so, treat as if + # the resource was set + if sys._getframe().f_back.f_globals.get("__name__") == "__main__": + return + if not is_resource_enabled(resource): + if msg is None: + msg = "Use of the `%s' resource not enabled" % resource + raise ResourceDenied(msg) + +def find_package_modules(package, mask): + import fnmatch + if (hasattr(package, "__loader__") and + hasattr(package.__loader__, '_files')): + path = package.__name__.replace(".", os.path.sep) + mask = os.path.join(path, mask) + for fnm in package.__loader__._files.iterkeys(): + if fnmatch.fnmatchcase(fnm, mask): + yield os.path.splitext(fnm)[0].replace(os.path.sep, ".") + else: + path = package.__path__[0] + for fnm in os.listdir(path): + if fnmatch.fnmatchcase(fnm, mask): + yield "%s.%s" % (package.__name__, os.path.splitext(fnm)[0]) + +def get_tests(package, mask, verbosity, exclude=()): + """Return a list of skipped test modules, and a list of test cases.""" + tests = [] + skipped = [] + for modname in find_package_modules(package, mask): + if modname.split(".")[-1] in exclude: + skipped.append(modname) + if verbosity > 1: + print >> sys.stderr, "Skipped %s: excluded" % modname + continue + try: + mod = __import__(modname, globals(), locals(), ['*']) + except (ResourceDenied, unittest.SkipTest) as detail: + skipped.append(modname) + if verbosity > 1: + print >> sys.stderr, "Skipped %s: %s" % (modname, detail) + continue + for name in dir(mod): + if name.startswith("_"): + continue + o = getattr(mod, name) + if type(o) is type(unittest.TestCase) and issubclass(o, unittest.TestCase): + tests.append(o) + return skipped, tests + +def usage(): + print __doc__ + return 1 + +def test_with_refcounts(runner, verbosity, testcase): + """Run testcase several times, tracking reference counts.""" + import gc + import ctypes + ptc = ctypes._pointer_type_cache.copy() + cfc = ctypes._c_functype_cache.copy() + wfc = ctypes._win_functype_cache.copy() + + # when searching for refcount leaks, we have to manually reset any + # caches that ctypes has. + def cleanup(): + ctypes._pointer_type_cache = ptc.copy() + ctypes._c_functype_cache = cfc.copy() + ctypes._win_functype_cache = wfc.copy() + gc.collect() + + test = unittest.makeSuite(testcase) + for i in range(5): + rc = sys.gettotalrefcount() + runner.run(test) + cleanup() + COUNT = 5 + refcounts = [None] * COUNT + for i in range(COUNT): + rc = sys.gettotalrefcount() + runner.run(test) + cleanup() + refcounts[i] = sys.gettotalrefcount() - rc + if filter(None, refcounts): + print "%s leaks:\n\t" % testcase, refcounts + elif verbosity: + print "%s: ok." % testcase + +class TestRunner(unittest.TextTestRunner): + def run(self, test, skipped): + "Run the given test case or test suite." + # Same as unittest.TextTestRunner.run, except that it reports + # skipped tests. + result = self._makeResult() + startTime = time.time() + test(result) + stopTime = time.time() + timeTaken = stopTime - startTime + result.printErrors() + self.stream.writeln(result.separator2) + run = result.testsRun + if _unavail: #skipped: + requested = _unavail.keys() + requested.sort() + self.stream.writeln("Ran %d test%s in %.3fs (%s module%s skipped)" % + (run, run != 1 and "s" or "", timeTaken, + len(skipped), + len(skipped) != 1 and "s" or "")) + self.stream.writeln("Unavailable resources: %s" % ", ".join(requested)) + else: + self.stream.writeln("Ran %d test%s in %.3fs" % + (run, run != 1 and "s" or "", timeTaken)) + self.stream.writeln() + if not result.wasSuccessful(): + self.stream.write("FAILED (") + failed, errored = map(len, (result.failures, result.errors)) + if failed: + self.stream.write("failures=%d" % failed) + if errored: + if failed: self.stream.write(", ") + self.stream.write("errors=%d" % errored) + self.stream.writeln(")") + else: + self.stream.writeln("OK") + return result + + +def main(*packages): + try: + opts, args = getopt.getopt(sys.argv[1:], "rqvu:x:") + except getopt.error: + return usage() + + verbosity = 1 + search_leaks = False + exclude = [] + for flag, value in opts: + if flag == "-q": + verbosity -= 1 + elif flag == "-v": + verbosity += 1 + elif flag == "-r": + try: + sys.gettotalrefcount + except AttributeError: + print >> sys.stderr, "-r flag requires Python debug build" + return -1 + search_leaks = True + elif flag == "-u": + use_resources.extend(value.split(",")) + elif flag == "-x": + exclude.extend(value.split(",")) + + mask = "test_*.py" + if args: + mask = args[0] + + for package in packages: + run_tests(package, mask, verbosity, search_leaks, exclude) + + +def run_tests(package, mask, verbosity, search_leaks, exclude): + skipped, testcases = get_tests(package, mask, verbosity, exclude) + runner = TestRunner(verbosity=verbosity) + + suites = [unittest.makeSuite(o) for o in testcases] + suite = unittest.TestSuite(suites) + result = runner.run(suite, skipped) + + if search_leaks: + # hunt for refcount leaks + runner = BasicTestRunner() + for t in testcases: + test_with_refcounts(runner, verbosity, t) + + return bool(result.errors) + +class BasicTestRunner: + def run(self, test): + result = unittest.TestResult() + test(result) + return result diff --git a/Lib/ctypes/test/__main__.py b/Lib/ctypes/test/__main__.py deleted file mode 100644 index 362a9ec..0000000 --- a/Lib/ctypes/test/__main__.py +++ /dev/null @@ -1,4 +0,0 @@ -from ctypes.test import load_tests -import unittest - -unittest.main() diff --git a/Lib/ctypes/test/runtests.py b/Lib/ctypes/test/runtests.py new file mode 100644 index 0000000..b7a2b26 --- /dev/null +++ b/Lib/ctypes/test/runtests.py @@ -0,0 +1,19 @@ +"""Usage: runtests.py [-q] [-r] [-v] [-u resources] [mask] + +Run all tests found in this directory, and print a summary of the results. +Command line flags: + -q quiet mode: don't print anything while the tests are running + -r run tests repeatedly, look for refcount leaks + -u<resources> + Add resources to the lits of allowed resources. '*' allows all + resources. + -v verbose mode: print the test currently executed + -x<test1[,test2...]> + Exclude specified tests. + mask mask to select filenames containing testcases, wildcards allowed +""" +import sys +import ctypes.test + +if __name__ == "__main__": + sys.exit(ctypes.test.main(ctypes.test)) diff --git a/Lib/ctypes/test/test_anon.py b/Lib/ctypes/test/test_anon.py index d378392..2c28b7f 100644 --- a/Lib/ctypes/test/test_anon.py +++ b/Lib/ctypes/test/test_anon.py @@ -1,5 +1,5 @@ import unittest -import test.support +from test.support import cpython_only from ctypes import * class AnonTest(unittest.TestCase): @@ -36,7 +36,7 @@ class AnonTest(unittest.TestCase): {"_fields_": [], "_anonymous_": ["x"]})) - @test.support.cpython_only + @cpython_only def test_issue31490(self): # There shouldn't be an assertion failure in case the class has an # attribute whose name is specified in _anonymous_ but not in _fields_. diff --git a/Lib/ctypes/test/test_array_in_pointer.py b/Lib/ctypes/test/test_array_in_pointer.py index ca1edcf..ee7863c 100644 --- a/Lib/ctypes/test/test_array_in_pointer.py +++ b/Lib/ctypes/test/test_array_in_pointer.py @@ -6,7 +6,7 @@ import re def dump(obj): # helper function to dump memory contents in hex, with a hyphen # between the bytes. - h = hexlify(memoryview(obj)).decode() + h = hexlify(memoryview(obj)) return re.sub(r"(..)", r"\1-", h)[:-1] diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py index 14603b7..ec00d9f 100644 --- a/Lib/ctypes/test/test_arrays.py +++ b/Lib/ctypes/test/test_arrays.py @@ -1,5 +1,5 @@ import unittest -from test.support import bigmemtest, _2G +from test.support import precisionbigmemtest, _2G import sys from ctypes import * @@ -15,7 +15,7 @@ class ArrayTestCase(unittest.TestCase): # create classes holding simple numeric types, and check # various properties. - init = list(range(15, 25)) + init = range(15, 25) for fmt in formats: alen = len(init) @@ -35,7 +35,7 @@ class ArrayTestCase(unittest.TestCase): # change the items from operator import setitem - new_values = list(range(42, 42+alen)) + new_values = range(42, 42+alen) [setitem(ia, n, new_values[n]) for n in range(alen)] values = [ia[i] for i in range(alen)] self.assertEqual(values, new_values) @@ -50,36 +50,28 @@ class ArrayTestCase(unittest.TestCase): CharArray = ARRAY(c_char, 3) - ca = CharArray(b"a", b"b", b"c") + ca = CharArray("a", "b", "c") # Should this work? It doesn't: # CharArray("abc") self.assertRaises(TypeError, CharArray, "abc") - self.assertEqual(ca[0], b"a") - self.assertEqual(ca[1], b"b") - self.assertEqual(ca[2], b"c") - self.assertEqual(ca[-3], b"a") - self.assertEqual(ca[-2], b"b") - self.assertEqual(ca[-1], b"c") + self.assertEqual(ca[0], "a") + self.assertEqual(ca[1], "b") + self.assertEqual(ca[2], "c") + self.assertEqual(ca[-3], "a") + self.assertEqual(ca[-2], "b") + self.assertEqual(ca[-1], "c") self.assertEqual(len(ca), 3) + # slicing is now supported, but not extended slicing (3-argument)! + from operator import getslice, delitem + self.assertRaises(TypeError, getslice, ca, 0, 1, -1) + # cannot delete items - from operator import delitem self.assertRaises(TypeError, delitem, ca, 0) - def test_step_overflow(self): - a = (c_int * 5)() - a[3::sys.maxsize] = (1,) - self.assertListEqual(a[3::sys.maxsize], [1]) - a = (c_char * 5)() - a[3::sys.maxsize] = b"A" - self.assertEqual(a[3::sys.maxsize], b"A") - a = (c_wchar * 5)() - a[3::sys.maxsize] = u"X" - self.assertEqual(a[3::sys.maxsize], u"X") - def test_numeric_arrays(self): alen = 5 @@ -108,14 +100,14 @@ class ArrayTestCase(unittest.TestCase): def test_from_address(self): # Failed with 0.9.8, reported by JUrner - p = create_string_buffer(b"foo") + p = create_string_buffer("foo") sz = (c_char * 3).from_address(addressof(p)) - self.assertEqual(sz[:], b"foo") - self.assertEqual(sz[::], b"foo") - self.assertEqual(sz[::-1], b"oof") - self.assertEqual(sz[::3], b"f") - self.assertEqual(sz[1:4:2], b"o") - self.assertEqual(sz.value, b"foo") + self.assertEqual(sz[:], "foo") + self.assertEqual(sz[::], "foo") + self.assertEqual(sz[::-1], "oof") + self.assertEqual(sz[::3], "f") + self.assertEqual(sz[1:4:2], "o") + self.assertEqual(sz.value, "foo") @need_symbol('create_unicode_buffer') def test_from_addressW(self): @@ -142,72 +134,6 @@ class ArrayTestCase(unittest.TestCase): t2 = my_int * 1 self.assertIs(t1, t2) - def test_subclass(self): - class T(Array): - _type_ = c_int - _length_ = 13 - class U(T): - pass - class V(U): - pass - class W(V): - pass - class X(T): - _type_ = c_short - class Y(T): - _length_ = 187 - - for c in [T, U, V, W]: - self.assertEqual(c._type_, c_int) - self.assertEqual(c._length_, 13) - self.assertEqual(c()._type_, c_int) - self.assertEqual(c()._length_, 13) - - self.assertEqual(X._type_, c_short) - self.assertEqual(X._length_, 13) - self.assertEqual(X()._type_, c_short) - self.assertEqual(X()._length_, 13) - - self.assertEqual(Y._type_, c_int) - self.assertEqual(Y._length_, 187) - self.assertEqual(Y()._type_, c_int) - self.assertEqual(Y()._length_, 187) - - def test_bad_subclass(self): - with self.assertRaises(AttributeError): - class T(Array): - pass - with self.assertRaises(AttributeError): - class T(Array): - _type_ = c_int - with self.assertRaises(AttributeError): - class T(Array): - _length_ = 13 - - def test_bad_length(self): - with self.assertRaises(ValueError): - class T(Array): - _type_ = c_int - _length_ = - sys.maxsize * 2 - with self.assertRaises(ValueError): - class T(Array): - _type_ = c_int - _length_ = -1 - with self.assertRaises(TypeError): - class T(Array): - _type_ = c_int - _length_ = 1.87 - with self.assertRaises(OverflowError): - class T(Array): - _type_ = c_int - _length_ = sys.maxsize * 2 - - def test_zero_length(self): - # _length_ can be zero. - class T(Array): - _type_ = c_int - _length_ = 0 - def test_empty_element_struct(self): class EmptyStruct(Structure): _fields_ = [] @@ -230,9 +156,9 @@ class ArrayTestCase(unittest.TestCase): c_char * sys.maxsize * 2 @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') - @bigmemtest(size=_2G, memuse=1, dry_run=False) + @precisionbigmemtest(size=_2G, memuse=1, dry_run=False) def test_large_array(self, size): - c_char * size + a = c_char * size if __name__ == '__main__': unittest.main() diff --git a/Lib/ctypes/test/test_as_parameter.py b/Lib/ctypes/test/test_as_parameter.py index f9d27cb..de730e9 100644 --- a/Lib/ctypes/test/test_as_parameter.py +++ b/Lib/ctypes/test/test_as_parameter.py @@ -22,7 +22,7 @@ class BasicWrapTestCase(unittest.TestCase): def test_wchar_parm(self): f = dll._testfunc_i_bhilfd f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double] - result = f(self.wrap(1), self.wrap("x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0)) + result = f(self.wrap(1), self.wrap(u"x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0)) self.assertEqual(result, 139) self.assertIs(type(result), int) @@ -132,7 +132,7 @@ class BasicWrapTestCase(unittest.TestCase): f.argtypes = [c_longlong, MyCallback] def callback(value): - self.assertIsInstance(value, int) + self.assertIsInstance(value, (int, long)) return value & 0x7FFFFFFF cb = MyCallback(callback) @@ -169,10 +169,6 @@ class BasicWrapTestCase(unittest.TestCase): s2h = dll.ret_2h_func(self.wrap(inp)) self.assertEqual((s2h.x, s2h.y), (99*2, 88*3)) - # Test also that the original struct was unmodified (i.e. was passed by - # value) - self.assertEqual((inp.x, inp.y), (99, 88)) - def test_struct_return_8H(self): class S8I(Structure): _fields_ = [("a", c_int), @@ -198,7 +194,7 @@ class BasicWrapTestCase(unittest.TestCase): a = A() a._as_parameter_ = a - with self.assertRaises(RecursionError): + with self.assertRaises(RuntimeError): c_int.from_param(a) diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py index 992b8c4..a854d2b 100644 --- a/Lib/ctypes/test/test_bitfields.py +++ b/Lib/ctypes/test/test_bitfields.py @@ -3,6 +3,7 @@ from ctypes.test import need_symbol import unittest import os +import ctypes import _ctypes_test class BITS(Structure): @@ -37,18 +38,14 @@ class C_Test(unittest.TestCase): for name in "ABCDEFGHI": b = BITS() setattr(b, name, i) - self.assertEqual(getattr(b, name), func(byref(b), name.encode('ascii'))) + self.assertEqual((name, i, getattr(b, name)), (name, i, func(byref(b), name))) def test_shorts(self): - b = BITS() - name = "M" - if func(byref(b), name.encode('ascii')) == 999: - self.skipTest("Compiler does not support signed short bitfields") for i in range(256): for name in "MNOPQRS": b = BITS() setattr(b, name, i) - self.assertEqual(getattr(b, name), func(byref(b), name.encode('ascii'))) + self.assertEqual((name, i, getattr(b, name)), (name, i, func(byref(b), name))) signed_int_types = (c_byte, c_short, c_int, c_long, c_longlong) unsigned_int_types = (c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong) @@ -193,14 +190,14 @@ class BitFieldTest(unittest.TestCase): def get_except(self, func, *args, **kw): try: func(*args, **kw) - except Exception as detail: + except Exception, detail: return detail.__class__, str(detail) def test_mixed_1(self): class X(Structure): _fields_ = [("a", c_byte, 4), ("b", c_int, 4)] - if os.name == "nt": + if os.name in ("nt", "ce"): self.assertEqual(sizeof(X), sizeof(c_int)*2) else: self.assertEqual(sizeof(X), sizeof(c_int)) @@ -228,7 +225,7 @@ class BitFieldTest(unittest.TestCase): # MSVC does NOT combine c_short and c_int into one field, GCC # does (unless GCC is run with '-mms-bitfields' which # produces code compatible with MSVC). - if os.name == "nt": + if os.name in ("nt", "ce"): self.assertEqual(sizeof(X), sizeof(c_int) * 4) else: self.assertEqual(sizeof(X), sizeof(c_int) * 2) diff --git a/Lib/ctypes/test/test_buffers.py b/Lib/ctypes/test/test_buffers.py index 15782be..88d87e9 100644 --- a/Lib/ctypes/test/test_buffers.py +++ b/Lib/ctypes/test/test_buffers.py @@ -8,66 +8,65 @@ class StringBufferTestCase(unittest.TestCase): b = create_string_buffer(32) self.assertEqual(len(b), 32) self.assertEqual(sizeof(b), 32 * sizeof(c_char)) - self.assertIs(type(b[0]), bytes) + self.assertIs(type(b[0]), str) - b = create_string_buffer(b"abc") + b = create_string_buffer("abc") self.assertEqual(len(b), 4) # trailing nul char self.assertEqual(sizeof(b), 4 * sizeof(c_char)) - self.assertIs(type(b[0]), bytes) - self.assertEqual(b[0], b"a") - self.assertEqual(b[:], b"abc\0") - self.assertEqual(b[::], b"abc\0") - self.assertEqual(b[::-1], b"\0cba") - self.assertEqual(b[::2], b"ac") - self.assertEqual(b[::5], b"a") - - self.assertRaises(TypeError, create_string_buffer, "abc") + self.assertIs(type(b[0]), str) + self.assertEqual(b[0], "a") + self.assertEqual(b[:], "abc\0") + self.assertEqual(b[::], "abc\0") + self.assertEqual(b[::-1], "\0cba") + self.assertEqual(b[::2], "ac") + self.assertEqual(b[::5], "a") def test_buffer_interface(self): self.assertEqual(len(bytearray(create_string_buffer(0))), 0) self.assertEqual(len(bytearray(create_string_buffer(1))), 1) + def test_string_conversion(self): + b = create_string_buffer(u"abc") + self.assertEqual(len(b), 4) # trailing nul char + self.assertEqual(sizeof(b), 4 * sizeof(c_char)) + self.assertTrue(type(b[0]) is str) + self.assertEqual(b[0], "a") + self.assertEqual(b[:], "abc\0") + self.assertEqual(b[::], "abc\0") + self.assertEqual(b[::-1], "\0cba") + self.assertEqual(b[::2], "ac") + self.assertEqual(b[::5], "a") + @need_symbol('c_wchar') def test_unicode_buffer(self): b = create_unicode_buffer(32) self.assertEqual(len(b), 32) self.assertEqual(sizeof(b), 32 * sizeof(c_wchar)) - self.assertIs(type(b[0]), str) + self.assertIs(type(b[0]), unicode) - b = create_unicode_buffer("abc") + b = create_unicode_buffer(u"abc") self.assertEqual(len(b), 4) # trailing nul char self.assertEqual(sizeof(b), 4 * sizeof(c_wchar)) - self.assertIs(type(b[0]), str) - self.assertEqual(b[0], "a") + self.assertIs(type(b[0]), unicode) + self.assertEqual(b[0], u"a") self.assertEqual(b[:], "abc\0") self.assertEqual(b[::], "abc\0") self.assertEqual(b[::-1], "\0cba") self.assertEqual(b[::2], "ac") self.assertEqual(b[::5], "a") - self.assertRaises(TypeError, create_unicode_buffer, b"abc") - @need_symbol('c_wchar') def test_unicode_conversion(self): b = create_unicode_buffer("abc") self.assertEqual(len(b), 4) # trailing nul char self.assertEqual(sizeof(b), 4 * sizeof(c_wchar)) - self.assertIs(type(b[0]), str) - self.assertEqual(b[0], "a") + self.assertIs(type(b[0]), unicode) + self.assertEqual(b[0], u"a") self.assertEqual(b[:], "abc\0") self.assertEqual(b[::], "abc\0") self.assertEqual(b[::-1], "\0cba") self.assertEqual(b[::2], "ac") self.assertEqual(b[::5], "a") - @need_symbol('c_wchar') - def test_create_unicode_buffer_non_bmp(self): - expected = 5 if sizeof(c_wchar) == 2 else 3 - for s in '\U00010000\U00100000', '\U00010000\U0010ffff': - b = create_unicode_buffer(s) - self.assertEqual(len(b), expected) - self.assertEqual(b[-1], '\0') - - if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_bytes.py b/Lib/ctypes/test/test_bytes.py deleted file mode 100644 index 092ec5a..0000000 --- a/Lib/ctypes/test/test_bytes.py +++ /dev/null @@ -1,66 +0,0 @@ -"""Test where byte objects are accepted""" -import unittest -import sys -from ctypes import * - -class BytesTest(unittest.TestCase): - def test_c_char(self): - x = c_char(b"x") - self.assertRaises(TypeError, c_char, "x") - x.value = b"y" - with self.assertRaises(TypeError): - x.value = "y" - c_char.from_param(b"x") - self.assertRaises(TypeError, c_char.from_param, "x") - self.assertIn('xbd', repr(c_char.from_param(b"\xbd"))) - (c_char * 3)(b"a", b"b", b"c") - self.assertRaises(TypeError, c_char * 3, "a", "b", "c") - - def test_c_wchar(self): - x = c_wchar("x") - self.assertRaises(TypeError, c_wchar, b"x") - x.value = "y" - with self.assertRaises(TypeError): - x.value = b"y" - c_wchar.from_param("x") - self.assertRaises(TypeError, c_wchar.from_param, b"x") - (c_wchar * 3)("a", "b", "c") - self.assertRaises(TypeError, c_wchar * 3, b"a", b"b", b"c") - - def test_c_char_p(self): - c_char_p(b"foo bar") - self.assertRaises(TypeError, c_char_p, "foo bar") - - def test_c_wchar_p(self): - c_wchar_p("foo bar") - self.assertRaises(TypeError, c_wchar_p, b"foo bar") - - def test_struct(self): - class X(Structure): - _fields_ = [("a", c_char * 3)] - - x = X(b"abc") - self.assertRaises(TypeError, X, "abc") - self.assertEqual(x.a, b"abc") - self.assertEqual(type(x.a), bytes) - - def test_struct_W(self): - class X(Structure): - _fields_ = [("a", c_wchar * 3)] - - x = X("abc") - self.assertRaises(TypeError, X, b"abc") - self.assertEqual(x.a, "abc") - self.assertEqual(type(x.a), str) - - @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') - def test_BSTR(self): - from _ctypes import _SimpleCData - class BSTR(_SimpleCData): - _type_ = "X" - - BSTR("abc") - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/ctypes/test/test_byteswap.py b/Lib/ctypes/test/test_byteswap.py index 01c97e8..d36402b 100644 --- a/Lib/ctypes/test/test_byteswap.py +++ b/Lib/ctypes/test/test_byteswap.py @@ -4,7 +4,7 @@ from binascii import hexlify from ctypes import * def bin(s): - return hexlify(memoryview(s)).decode().upper() + return hexlify(memoryview(s)).upper() # Each *simple* type that supports different byte orders has an # __ctype_be__ attribute that specifies the same type in BIG ENDIAN @@ -16,32 +16,12 @@ def bin(s): class Test(unittest.TestCase): @unittest.skip('test disabled') def test_X(self): - print(sys.byteorder, file=sys.stderr) + print >> sys.stderr, sys.byteorder for i in range(32): bits = BITS() setattr(bits, "i%s" % i, 1) dump(bits) - def test_slots(self): - class BigPoint(BigEndianStructure): - __slots__ = () - _fields_ = [("x", c_int), ("y", c_int)] - - class LowPoint(LittleEndianStructure): - __slots__ = () - _fields_ = [("x", c_int), ("y", c_int)] - - big = BigPoint() - little = LowPoint() - big.x = 4 - big.y = 2 - little.x = 2 - little.y = 4 - with self.assertRaises(AttributeError): - big.z = 42 - with self.assertRaises(AttributeError): - little.z = 24 - def test_endian_short(self): if sys.byteorder == "little": self.assertIs(c_short.__ctype_le__, c_short) @@ -135,12 +115,12 @@ class Test(unittest.TestCase): s = c_float(math.pi) self.assertEqual(bin(struct.pack("f", math.pi)), bin(s)) # Hm, what's the precision of a float compared to a double? - self.assertAlmostEqual(s.value, math.pi, places=6) + self.assertAlmostEqual(s.value, math.pi, 6) s = c_float.__ctype_le__(math.pi) - self.assertAlmostEqual(s.value, math.pi, places=6) + self.assertAlmostEqual(s.value, math.pi, 6) self.assertEqual(bin(struct.pack("<f", math.pi)), bin(s)) s = c_float.__ctype_be__(math.pi) - self.assertAlmostEqual(s.value, math.pi, places=6) + self.assertAlmostEqual(s.value, math.pi, 6) self.assertEqual(bin(struct.pack(">f", math.pi)), bin(s)) def test_endian_double(self): diff --git a/Lib/ctypes/test/test_callbacks.py b/Lib/ctypes/test/test_callbacks.py index f622093..db3d9e7 100644 --- a/Lib/ctypes/test/test_callbacks.py +++ b/Lib/ctypes/test/test_callbacks.py @@ -16,7 +16,7 @@ class Callbacks(unittest.TestCase): return args[-1] def check_type(self, typ, arg): - PROTO = self.functype.__func__(typ, typ) + PROTO = self.functype.im_func(typ, typ) result = PROTO(self.callback)(arg) if typ == c_float: self.assertAlmostEqual(result, arg, places=5) @@ -24,7 +24,7 @@ class Callbacks(unittest.TestCase): self.assertEqual(self.got_args, (arg,)) self.assertEqual(result, arg) - PROTO = self.functype.__func__(typ, c_byte, typ) + PROTO = self.functype.im_func(typ, c_byte, typ) result = PROTO(self.callback)(-3, arg) if typ == c_float: self.assertAlmostEqual(result, arg, places=5) @@ -63,10 +63,16 @@ class Callbacks(unittest.TestCase): self.check_type(c_ulong, 42) def test_longlong(self): + # test some 64-bit values, positive and negative + self.check_type(c_longlong, 5948291757245277467) + self.check_type(c_longlong, -5229388909784190580) self.check_type(c_longlong, 42) self.check_type(c_longlong, -42) def test_ulonglong(self): + # test some 64-bit values, with and without msb set. + self.check_type(c_ulonglong, 10955412242170339782) + self.check_type(c_ulonglong, 3665885499841167458) self.check_type(c_ulonglong, 42) def test_float(self): @@ -84,8 +90,8 @@ class Callbacks(unittest.TestCase): self.check_type(c_longdouble, -3.14) def test_char(self): - self.check_type(c_char, b"x") - self.check_type(c_char, b"a") + self.check_type(c_char, "x") + self.check_type(c_char, "a") # disabled: would now (correctly) raise a RuntimeWarning about # a memory leak. A callback function cannot return a non-integral @@ -113,16 +119,16 @@ class Callbacks(unittest.TestCase): # functions, the type must have a non-NULL stgdict->setfunc. # POINTER(c_double), for example, is not supported. - prototype = self.functype.__func__(POINTER(c_double)) + prototype = self.functype.im_func(POINTER(c_double)) # The type is checked when the prototype is called self.assertRaises(TypeError, prototype, lambda: None) def test_unsupported_restype_2(self): - prototype = self.functype.__func__(object) + prototype = self.functype.im_func(object) self.assertRaises(TypeError, prototype, lambda: None) def test_issue_7959(self): - proto = self.functype.__func__(None) + proto = self.functype.im_func(None) class X(object): def func(self): pass diff --git a/Lib/ctypes/test/test_cast.py b/Lib/ctypes/test/test_cast.py index 6878f97..d24e0b5 100644 --- a/Lib/ctypes/test/test_cast.py +++ b/Lib/ctypes/test/test_cast.py @@ -34,18 +34,18 @@ class Test(unittest.TestCase): def test_p2a_objects(self): array = (c_char_p * 5)() self.assertEqual(array._objects, None) - array[0] = b"foo bar" - self.assertEqual(array._objects, {'0': b"foo bar"}) + array[0] = "foo bar" + self.assertEqual(array._objects, {'0': "foo bar"}) p = cast(array, POINTER(c_char_p)) # array and p share a common _objects attribute self.assertIs(p._objects, array._objects) - self.assertEqual(array._objects, {'0': b"foo bar", id(array): array}) - p[0] = b"spam spam" - self.assertEqual(p._objects, {'0': b"spam spam", id(array): array}) + self.assertEqual(array._objects, {'0': "foo bar", id(array): array}) + p[0] = "spam spam" + self.assertEqual(p._objects, {'0': "spam spam", id(array): array}) self.assertIs(array._objects, p._objects) - p[1] = b"foo bar" - self.assertEqual(p._objects, {'1': b'foo bar', '0': b"spam spam", id(array): array}) + p[1] = "foo bar" + self.assertEqual(p._objects, {'1': 'foo bar', '0': "spam spam", id(array): array}) self.assertIs(array._objects, p._objects) def test_other(self): @@ -72,9 +72,9 @@ class Test(unittest.TestCase): def test_char_p(self): # This didn't work: bad argument to internal function - s = c_char_p(b"hiho") + s = c_char_p("hiho") self.assertEqual(cast(cast(s, c_void_p), c_char_p).value, - b"hiho") + "hiho") @need_symbol('c_wchar_p') def test_wchar_p(self): @@ -82,18 +82,5 @@ class Test(unittest.TestCase): self.assertEqual(cast(cast(s, c_void_p), c_wchar_p).value, "hiho") - def test_bad_type_arg(self): - # The type argument must be a ctypes pointer type. - array_type = c_byte * sizeof(c_int) - array = array_type() - self.assertRaises(TypeError, cast, array, None) - self.assertRaises(TypeError, cast, array, array_type) - class Struct(Structure): - _fields_ = [("a", c_int)] - self.assertRaises(TypeError, cast, array, Struct) - class MyUnion(Union): - _fields_ = [("a", c_int)] - self.assertRaises(TypeError, cast, array, MyUnion) - if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_cfuncs.py b/Lib/ctypes/test/test_cfuncs.py index ac2240f..765408c 100644 --- a/Lib/ctypes/test/test_cfuncs.py +++ b/Lib/ctypes/test/test_cfuncs.py @@ -108,7 +108,7 @@ class CFunctions(unittest.TestCase): def test_ulong_plus(self): self._dll.tf_bL.restype = c_ulong self._dll.tf_bL.argtypes = (c_char, c_ulong) - self.assertEqual(self._dll.tf_bL(b' ', 4294967295), 1431655765) + self.assertEqual(self._dll.tf_bL(' ', 4294967295), 1431655765) self.assertEqual(self.U(), 4294967295) def test_longlong(self): diff --git a/Lib/ctypes/test/test_checkretval.py b/Lib/ctypes/test/test_checkretval.py index e9567dc..a0dc534 100644 --- a/Lib/ctypes/test/test_checkretval.py +++ b/Lib/ctypes/test/test_checkretval.py @@ -28,7 +28,7 @@ class Test(unittest.TestCase): @need_symbol('oledll') def test_oledll(self): - self.assertRaises(OSError, + self.assertRaises(WindowsError, oledll.oleaut32.CreateTypeLib2, 0, None, None) diff --git a/Lib/ctypes/test/test_errno.py b/Lib/ctypes/test/test_errno.py index 3685164..c7a5bf0 100644 --- a/Lib/ctypes/test/test_errno.py +++ b/Lib/ctypes/test/test_errno.py @@ -1,8 +1,11 @@ import unittest, os, errno -import threading - from ctypes import * from ctypes.util import find_library +from test import test_support +try: + import threading +except ImportError: + threading = None class Test(unittest.TestCase): def test_open(self): @@ -17,30 +20,31 @@ class Test(unittest.TestCase): libc_open.argtypes = c_char_p, c_int - self.assertEqual(libc_open(b"", 0), -1) + self.assertEqual(libc_open("", 0), -1) self.assertEqual(get_errno(), errno.ENOENT) self.assertEqual(set_errno(32), errno.ENOENT) self.assertEqual(get_errno(), 32) - def _worker(): - set_errno(0) + if threading: + def _worker(): + set_errno(0) - libc = CDLL(libc_name, use_errno=False) - if os.name == "nt": - libc_open = libc._open - else: - libc_open = libc.open - libc_open.argtypes = c_char_p, c_int - self.assertEqual(libc_open(b"", 0), -1) - self.assertEqual(get_errno(), 0) + libc = CDLL(libc_name, use_errno=False) + if os.name == "nt": + libc_open = libc._open + else: + libc_open = libc.open + libc_open.argtypes = c_char_p, c_int + self.assertEqual(libc_open("", 0), -1) + self.assertEqual(get_errno(), 0) - t = threading.Thread(target=_worker) - t.start() - t.join() + t = threading.Thread(target=_worker) + t.start() + t.join() - self.assertEqual(get_errno(), 32) - set_errno(0) + self.assertEqual(get_errno(), 32) + set_errno(0) @unittest.skipUnless(os.name == "nt", 'Test specific to Windows') def test_GetLastError(self): diff --git a/Lib/ctypes/test/test_find.py b/Lib/ctypes/test/test_find.py index b99fdcb..c10d441 100644 --- a/Lib/ctypes/test/test_find.py +++ b/Lib/ctypes/test/test_find.py @@ -1,116 +1,75 @@ import unittest import os.path import sys -import test.support +from test import test_support from ctypes import * from ctypes.util import find_library +from ctypes.test import is_resource_enabled -# On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode. -class Test_OpenGL_libs(unittest.TestCase): - @classmethod - def setUpClass(cls): - lib_gl = lib_glu = lib_gle = None - if sys.platform == "win32": - lib_gl = find_library("OpenGL32") - lib_glu = find_library("Glu32") - elif sys.platform == "darwin": - lib_gl = lib_glu = find_library("OpenGL") - else: - lib_gl = find_library("GL") - lib_glu = find_library("GLU") - lib_gle = find_library("gle") +if sys.platform == "win32": + lib_gl = find_library("OpenGL32") + lib_glu = find_library("Glu32") + lib_gle = None +elif sys.platform == "darwin": + lib_gl = lib_glu = find_library("OpenGL") + lib_gle = None +else: + lib_gl = find_library("GL") + lib_glu = find_library("GLU") + lib_gle = find_library("gle") + +## print, for debugging +if is_resource_enabled("printing"): + if lib_gl or lib_glu or lib_gle: + print "OpenGL libraries:" + for item in (("GL", lib_gl), + ("GLU", lib_glu), + ("gle", lib_gle)): + print "\t", item - ## print, for debugging - if test.support.verbose: - print("OpenGL libraries:") - for item in (("GL", lib_gl), - ("GLU", lib_glu), - ("gle", lib_gle)): - print("\t", item) - cls.gl = cls.glu = cls.gle = None +# On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode. +class Test_OpenGL_libs(unittest.TestCase): + def setUp(self): + self.gl = self.glu = self.gle = None if lib_gl: try: - cls.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) + self.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) except OSError: pass if lib_glu: try: - cls.glu = CDLL(lib_glu, RTLD_GLOBAL) + self.glu = CDLL(lib_glu, RTLD_GLOBAL) except OSError: pass if lib_gle: try: - cls.gle = CDLL(lib_gle) + self.gle = CDLL(lib_gle) except OSError: pass - @classmethod - def tearDownClass(cls): - cls.gl = cls.glu = cls.gle = None + def tearDown(self): + self.gl = self.glu = self.gle = None + @unittest.skipUnless(lib_gl, 'lib_gl not available') def test_gl(self): - if self.gl is None: - self.skipTest('lib_gl not available') - self.gl.glClearIndex + if self.gl: + self.gl.glClearIndex + @unittest.skipUnless(lib_glu, 'lib_glu not available') def test_glu(self): - if self.glu is None: - self.skipTest('lib_glu not available') - self.glu.gluBeginCurve + if self.glu: + self.glu.gluBeginCurve + @unittest.skipUnless(lib_gle, 'lib_gle not available') def test_gle(self): - if self.gle is None: - self.skipTest('lib_gle not available') - self.gle.gleGetJoinStyle + if self.gle: + self.gle.gleGetJoinStyle def test_shell_injection(self): - result = find_library('; echo Hello shell > ' + test.support.TESTFN) - self.assertFalse(os.path.lexists(test.support.TESTFN)) + result = find_library('; echo Hello shell > ' + test_support.TESTFN) + self.assertFalse(os.path.lexists(test_support.TESTFN)) self.assertIsNone(result) - -@unittest.skipUnless(sys.platform.startswith('linux'), - 'Test only valid for Linux') -class LibPathFindTest(unittest.TestCase): - def test_find_on_libpath(self): - import subprocess - import tempfile - - try: - p = subprocess.Popen(['gcc', '--version'], stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL) - out, _ = p.communicate() - except OSError: - raise unittest.SkipTest('gcc, needed for test, not available') - with tempfile.TemporaryDirectory() as d: - # create an empty temporary file - srcname = os.path.join(d, 'dummy.c') - libname = 'py_ctypes_test_dummy' - dstname = os.path.join(d, 'lib%s.so' % libname) - with open(srcname, 'w') as f: - pass - self.assertTrue(os.path.exists(srcname)) - # compile the file to a shared library - cmd = ['gcc', '-o', dstname, '--shared', - '-Wl,-soname,lib%s.so' % libname, srcname] - out = subprocess.check_output(cmd) - self.assertTrue(os.path.exists(dstname)) - # now check that the .so can't be found (since not in - # LD_LIBRARY_PATH) - self.assertIsNone(find_library(libname)) - # now add the location to LD_LIBRARY_PATH - with test.support.EnvironmentVarGuard() as env: - KEY = 'LD_LIBRARY_PATH' - if KEY not in env: - v = d - else: - v = '%s:%s' % (env[KEY], d) - env.set(KEY, v) - # now check that the .so can be found (since in - # LD_LIBRARY_PATH) - self.assertEqual(find_library(libname), 'lib%s.so' % libname) - - if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_frombuffer.py b/Lib/ctypes/test/test_frombuffer.py index 55c2443..99c32e0 100644 --- a/Lib/ctypes/test/test_frombuffer.py +++ b/Lib/ctypes/test/test_frombuffer.py @@ -10,7 +10,7 @@ class X(Structure): self._init_called = True class Test(unittest.TestCase): - def test_from_buffer(self): + def test_fom_buffer(self): a = array.array("i", range(16)) x = (c_int * 16).from_buffer(a) @@ -23,64 +23,25 @@ class Test(unittest.TestCase): a[0], a[-1] = 200, -200 self.assertEqual(x[:], a.tolist()) - self.assertRaises(BufferError, a.append, 100) - self.assertRaises(BufferError, a.pop) + self.assertIn(a, x._objects.values()) - del x; del y; gc.collect(); gc.collect(); gc.collect() - a.append(100) - a.pop() - x = (c_int * 16).from_buffer(a) - - self.assertIn(a, [obj.obj if isinstance(obj, memoryview) else obj - for obj in x._objects.values()]) + self.assertRaises(ValueError, + c_int.from_buffer, a, -1) expected = x[:] del a; gc.collect(); gc.collect(); gc.collect() self.assertEqual(x[:], expected) - with self.assertRaisesRegex(TypeError, "not writable"): - (c_char * 16).from_buffer(b"a" * 16) - with self.assertRaisesRegex(TypeError, "not writable"): - (c_char * 16).from_buffer(memoryview(b"a" * 16)) - with self.assertRaisesRegex(TypeError, "not C contiguous"): - (c_char * 16).from_buffer(memoryview(bytearray(b"a" * 16))[::-1]) - msg = "bytes-like object is required" - with self.assertRaisesRegex(TypeError, msg): - (c_char * 16).from_buffer("a" * 16) - - def test_fortran_contiguous(self): - try: - import _testbuffer - except ImportError as err: - self.skipTest(str(err)) - flags = _testbuffer.ND_WRITABLE | _testbuffer.ND_FORTRAN - array = _testbuffer.ndarray( - [97] * 16, format="B", shape=[4, 4], flags=flags) - with self.assertRaisesRegex(TypeError, "not C contiguous"): - (c_char * 16).from_buffer(array) - array = memoryview(array) - self.assertTrue(array.f_contiguous) - self.assertFalse(array.c_contiguous) - with self.assertRaisesRegex(TypeError, "not C contiguous"): - (c_char * 16).from_buffer(array) - - def test_from_buffer_with_offset(self): + self.assertRaises(TypeError, + (c_char * 16).from_buffer, "a" * 16) + + def test_fom_buffer_with_offset(self): a = array.array("i", range(16)) x = (c_int * 15).from_buffer(a, sizeof(c_int)) self.assertEqual(x[:], a.tolist()[1:]) - with self.assertRaises(ValueError): - c_int.from_buffer(a, -1) - with self.assertRaises(ValueError): - (c_int * 16).from_buffer(a, sizeof(c_int)) - with self.assertRaises(ValueError): - (c_int * 1).from_buffer(a, 16 * sizeof(c_int)) - - def test_from_buffer_memoryview(self): - a = [c_char.from_buffer(memoryview(bytearray(b'a')))] - a.append(a) - del a - gc.collect() # Should not crash + self.assertRaises(ValueError, lambda: (c_int * 16).from_buffer(a, sizeof(c_int))) + self.assertRaises(ValueError, lambda: (c_int * 1).from_buffer(a, 16 * sizeof(c_int))) def test_from_buffer_copy(self): a = array.array("i", range(16)) @@ -90,35 +51,31 @@ class Test(unittest.TestCase): self.assertEqual(y.c_int, a[0]) self.assertFalse(y.init_called) - self.assertEqual(x[:], list(range(16))) + self.assertEqual(x[:], range(16)) a[0], a[-1] = 200, -200 - self.assertEqual(x[:], list(range(16))) - - a.append(100) - self.assertEqual(x[:], list(range(16))) + self.assertEqual(x[:], range(16)) self.assertEqual(x._objects, None) + self.assertRaises(ValueError, + c_int.from_buffer, a, -1) + del a; gc.collect(); gc.collect(); gc.collect() - self.assertEqual(x[:], list(range(16))) + self.assertEqual(x[:], range(16)) - x = (c_char * 16).from_buffer_copy(b"a" * 16) - self.assertEqual(x[:], b"a" * 16) - with self.assertRaises(TypeError): - (c_char * 16).from_buffer_copy("a" * 16) + x = (c_char * 16).from_buffer_copy("a" * 16) + self.assertEqual(x[:], "a" * 16) - def test_from_buffer_copy_with_offset(self): + def test_fom_buffer_copy_with_offset(self): a = array.array("i", range(16)) x = (c_int * 15).from_buffer_copy(a, sizeof(c_int)) self.assertEqual(x[:], a.tolist()[1:]) - with self.assertRaises(ValueError): - c_int.from_buffer_copy(a, -1) - with self.assertRaises(ValueError): - (c_int * 16).from_buffer_copy(a, sizeof(c_int)) - with self.assertRaises(ValueError): - (c_int * 1).from_buffer_copy(a, 16 * sizeof(c_int)) + self.assertRaises(ValueError, + (c_int * 16).from_buffer_copy, a, sizeof(c_int)) + self.assertRaises(ValueError, + (c_int * 1).from_buffer_copy, a, 16 * sizeof(c_int)) def test_abstract(self): from ctypes import _Pointer, _SimpleCData, _CFuncPtr diff --git a/Lib/ctypes/test/test_funcptr.py b/Lib/ctypes/test/test_funcptr.py index e0b9b54..5750303 100644 --- a/Lib/ctypes/test/test_funcptr.py +++ b/Lib/ctypes/test/test_funcptr.py @@ -1,4 +1,4 @@ -import unittest +import os, unittest from ctypes import * try: @@ -39,7 +39,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 not WINFUNCTYPE is CFUNCTYPE and os.name != "ce": self.assertRaises(TypeError, s, 1, 2, 3) def test_structures(self): @@ -97,8 +97,8 @@ class CFuncPtrTestCase(unittest.TestCase): strchr = lib.my_strchr strchr.restype = c_char_p strchr.argtypes = (c_char_p, c_char) - self.assertEqual(strchr(b"abcdefghi", b"b"), b"bcdefghi") - self.assertEqual(strchr(b"abcdefghi", b"x"), None) + self.assertEqual(strchr("abcdefghi", "b"), "bcdefghi") + self.assertEqual(strchr("abcdefghi", "x"), None) strtok = lib.my_strtok @@ -111,17 +111,17 @@ class CFuncPtrTestCase(unittest.TestCase): size = len(init) + 1 return (c_char*size)(*init) - s = b"a\nb\nc" + s = "a\nb\nc" b = c_string(s) ## b = (c_char * (len(s)+1))() ## b.value = s ## b = c_string(s) - self.assertEqual(strtok(b, b"\n"), b"a") - self.assertEqual(strtok(None, b"\n"), b"b") - self.assertEqual(strtok(None, b"\n"), b"c") - self.assertEqual(strtok(None, b"\n"), None) + self.assertEqual(strtok(b, "\n"), "a") + self.assertEqual(strtok(None, "\n"), "b") + self.assertEqual(strtok(None, "\n"), "c") + self.assertEqual(strtok(None, "\n"), None) def test_abstract(self): from ctypes import _CFuncPtr diff --git a/Lib/ctypes/test/test_functions.py b/Lib/ctypes/test/test_functions.py index 7562892..a374415 100644 --- a/Lib/ctypes/test/test_functions.py +++ b/Lib/ctypes/test/test_functions.py @@ -68,7 +68,7 @@ class FunctionTestCase(unittest.TestCase): def test_wchar_parm(self): f = dll._testfunc_i_bhilfd f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double] - result = f(1, "x", 3, 4, 5.0, 6.0) + result = f(1, u"x", 3, 4, 5.0, 6.0) self.assertEqual(result, 139) self.assertEqual(type(result), int) @@ -78,7 +78,7 @@ class FunctionTestCase(unittest.TestCase): f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double] f.restype = c_wchar result = f(0, 0, 0, 0, 0, 0) - self.assertEqual(result, '\x00') + self.assertEqual(result, u'\x00') def test_voidresult(self): f = dll._testfunc_v @@ -168,8 +168,8 @@ class FunctionTestCase(unittest.TestCase): f = dll._testfunc_p_p f.argtypes = None f.restype = c_char_p - result = f(b"123") - self.assertEqual(result, b"123") + result = f("123") + self.assertEqual(result, "123") result = f(None) self.assertEqual(result, None) @@ -299,7 +299,7 @@ class FunctionTestCase(unittest.TestCase): f.argtypes = [c_longlong, MyCallback] def callback(value): - self.assertIsInstance(value, int) + self.assertIsInstance(value, (int, long)) return value & 0x7FFFFFFF cb = MyCallback(callback) diff --git a/Lib/ctypes/test/test_incomplete.py b/Lib/ctypes/test/test_incomplete.py index 00c430e..1e03e9f 100644 --- a/Lib/ctypes/test/test_incomplete.py +++ b/Lib/ctypes/test/test_incomplete.py @@ -17,9 +17,9 @@ class MyTestCase(unittest.TestCase): SetPointerType(lpcell, cell) c1 = cell() - c1.name = b"foo" + c1.name = "foo" c2 = cell() - c2.name = b"bar" + c2.name = "bar" c1.next = pointer(c2) c2.next = pointer(c1) @@ -30,7 +30,7 @@ class MyTestCase(unittest.TestCase): for i in range(8): result.append(p.name) p = p.next[0] - self.assertEqual(result, [b"foo", b"bar"] * 4) + self.assertEqual(result, ["foo", "bar"] * 4) # to not leak references, we must clean _pointer_type_cache from ctypes import _pointer_type_cache diff --git a/Lib/ctypes/test/test_init.py b/Lib/ctypes/test/test_init.py index 75fad11..82bd1f9 100644 --- a/Lib/ctypes/test/test_init.py +++ b/Lib/ctypes/test/test_init.py @@ -7,7 +7,7 @@ class X(Structure): new_was_called = False def __new__(cls): - result = super().__new__(cls) + result = super(X, cls).__new__(cls) result.new_was_called = True return result diff --git a/Lib/ctypes/test/test_internals.py b/Lib/ctypes/test/test_internals.py index 271e3f5..2e5b1fe 100644 --- a/Lib/ctypes/test/test_internals.py +++ b/Lib/ctypes/test/test_internals.py @@ -5,14 +5,17 @@ from sys import getrefcount as grc # XXX This test must be reviewed for correctness!!! -# ctypes' types are container types. -# -# They have an internal memory block, which only consists of some bytes, -# but it has to keep references to other objects as well. This is not -# really needed for trivial C types like int or char, but it is important -# for aggregate types like strings or pointers in particular. -# -# What about pointers? +""" +ctypes' types are container types. + +They have an internal memory block, which only consists of some bytes, +but it has to keep references to other objects as well. This is not +really needed for trivial C types like int or char, but it is important +for aggregate types like strings or pointers in particular. + +What about pointers? + +""" class ObjectsTestCase(unittest.TestCase): def assertSame(self, a, b): @@ -26,7 +29,7 @@ class ObjectsTestCase(unittest.TestCase): self.assertEqual(ci._objects, None) def test_c_char_p(self): - s = b"Hello, World" + s = "Hello, World" refcnt = grc(s) cs = c_char_p(s) self.assertEqual(refcnt + 1, grc(s)) @@ -67,8 +70,8 @@ class ObjectsTestCase(unittest.TestCase): class Y(Structure): _fields_ = [("x", X), ("y", X)] - s1 = b"Hello, World" - s2 = b"Hallo, Welt" + s1 = "Hello, World" + s2 = "Hallo, Welt" x = X() x.a = s1 diff --git a/Lib/ctypes/test/test_keeprefs.py b/Lib/ctypes/test/test_keeprefs.py index 94c0257..b2a50ab 100644 --- a/Lib/ctypes/test/test_keeprefs.py +++ b/Lib/ctypes/test/test_keeprefs.py @@ -13,10 +13,10 @@ class SimpleTestCase(unittest.TestCase): def test_ccharp(self): x = c_char_p() self.assertEqual(x._objects, None) - x.value = b"abc" - self.assertEqual(x._objects, b"abc") - x = c_char_p(b"spam") - self.assertEqual(x._objects, b"spam") + x.value = "abc" + self.assertEqual(x._objects, "abc") + x = c_char_p("spam") + self.assertEqual(x._objects, "spam") class StructureTestCase(unittest.TestCase): def test_cint_struct(self): @@ -37,9 +37,9 @@ class StructureTestCase(unittest.TestCase): x = X() self.assertEqual(x._objects, None) - x.a = b"spam" - x.b = b"foo" - self.assertEqual(x._objects, {"0": b"spam", "1": b"foo"}) + x.a = "spam" + x.b = "foo" + self.assertEqual(x._objects, {"0": "spam", "1": "foo"}) def test_struct_struct(self): class POINT(Structure): @@ -101,13 +101,13 @@ class DeletePointerTestCase(unittest.TestCase): x = X() i = c_char_p("abc def") from sys import getrefcount as grc - print("2?", grc(i)) + print "2?", grc(i) x.p = pointer(i) - print("3?", grc(i)) + print "3?", grc(i) for i in range(320): c_int(99) x.p[0] - print(x.p[0]) + print x.p[0] ## del x ## print "2?", grc(i) ## del i @@ -116,14 +116,14 @@ class DeletePointerTestCase(unittest.TestCase): for i in range(320): c_int(99) x.p[0] - print(x.p[0]) - print(x.p.contents) + print x.p[0] + print x.p.contents ## print x._objects x.p[0] = "spam spam" ## print x.p[0] - print("+" * 42) - print(x._objects) + print "+" * 42 + print x._objects class PointerToStructure(unittest.TestCase): def test(self): diff --git a/Lib/ctypes/test/test_libc.py b/Lib/ctypes/test/test_libc.py index 56285b5..3dc463f 100644 --- a/Lib/ctypes/test/test_libc.py +++ b/Lib/ctypes/test/test_libc.py @@ -5,10 +5,6 @@ import _ctypes_test lib = CDLL(_ctypes_test.__file__) -def three_way_cmp(x, y): - """Return -1 if x < y, 0 if x == y and 1 if x > y""" - return (x > y) - (x < y) - class LibTest(unittest.TestCase): def test_sqrt(self): lib.my_sqrt.argtypes = c_double, @@ -23,11 +19,11 @@ class LibTest(unittest.TestCase): lib.my_qsort.restype = None def sort(a, b): - return three_way_cmp(a[0], b[0]) + return cmp(a[0], b[0]) - chars = create_string_buffer(b"spam, spam, and spam") + chars = create_string_buffer("spam, spam, and spam") lib.my_qsort(chars, len(chars)-1, sizeof(c_char), comparefunc(sort)) - self.assertEqual(chars.raw, b" ,,aaaadmmmnpppsss\x00") + self.assertEqual(chars.raw, " ,,aaaadmmmnpppsss\x00") if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_loading.py b/Lib/ctypes/test/test_loading.py index 9b97d80..e64fff7 100644 --- a/Lib/ctypes/test/test_loading.py +++ b/Lib/ctypes/test/test_loading.py @@ -1,43 +1,44 @@ from ctypes import * +import sys, unittest import os -import shutil -import subprocess -import sys -import sysconfig -import unittest -import test.support from ctypes.util import find_library +from ctypes.test import is_resource_enabled +import test.test_support as support libc_name = None - -def setUpModule(): - global libc_name - if os.name == "nt": - libc_name = find_library("c") - elif sys.platform == "cygwin": - libc_name = "cygwin1.dll" - else: - libc_name = find_library("c") - - if test.support.verbose: - print("libc_name is", libc_name) +if os.name == "nt": + libc_name = find_library("c") +elif os.name == "ce": + libc_name = "coredll" +elif sys.platform == "cygwin": + libc_name = "cygwin1.dll" +else: + libc_name = find_library("c") + +if is_resource_enabled("printing"): + print "libc_name is", libc_name class LoaderTest(unittest.TestCase): unknowndll = "xxrandomnamexx" + @unittest.skipUnless(libc_name is not None, 'could not find libc') def test_load(self): - if libc_name is None: - self.skipTest('could not find libc') CDLL(libc_name) CDLL(os.path.basename(libc_name)) self.assertRaises(OSError, CDLL, self.unknowndll) + @support.requires_unicode + @unittest.skipUnless(libc_name is not None, 'could not find libc') + def test_load_unicode(self): + CDLL(unicode(libc_name)) + self.assertRaises(OSError, CDLL, unicode(self.unknowndll)) + + @unittest.skipUnless(libc_name is not None, 'could not find libc') + @unittest.skipUnless(libc_name is not None and + os.path.basename(libc_name) == "libc.so.6", + 'wrong libc path for test') def test_load_version(self): - if libc_name is None: - self.skipTest('could not find libc') - if os.path.basename(libc_name) != 'libc.so.6': - self.skipTest('wrong libc path for test') cdll.LoadLibrary("libc.so.6") # linux uses version, libc 9 should not exist self.assertRaises(OSError, cdll.LoadLibrary, "libc.so.9") @@ -50,26 +51,27 @@ class LoaderTest(unittest.TestCase): cdll.LoadLibrary(lib) CDLL(lib) - @unittest.skipUnless(os.name == "nt", - 'test specific to Windows') + @unittest.skipUnless(os.name in ("nt", "ce"), + 'test specific to Windows (NT/CE)') def test_load_library(self): - # CRT is no longer directly loadable. See issue23606 for the - # discussion about alternative approaches. - #self.assertIsNotNone(libc_name) - if test.support.verbose: - print(find_library("kernel32")) - print(find_library("user32")) + self.assertIsNotNone(libc_name) + if is_resource_enabled("printing"): + print find_library("kernel32") + print find_library("user32") if os.name == "nt": windll.kernel32.GetModuleHandleW windll["kernel32"].GetModuleHandleW windll.LoadLibrary("kernel32").GetModuleHandleW WinDLL("kernel32").GetModuleHandleW - # embedded null character - self.assertRaises(ValueError, windll.LoadLibrary, "kernel32\0") - - @unittest.skipUnless(os.name == "nt", - 'test specific to Windows') + elif os.name == "ce": + windll.coredll.GetModuleHandleW + windll["coredll"].GetModuleHandleW + windll.LoadLibrary("coredll").GetModuleHandleW + WinDLL("coredll").GetModuleHandleW + + @unittest.skipUnless(os.name in ("nt", "ce"), + 'test specific to Windows (NT/CE)') def test_load_ordinal_functions(self): import _ctypes_test dll = WinDLL(_ctypes_test.__file__) @@ -110,71 +112,10 @@ class LoaderTest(unittest.TestCase): 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") + "CloseEventLog") self.assertTrue(proc) # This is the real test: call the function via 'call_function' self.assertEqual(0, call_function(proc, (None,))) - @unittest.skipUnless(os.name == "nt", - 'test specific to Windows') - def test_load_dll_with_flags(self): - _sqlite3 = test.support.import_module("_sqlite3") - src = _sqlite3.__file__ - if src.lower().endswith("_d.pyd"): - ext = "_d.dll" - else: - ext = ".dll" - - with test.support.temp_dir() as tmp: - # We copy two files and load _sqlite3.dll (formerly .pyd), - # which has a dependency on sqlite3.dll. Then we test - # loading it in subprocesses to avoid it starting in memory - # for each test. - target = os.path.join(tmp, "_sqlite3.dll") - shutil.copy(src, target) - shutil.copy(os.path.join(os.path.dirname(src), "sqlite3" + ext), - os.path.join(tmp, "sqlite3" + ext)) - - def should_pass(command): - with self.subTest(command): - subprocess.check_output( - [sys.executable, "-c", - "from ctypes import *; import nt;" + command], - cwd=tmp - ) - - def should_fail(command): - with self.subTest(command): - with self.assertRaises(subprocess.CalledProcessError): - subprocess.check_output( - [sys.executable, "-c", - "from ctypes import *; import nt;" + command], - cwd=tmp, stderr=subprocess.STDOUT, - ) - - # Default load should not find this in CWD - should_fail("WinDLL('_sqlite3.dll')") - - # Relative path (but not just filename) should succeed - should_pass("WinDLL('./_sqlite3.dll')") - - # Insecure load flags should succeed - should_pass("WinDLL('_sqlite3.dll', winmode=0)") - - # Full path load without DLL_LOAD_DIR shouldn't find dependency - should_fail("WinDLL(nt._getfullpathname('_sqlite3.dll'), " + - "winmode=nt._LOAD_LIBRARY_SEARCH_SYSTEM32)") - - # Full path load with DLL_LOAD_DIR should succeed - should_pass("WinDLL(nt._getfullpathname('_sqlite3.dll'), " + - "winmode=nt._LOAD_LIBRARY_SEARCH_SYSTEM32|" + - "nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)") - - # User-specified directory should succeed - should_pass("import os; p = os.add_dll_directory(os.getcwd());" + - "WinDLL('_sqlite3.dll'); p.close()") - - - if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_macholib.py b/Lib/ctypes/test/test_macholib.py index 6b35269..9779b2f 100644 --- a/Lib/ctypes/test/test_macholib.py +++ b/Lib/ctypes/test/test_macholib.py @@ -3,33 +3,35 @@ import sys import unittest # Bob Ippolito: -# -# Ok.. the code to find the filename for __getattr__ should look -# something like: -# -# import os -# from macholib.dyld import dyld_find -# -# def find_lib(name): -# possible = ['lib'+name+'.dylib', name+'.dylib', -# name+'.framework/'+name] -# for dylib in possible: -# try: -# return os.path.realpath(dyld_find(dylib)) -# except ValueError: -# pass -# raise ValueError, "%s not found" % (name,) -# -# It'll have output like this: -# -# >>> find_lib('pthread') -# '/usr/lib/libSystem.B.dylib' -# >>> find_lib('z') -# '/usr/lib/libz.1.dylib' -# >>> find_lib('IOKit') -# '/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit' -# -# -bob +""" +Ok.. the code to find the filename for __getattr__ should look +something like: + +import os +from macholib.dyld import dyld_find + +def find_lib(name): + possible = ['lib'+name+'.dylib', name+'.dylib', + name+'.framework/'+name] + for dylib in possible: + try: + return os.path.realpath(dyld_find(dylib)) + except ValueError: + pass + raise ValueError, "%s not found" % (name,) + +It'll have output like this: + + >>> find_lib('pthread') +'/usr/lib/libSystem.B.dylib' + >>> find_lib('z') +'/usr/lib/libz.1.dylib' + >>> find_lib('IOKit') +'/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit' + +-bob + +""" from ctypes.macholib.dyld import dyld_find @@ -54,7 +56,7 @@ class MachOTest(unittest.TestCase): # /usr/local/lib before /usr/lib, which caused test failures if # a local copy of libz exists in one of them. Now ignore the head # of the path. - self.assertRegex(result, r".*/lib/libz\..*.*\.dylib") + self.assertRegexpMatches(result, r".*/lib/libz\..*.*\.dylib") self.assertEqual(find_lib('IOKit'), '/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit') diff --git a/Lib/ctypes/test/test_memfunctions.py b/Lib/ctypes/test/test_memfunctions.py index e784b9a..ba9eea6 100644 --- a/Lib/ctypes/test/test_memfunctions.py +++ b/Lib/ctypes/test/test_memfunctions.py @@ -1,5 +1,4 @@ import sys -from test import support import unittest from ctypes import * from ctypes.test import need_symbol @@ -20,27 +19,27 @@ class MemFunctionsTest(unittest.TestCase): # large buffers apparently increase the chance that the memory # is allocated in high address space. a = create_string_buffer(1000000) - p = b"Hello, World" + p = "Hello, World" result = memmove(a, p, len(p)) - self.assertEqual(a.value, b"Hello, World") + self.assertEqual(a.value, "Hello, World") - self.assertEqual(string_at(result), b"Hello, World") - self.assertEqual(string_at(result, 5), b"Hello") - self.assertEqual(string_at(result, 16), b"Hello, World\0\0\0\0") - self.assertEqual(string_at(result, 0), b"") + self.assertEqual(string_at(result), "Hello, World") + self.assertEqual(string_at(result, 5), "Hello") + self.assertEqual(string_at(result, 16), "Hello, World\0\0\0\0") + self.assertEqual(string_at(result, 0), "") def test_memset(self): a = create_string_buffer(1000000) result = memset(a, ord('x'), 16) - self.assertEqual(a.value, b"xxxxxxxxxxxxxxxx") + self.assertEqual(a.value, "xxxxxxxxxxxxxxxx") - self.assertEqual(string_at(result), b"xxxxxxxxxxxxxxxx") - self.assertEqual(string_at(a), b"xxxxxxxxxxxxxxxx") - self.assertEqual(string_at(a, 20), b"xxxxxxxxxxxxxxxx\0\0\0\0") + self.assertEqual(string_at(result), "xxxxxxxxxxxxxxxx") + self.assertEqual(string_at(a), "xxxxxxxxxxxxxxxx") + self.assertEqual(string_at(a, 20), "xxxxxxxxxxxxxxxx\0\0\0\0") def test_cast(self): a = (c_ubyte * 32)(*map(ord, "abcdef")) - self.assertEqual(cast(a, c_char_p).value, b"abcdef") + self.assertEqual(cast(a, c_char_p).value, "abcdef") self.assertEqual(cast(a, POINTER(c_byte))[:7], [97, 98, 99, 100, 101, 102, 0]) self.assertEqual(cast(a, POINTER(c_byte))[:7:], @@ -52,16 +51,15 @@ class MemFunctionsTest(unittest.TestCase): self.assertEqual(cast(a, POINTER(c_byte))[:7:7], [97]) - @support.refcount_test def test_string_at(self): - s = string_at(b"foo bar") + s = string_at("foo bar") # XXX The following may be wrong, depending on how Python # manages string instances self.assertEqual(2, sys.getrefcount(s)) self.assertTrue(s, "foo bar") - self.assertEqual(string_at(b"foo bar", 7), b"foo bar") - self.assertEqual(string_at(b"foo bar", 3), b"foo") + self.assertEqual(string_at("foo bar", 8), "foo bar\0") + self.assertEqual(string_at("foo bar", 3), "foo") @need_symbol('create_unicode_buffer') def test_wstring_at(self): diff --git a/Lib/ctypes/test/test_numbers.py b/Lib/ctypes/test/test_numbers.py index c6d843b..ec42e96 100644 --- a/Lib/ctypes/test/test_numbers.py +++ b/Lib/ctypes/test/test_numbers.py @@ -12,10 +12,10 @@ def valid_ranges(*types): for t in types: fmt = t._type_ size = struct.calcsize(fmt) - a = struct.unpack(fmt, (b"\x00"*32)[:size])[0] - b = struct.unpack(fmt, (b"\xFF"*32)[:size])[0] - c = struct.unpack(fmt, (b"\x7F"+b"\x00"*32)[:size])[0] - d = struct.unpack(fmt, (b"\x80"+b"\xFF"*32)[:size])[0] + a = struct.unpack(fmt, ("\x00"*32)[:size])[0] + b = struct.unpack(fmt, ("\xFF"*32)[:size])[0] + c = struct.unpack(fmt, ("\x7F"+"\x00"*32)[:size])[0] + d = struct.unpack(fmt, ("\x80"+"\xFF"*32)[:size])[0] result.append((min(a, b, c, d), max(a, b, c, d))) return result @@ -105,7 +105,7 @@ class NumberTestCase(unittest.TestCase): def test_floats(self): # c_float and c_double can be created from - # Python int and float + # Python int, long and float class FloatLike(object): def __float__(self): return 2.0 @@ -113,7 +113,7 @@ class NumberTestCase(unittest.TestCase): for t in float_types: self.assertEqual(t(2.0).value, 2.0) self.assertEqual(t(2).value, 2.0) - self.assertEqual(t(2).value, 2.0) + self.assertEqual(t(2L).value, 2.0) self.assertEqual(t(f).value, 2.0) def test_integers(self): @@ -124,18 +124,12 @@ class NumberTestCase(unittest.TestCase): class IntLike(object): def __int__(self): return 2 - d = IntLike() - class IndexLike(object): - def __index__(self): - return 2 - i = IndexLike() + i = IntLike() # integers cannot be constructed from floats, # but from integer-like objects for t in signed_types + unsigned_types: self.assertRaises(TypeError, t, 3.14) self.assertRaises(TypeError, t, f) - with self.assertWarns(DeprecationWarning): - self.assertEqual(t(d).value, 2) self.assertEqual(t(i).value, 2) def test_sizes(self): @@ -197,14 +191,13 @@ class NumberTestCase(unittest.TestCase): from ctypes import c_char from array import array - a = array('b', [0]) - a[0] = ord('x') + a = array('c', 'x') v = c_char.from_address(a.buffer_info()[0]) - self.assertEqual(v.value, b'x') + self.assertEqual(v.value, a[0]) self.assertIs(type(v), c_char) - a[0] = ord('?') - self.assertEqual(v.value, b'?') + a[0] = '?' + self.assertEqual(v.value, a[0]) # array does not support c_bool / 't' @unittest.skip('test disabled') @@ -247,7 +240,7 @@ class c_int_S(_SimpleCData): def run_test(rep, msg, func, arg=None): ## items = [None] * rep items = range(rep) - from time import perf_counter as clock + from time import clock if arg is not None: start = clock() for i in items: @@ -258,7 +251,7 @@ def run_test(rep, msg, func, arg=None): for i in items: func(); func(); func(); func(); func() stop = clock() - print("%15s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))) + print "%15s: %.2f us" % (msg, ((stop-start)*1e6/5/rep)) def check_perf(): # Construct 5 objects diff --git a/Lib/ctypes/test/test_objects.py b/Lib/ctypes/test/test_objects.py index 19e3dc1..a7c5247 100644 --- a/Lib/ctypes/test/test_objects.py +++ b/Lib/ctypes/test/test_objects.py @@ -13,18 +13,18 @@ Here is an array of string pointers: >>> from ctypes import * >>> array = (c_char_p * 5)() ->>> print(array._objects) +>>> print array._objects None >>> The memory block stores pointers to strings, and the strings itself assigned from Python must be kept. ->>> array[4] = b'foo bar' +>>> array[4] = 'foo bar' >>> array._objects -{'4': b'foo bar'} +{'4': 'foo bar'} >>> array[4] -b'foo bar' +'foo bar' >>> It gets more complicated when the ctypes instance itself is contained @@ -34,27 +34,27 @@ in a 'base' object. ... _fields_ = [("x", c_int), ("y", c_int), ("array", c_char_p * 5)] ... >>> x = X() ->>> print(x._objects) +>>> print x._objects None >>> The'array' attribute of the 'x' object shares part of the memory buffer of 'x' ('_b_base_' is either None, or the root object owning the memory block): ->>> print(x.array._b_base_) # doctest: +ELLIPSIS +>>> print x.array._b_base_ # doctest: +ELLIPSIS <ctypes.test.test_objects.X object at 0x...> >>> ->>> x.array[0] = b'spam spam spam' +>>> x.array[0] = 'spam spam spam' >>> x._objects -{'0:2': b'spam spam spam'} +{'0:2': 'spam spam spam'} >>> x.array._b_base_._objects -{'0:2': b'spam spam spam'} +{'0:2': 'spam spam spam'} >>> ''' -import unittest, doctest +import unittest, doctest, sys import ctypes.test.test_objects diff --git a/Lib/ctypes/test/test_parameters.py b/Lib/ctypes/test/test_parameters.py index e4c25fd..23c1b6e 100644 --- a/Lib/ctypes/test/test_parameters.py +++ b/Lib/ctypes/test/test_parameters.py @@ -1,4 +1,4 @@ -import unittest +import unittest, sys from ctypes.test import need_symbol import test.support @@ -21,6 +21,7 @@ class SimpleTypesTestCase(unittest.TestCase): else: set_conversion_mode(*self.prev_conv_mode) + def test_subclasses(self): from ctypes import c_void_p, c_char_p # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new @@ -50,33 +51,37 @@ class SimpleTypesTestCase(unittest.TestCase): # XXX Replace by c_char_p tests def test_cstrings(self): - from ctypes import c_char_p + from ctypes import c_char_p, byref # c_char_p.from_param on a Python String packs the string # into a cparam object - s = b"123" + s = "123" self.assertIs(c_char_p.from_param(s)._obj, s) # new in 0.9.1: convert (encode) unicode to ascii - self.assertEqual(c_char_p.from_param(b"123")._obj, b"123") - self.assertRaises(TypeError, c_char_p.from_param, "123\377") + self.assertEqual(c_char_p.from_param(u"123")._obj, "123") + self.assertRaises(UnicodeEncodeError, c_char_p.from_param, u"123\377") + self.assertRaises(TypeError, c_char_p.from_param, 42) # calling c_char_p.from_param with a c_char_p instance # returns the argument itself: - a = c_char_p(b"123") + a = c_char_p("123") self.assertIs(c_char_p.from_param(a), a) @need_symbol('c_wchar_p') def test_cw_strings(self): - from ctypes import c_wchar_p + from ctypes import byref, c_wchar_p + s = u"123" + if sys.platform == "win32": + self.assertTrue(c_wchar_p.from_param(s)._obj is s) + self.assertRaises(TypeError, c_wchar_p.from_param, 42) - c_wchar_p.from_param("123") + # new in 0.9.1: convert (decode) ascii to unicode + self.assertEqual(c_wchar_p.from_param("123")._obj, u"123") + self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, "123\377") - self.assertRaises(TypeError, c_wchar_p.from_param, 42) - self.assertRaises(TypeError, c_wchar_p.from_param, b"123\377") - - pa = c_wchar_p.from_param(c_wchar_p("123")) + pa = c_wchar_p.from_param(c_wchar_p(u"123")) self.assertEqual(type(pa), c_wchar_p) def test_int_pointers(self): @@ -99,7 +104,7 @@ class SimpleTypesTestCase(unittest.TestCase): def test_byref_pointer(self): # The from_param class method of POINTER(typ) classes accepts what is # returned by byref(obj), it type(obj) == typ - from ctypes import c_short, c_uint, c_int, c_long, POINTER, byref + from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref LPINT = POINTER(c_int) LPINT.from_param(byref(c_int(42))) @@ -197,7 +202,7 @@ class SimpleTypesTestCase(unittest.TestCase): class WorseStruct(Structure): @property def __dict__(self): - 1/0 + 1/0.0 with self.assertRaises(ZeroDivisionError): WorseStruct().__setstate__({}, b'foo') diff --git a/Lib/ctypes/test/test_pep3118.py b/Lib/ctypes/test/test_pep3118.py index 81e8ca7..49a1356 100644 --- a/Lib/ctypes/test/test_pep3118.py +++ b/Lib/ctypes/test/test_pep3118.py @@ -25,17 +25,14 @@ class Test(unittest.TestCase): v = memoryview(ob) try: self.assertEqual(normalize(v.format), normalize(fmt)) - if shape: + if shape is not None: self.assertEqual(len(v), shape[0]) else: self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob)) self.assertEqual(v.itemsize, sizeof(itemtp)) self.assertEqual(v.shape, shape) - # XXX Issue #12851: PyCData_NewGetBuffer() must provide strides - # if requested. memoryview currently reconstructs missing - # stride information, so this assert will fail. - # self.assertEqual(v.strides, ()) - + # ctypes object always have a non-strided memory block + self.assertEqual(v.strides, None) # they are always read/write self.assertFalse(v.readonly) @@ -55,15 +52,14 @@ class Test(unittest.TestCase): v = memoryview(ob) try: self.assertEqual(v.format, fmt) - if shape: + if shape is not None: self.assertEqual(len(v), shape[0]) else: self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob)) self.assertEqual(v.itemsize, sizeof(itemtp)) self.assertEqual(v.shape, shape) - # XXX Issue #12851 - # self.assertEqual(v.strides, ()) - + # ctypes object always have a non-strided memory block + self.assertEqual(v.strides, None) # they are always read/write self.assertFalse(v.readonly) @@ -99,6 +95,7 @@ class aUnion(Union): class StructWithArrays(Structure): _fields_ = [("x", c_long * 3 * 2), ("y", Point * 4)] + class Incomplete(Structure): pass @@ -145,33 +142,33 @@ native_types = [ ## simple types - (c_char, "<c", (), c_char), - (c_byte, "<b", (), c_byte), - (c_ubyte, "<B", (), c_ubyte), - (c_short, "<" + s_short, (), c_short), - (c_ushort, "<" + s_ushort, (), c_ushort), + (c_char, "<c", None, c_char), + (c_byte, "<b", None, c_byte), + (c_ubyte, "<B", None, c_ubyte), + (c_short, "<" + s_short, None, c_short), + (c_ushort, "<" + s_ushort, None, c_ushort), - (c_int, "<" + s_int, (), c_int), - (c_uint, "<" + s_uint, (), c_uint), + (c_int, "<" + s_int, None, c_int), + (c_uint, "<" + s_uint, None, c_uint), - (c_long, "<" + s_long, (), c_long), - (c_ulong, "<" + s_ulong, (), c_ulong), + (c_long, "<" + s_long, None, c_long), + (c_ulong, "<" + s_ulong, None, c_ulong), - (c_longlong, "<" + s_longlong, (), c_longlong), - (c_ulonglong, "<" + s_ulonglong, (), c_ulonglong), + (c_longlong, "<" + s_longlong, None, c_longlong), + (c_ulonglong, "<" + s_ulonglong, None, c_ulonglong), - (c_float, "<f", (), c_float), - (c_double, "<d", (), c_double), + (c_float, "<f", None, c_float), + (c_double, "<d", None, c_double), - (c_longdouble, "<" + s_longdouble, (), c_longdouble), + (c_longdouble, "<" + s_longdouble, None, c_longdouble), - (c_bool, "<" + s_bool, (), c_bool), - (py_object, "<O", (), py_object), + (c_bool, "<" + s_bool, None, c_bool), + (py_object, "<O", None, py_object), ## pointers - (POINTER(c_byte), "&<b", (), POINTER(c_byte)), - (POINTER(POINTER(c_long)), "&&<" + s_long, (), POINTER(POINTER(c_long))), + (POINTER(c_byte), "&<b", None, POINTER(c_byte)), + (POINTER(POINTER(c_long)), "&&<" + s_long, None, POINTER(POINTER(c_long))), ## arrays and pointers @@ -179,35 +176,35 @@ native_types = [ (c_float * 4 * 3 * 2, "<f", (2,3,4), c_float), (POINTER(c_short) * 2, "&<" + s_short, (2,), POINTER(c_short)), (POINTER(c_short) * 2 * 3, "&<" + s_short, (3,2,), POINTER(c_short)), - (POINTER(c_short * 2), "&(2)<" + s_short, (), POINTER(c_short)), + (POINTER(c_short * 2), "&(2)<" + s_short, None, POINTER(c_short)), ## structures and unions - (Point, "T{<l:x:<l:y:}".replace('l', s_long), (), Point), + (Point, "T{<l:x:<l:y:}".replace('l', s_long), None, Point), # packed structures do not implement the pep - (PackedPoint, "B", (), PackedPoint), - (Point2, "T{<l:x:<l:y:}".replace('l', s_long), (), Point2), - (EmptyStruct, "T{}", (), EmptyStruct), - # the pep doesn't support unions - (aUnion, "B", (), aUnion), + (PackedPoint, "B", None, PackedPoint), + (Point2, "T{<l:x:<l:y:}".replace('l', s_long), None, Point2), + (EmptyStruct, "T{}", None, EmptyStruct), + # the pep does't support unions + (aUnion, "B", None, aUnion), # structure with sub-arrays - (StructWithArrays, "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}".replace('l', s_long), (), StructWithArrays), + (StructWithArrays, "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}".replace('l', s_long), None, StructWithArrays), (StructWithArrays * 3, "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}".replace('l', s_long), (3,), StructWithArrays), ## pointer to incomplete structure - (Incomplete, "B", (), Incomplete), - (POINTER(Incomplete), "&B", (), POINTER(Incomplete)), + (Incomplete, "B", None, Incomplete), + (POINTER(Incomplete), "&B", None, POINTER(Incomplete)), # 'Complete' is a structure that starts incomplete, but is completed after the # pointer type to it has been created. - (Complete, "T{<l:a:}".replace('l', s_long), (), Complete), + (Complete, "T{<l:a:}".replace('l', s_long), None, Complete), # Unfortunately the pointer format string is not fixed... - (POINTER(Complete), "&B", (), POINTER(Complete)), + (POINTER(Complete), "&B", None, POINTER(Complete)), ## other # function signatures are not implemented - (CFUNCTYPE(None), "X{}", (), CFUNCTYPE(None)), + (CFUNCTYPE(None), "X{}", None, CFUNCTYPE(None)), ] @@ -223,10 +220,10 @@ class LEPoint(LittleEndianStructure): # and little endian machines. # endian_types = [ - (BEPoint, "T{>l:x:>l:y:}".replace('l', s_long), (), BEPoint), - (LEPoint, "T{<l:x:<l:y:}".replace('l', s_long), (), LEPoint), - (POINTER(BEPoint), "&T{>l:x:>l:y:}".replace('l', s_long), (), POINTER(BEPoint)), - (POINTER(LEPoint), "&T{<l:x:<l:y:}".replace('l', s_long), (), POINTER(LEPoint)), + (BEPoint, "T{>l:x:>l:y:}".replace('l', s_long), None, BEPoint), + (LEPoint, "T{<l:x:<l:y:}".replace('l', s_long), None, LEPoint), + (POINTER(BEPoint), "&T{>l:x:>l:y:}".replace('l', s_long), None, POINTER(BEPoint)), + (POINTER(LEPoint), "&T{<l:x:<l:y:}".replace('l', s_long), None, POINTER(LEPoint)), ] if __name__ == "__main__": diff --git a/Lib/ctypes/test/test_pickling.py b/Lib/ctypes/test/test_pickling.py index c4a79b9..73528d4 100644 --- a/Lib/ctypes/test/test_pickling.py +++ b/Lib/ctypes/test/test_pickling.py @@ -69,7 +69,7 @@ class PickleTest: def test_wchar(self): self.dumps(c_char(b"x")) # Issue 5049 - self.dumps(c_wchar("x")) + self.dumps(c_wchar(u"x")) for proto in range(pickle.HIGHEST_PROTOCOL + 1): name = 'PickleTest_%s' % proto diff --git a/Lib/ctypes/test/test_pointers.py b/Lib/ctypes/test/test_pointers.py index e975158..4a8887c 100644 --- a/Lib/ctypes/test/test_pointers.py +++ b/Lib/ctypes/test/test_pointers.py @@ -5,8 +5,8 @@ import _ctypes_test ctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float] -python_types = [int, int, int, int, int, int, - int, int, int, int, float, float] +python_types = [int, int, int, int, int, long, + int, long, long, long, float, float] class PointersTestCase(unittest.TestCase): @@ -22,10 +22,7 @@ class PointersTestCase(unittest.TestCase): def test_pass_pointers(self): dll = CDLL(_ctypes_test.__file__) func = dll._testfunc_p_p - if sizeof(c_longlong) == sizeof(c_void_p): - func.restype = c_longlong - else: - func.restype = c_long + func.restype = c_long i = c_int(12345678) ## func.argtypes = (POINTER(c_int),) @@ -148,10 +145,10 @@ class PointersTestCase(unittest.TestCase): func.restype = c_char_p argv = (c_char_p * 2)() argc = c_int( 2 ) - argv[0] = b'hello' - argv[1] = b'world' + argv[0] = 'hello' + argv[1] = 'world' result = func( byref(argc), argv ) - self.assertEqual(result, b'world') + assert result == 'world', result def test_bug_1467852(self): # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702 @@ -168,16 +165,16 @@ class PointersTestCase(unittest.TestCase): def test_c_void_p(self): # http://sourceforge.net/tracker/?func=detail&aid=1518190&group_id=5470&atid=105470 if sizeof(c_void_p) == 4: - self.assertEqual(c_void_p(0xFFFFFFFF).value, + self.assertEqual(c_void_p(0xFFFFFFFFL).value, c_void_p(-1).value) - self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFF).value, + self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value, c_void_p(-1).value) elif sizeof(c_void_p) == 8: - self.assertEqual(c_void_p(0xFFFFFFFF).value, - 0xFFFFFFFF) - self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFF).value, + self.assertEqual(c_void_p(0xFFFFFFFFL).value, + 0xFFFFFFFFL) + self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value, c_void_p(-1).value) - self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFF).value, + self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFFL).value, c_void_p(-1).value) self.assertRaises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted diff --git a/Lib/ctypes/test/test_prototypes.py b/Lib/ctypes/test/test_prototypes.py index cd0c649..a10317b 100644 --- a/Lib/ctypes/test/test_prototypes.py +++ b/Lib/ctypes/test/test_prototypes.py @@ -34,7 +34,7 @@ def positive_address(a): # View the bits in `a` as unsigned instead. import struct num_bits = struct.calcsize("P") * 8 # num bits in native machine address - a += 1 << num_bits + a += 1L << num_bits assert a >= 0 return a @@ -58,7 +58,7 @@ class CharPointersTestCase(unittest.TestCase): try: func() - except TypeError as details: + except TypeError, details: self.assertEqual(str(details), "required argument 'input' missing") else: self.fail("TypeError not raised") @@ -69,10 +69,7 @@ class CharPointersTestCase(unittest.TestCase): def test_int_pointer_arg(self): func = testdll._testfunc_p_p - if sizeof(c_longlong) == sizeof(c_void_p): - func.restype = c_longlong - else: - func.restype = c_long + func.restype = c_long self.assertEqual(0, func(0)) ci = c_int(0) @@ -96,14 +93,14 @@ class CharPointersTestCase(unittest.TestCase): func.argtypes = POINTER(c_char), self.assertEqual(None, func(None)) - self.assertEqual(b"123", func(b"123")) + self.assertEqual("123", func("123")) self.assertEqual(None, func(c_char_p(None))) - self.assertEqual(b"123", func(c_char_p(b"123"))) + self.assertEqual("123", func(c_char_p("123"))) - self.assertEqual(b"123", func(c_buffer(b"123"))) - ca = c_char(b"a") - self.assertEqual(ord(b"a"), func(pointer(ca))[0]) - self.assertEqual(ord(b"a"), func(byref(ca))[0]) + self.assertEqual("123", func(c_buffer("123"))) + ca = c_char("a") + self.assertEqual("a", func(pointer(ca))[0]) + self.assertEqual("a", func(byref(ca))[0]) def test_c_char_p_arg(self): func = testdll._testfunc_p_p @@ -111,14 +108,14 @@ class CharPointersTestCase(unittest.TestCase): func.argtypes = c_char_p, self.assertEqual(None, func(None)) - self.assertEqual(b"123", func(b"123")) + self.assertEqual("123", func("123")) self.assertEqual(None, func(c_char_p(None))) - self.assertEqual(b"123", func(c_char_p(b"123"))) + self.assertEqual("123", func(c_char_p("123"))) - self.assertEqual(b"123", func(c_buffer(b"123"))) - ca = c_char(b"a") - self.assertEqual(ord(b"a"), func(pointer(ca))[0]) - self.assertEqual(ord(b"a"), func(byref(ca))[0]) + self.assertEqual("123", func(c_buffer("123"))) + ca = c_char("a") + self.assertEqual("a", func(pointer(ca))[0]) + self.assertEqual("a", func(byref(ca))[0]) def test_c_void_p_arg(self): func = testdll._testfunc_p_p @@ -126,14 +123,14 @@ class CharPointersTestCase(unittest.TestCase): func.argtypes = c_void_p, self.assertEqual(None, func(None)) - self.assertEqual(b"123", func(b"123")) - self.assertEqual(b"123", func(c_char_p(b"123"))) + self.assertEqual("123", func("123")) + self.assertEqual("123", func(c_char_p("123"))) self.assertEqual(None, func(c_char_p(None))) - self.assertEqual(b"123", func(c_buffer(b"123"))) - ca = c_char(b"a") - self.assertEqual(ord(b"a"), func(pointer(ca))[0]) - self.assertEqual(ord(b"a"), func(byref(ca))[0]) + self.assertEqual("123", func(c_buffer("123"))) + ca = c_char("a") + self.assertEqual("a", func(pointer(ca))[0]) + self.assertEqual("a", func(byref(ca))[0]) func(byref(c_int())) func(pointer(c_int())) @@ -146,7 +143,7 @@ class CharPointersTestCase(unittest.TestCase): func.argtypes = c_void_p, self.assertEqual(None, func(c_wchar_p(None))) - self.assertEqual("123", func(c_wchar_p("123"))) + self.assertEqual(u"123", func(c_wchar_p(u"123"))) def test_instance(self): func = testdll._testfunc_p_p @@ -176,24 +173,24 @@ class WCharPointersTestCase(unittest.TestCase): func.argtypes = POINTER(c_wchar), self.assertEqual(None, func(None)) - self.assertEqual("123", func("123")) + self.assertEqual(u"123", func(u"123")) self.assertEqual(None, func(c_wchar_p(None))) - self.assertEqual("123", func(c_wchar_p("123"))) + self.assertEqual(u"123", func(c_wchar_p(u"123"))) - self.assertEqual("123", func(c_wbuffer("123"))) + self.assertEqual(u"123", func(c_wbuffer(u"123"))) ca = c_wchar("a") - self.assertEqual("a", func(pointer(ca))[0]) - self.assertEqual("a", func(byref(ca))[0]) + self.assertEqual(u"a", func(pointer(ca))[0]) + self.assertEqual(u"a", func(byref(ca))[0]) def test_c_wchar_p_arg(self): func = testdll._testfunc_p_p func.restype = c_wchar_p func.argtypes = c_wchar_p, - c_wchar_p.from_param("123") + c_wchar_p.from_param(u"123") self.assertEqual(None, func(None)) - self.assertEqual("123", func("123")) + self.assertEqual("123", func(u"123")) self.assertEqual(None, func(c_wchar_p(None))) self.assertEqual("123", func(c_wchar_p("123"))) diff --git a/Lib/ctypes/test/test_python_api.py b/Lib/ctypes/test/test_python_api.py index 9c13746..bc2ffd0 100644 --- a/Lib/ctypes/test/test_python_api.py +++ b/Lib/ctypes/test/test_python_api.py @@ -1,6 +1,6 @@ from ctypes import * import unittest, sys -from test import support +from ctypes.test import requires ################################################################ # This section should be moved into ctypes\__init__.py, when it's ready. @@ -17,44 +17,45 @@ else: class PythonAPITestCase(unittest.TestCase): - def test_PyBytes_FromStringAndSize(self): - PyBytes_FromStringAndSize = pythonapi.PyBytes_FromStringAndSize + def test_PyString_FromStringAndSize(self): + PyString_FromStringAndSize = pythonapi.PyString_FromStringAndSize - PyBytes_FromStringAndSize.restype = py_object - PyBytes_FromStringAndSize.argtypes = c_char_p, c_py_ssize_t + PyString_FromStringAndSize.restype = py_object + PyString_FromStringAndSize.argtypes = c_char_p, c_py_ssize_t - self.assertEqual(PyBytes_FromStringAndSize(b"abcdefghi", 3), b"abc") + self.assertEqual(PyString_FromStringAndSize("abcdefghi", 3), "abc") - @support.refcount_test def test_PyString_FromString(self): - pythonapi.PyBytes_FromString.restype = py_object - pythonapi.PyBytes_FromString.argtypes = (c_char_p,) + pythonapi.PyString_FromString.restype = py_object + pythonapi.PyString_FromString.argtypes = (c_char_p,) - s = b"abc" + s = "abc" refcnt = grc(s) - pyob = pythonapi.PyBytes_FromString(s) + pyob = pythonapi.PyString_FromString(s) self.assertEqual(grc(s), refcnt) self.assertEqual(s, pyob) del pyob self.assertEqual(grc(s), refcnt) - @support.refcount_test - def test_PyLong_Long(self): + # This test is unreliable, because it is possible that code in + # unittest changes the refcount of the '42' integer. So, it + # is disabled by default. + def test_PyInt_Long(self): + requires("refcount") ref42 = grc(42) - pythonapi.PyLong_FromLong.restype = py_object - self.assertEqual(pythonapi.PyLong_FromLong(42), 42) + pythonapi.PyInt_FromLong.restype = py_object + self.assertEqual(pythonapi.PyInt_FromLong(42), 42) self.assertEqual(grc(42), ref42) - pythonapi.PyLong_AsLong.argtypes = (py_object,) - pythonapi.PyLong_AsLong.restype = c_long + pythonapi.PyInt_AsLong.argtypes = (py_object,) + pythonapi.PyInt_AsLong.restype = c_long - res = pythonapi.PyLong_AsLong(42) + res = pythonapi.PyInt_AsLong(42) self.assertEqual(grc(res), ref42 + 1) del res self.assertEqual(grc(42), ref42) - @support.refcount_test def test_PyObj_FromPtr(self): s = "abc def ghi jkl" ref = grc(s) @@ -71,11 +72,11 @@ class PythonAPITestCase(unittest.TestCase): PyOS_snprintf.argtypes = POINTER(c_char), c_size_t, c_char_p buf = c_buffer(256) - PyOS_snprintf(buf, sizeof(buf), b"Hello from %s", b"ctypes") - self.assertEqual(buf.value, b"Hello from ctypes") + PyOS_snprintf(buf, sizeof(buf), "Hello from %s", "ctypes") + self.assertEqual(buf.value, "Hello from ctypes") - PyOS_snprintf(buf, sizeof(buf), b"Hello from %s (%d, %d, %d)", b"ctypes", 1, 2, 3) - self.assertEqual(buf.value, b"Hello from ctypes (1, 2, 3)") + PyOS_snprintf(buf, sizeof(buf), "Hello from %s", "ctypes", 1, 2, 3) + self.assertEqual(buf.value, "Hello from ctypes") # not enough arguments self.assertRaises(TypeError, PyOS_snprintf, buf) diff --git a/Lib/ctypes/test/test_random_things.py b/Lib/ctypes/test/test_random_things.py index ee5b212..d72b7c8 100644 --- a/Lib/ctypes/test/test_random_things.py +++ b/Lib/ctypes/test/test_random_things.py @@ -2,7 +2,7 @@ from ctypes import * import unittest, sys def callback_func(arg): - 42 / arg + 42 // arg raise ValueError(arg) @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') @@ -16,8 +16,8 @@ class call_function_TestCase(unittest.TestCase): 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") + hdll = windll.kernel32.LoadLibraryA("kernel32") + funcaddr = windll.kernel32.GetProcAddress(hdll, "GetModuleHandleA") self.assertEqual(call_function(funcaddr, (None,)), windll.kernel32.GetModuleHandleA(None)) @@ -36,9 +36,9 @@ class CallbackTracbackTestCase(unittest.TestCase): def capture_stderr(self, func, *args, **kw): # helper - call function 'func', and return the captured stderr - import io + import StringIO old_stderr = sys.stderr - logger = sys.stderr = io.StringIO() + logger = sys.stderr = StringIO.StringIO() try: func(*args, **kw) finally: @@ -65,10 +65,10 @@ class CallbackTracbackTestCase(unittest.TestCase): def test_TypeErrorDivisionError(self): cb = CFUNCTYPE(c_int, c_char_p)(callback_func) - out = self.capture_stderr(cb, b"spam") + out = self.capture_stderr(cb, "spam") self.assertEqual(out.splitlines()[-1], "TypeError: " - "unsupported operand type(s) for /: 'int' and 'bytes'") + "unsupported operand type(s) for //: 'int' and 'str'") if __name__ == '__main__': unittest.main() diff --git a/Lib/ctypes/test/test_refcounts.py b/Lib/ctypes/test/test_refcounts.py index f2edfa6..2031346 100644 --- a/Lib/ctypes/test/test_refcounts.py +++ b/Lib/ctypes/test/test_refcounts.py @@ -1,5 +1,4 @@ import unittest -from test import support import ctypes import gc @@ -11,7 +10,6 @@ dll = ctypes.CDLL(_ctypes_test.__file__) class RefcountTestCase(unittest.TestCase): - @support.refcount_test def test_1(self): from sys import getrefcount as grc @@ -36,7 +34,6 @@ class RefcountTestCase(unittest.TestCase): self.assertEqual(grc(callback), 2) - @support.refcount_test def test_refcount(self): from sys import getrefcount as grc def func(*args): diff --git a/Lib/ctypes/test/test_repr.py b/Lib/ctypes/test/test_repr.py index 60a2c80..99cc556 100644 --- a/Lib/ctypes/test/test_repr.py +++ b/Lib/ctypes/test/test_repr.py @@ -22,8 +22,8 @@ class ReprTest(unittest.TestCase): self.assertEqual("<X object at", repr(typ(42))[:12]) def test_char(self): - self.assertEqual("c_char(b'x')", repr(c_char(b'x'))) - self.assertEqual("<X object at", repr(X(b'x'))[:12]) + self.assertEqual("c_char('x')", repr(c_char('x'))) + self.assertEqual("<X object at", repr(X('x'))[:12]) if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_returnfuncptrs.py b/Lib/ctypes/test/test_returnfuncptrs.py index 1974f40..0827f0a 100644 --- a/Lib/ctypes/test/test_returnfuncptrs.py +++ b/Lib/ctypes/test/test_returnfuncptrs.py @@ -1,5 +1,6 @@ import unittest from ctypes import * +import os import _ctypes_test @@ -12,12 +13,10 @@ class ReturnFuncPtrTestCase(unittest.TestCase): get_strchr = dll.get_strchr get_strchr.restype = CFUNCTYPE(c_char_p, c_char_p, c_char) strchr = get_strchr() - self.assertEqual(strchr(b"abcdef", b"b"), b"bcdef") - self.assertEqual(strchr(b"abcdef", b"x"), None) - self.assertEqual(strchr(b"abcdef", 98), b"bcdef") - self.assertEqual(strchr(b"abcdef", 107), None) - self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0) - self.assertRaises(TypeError, strchr, b"abcdef") + self.assertEqual(strchr("abcdef", "b"), "bcdef") + self.assertEqual(strchr("abcdef", "x"), None) + self.assertRaises(ArgumentError, strchr, "abcdef", 3) + self.assertRaises(TypeError, strchr, "abcdef") def test_without_prototype(self): dll = CDLL(_ctypes_test.__file__) @@ -28,10 +27,10 @@ class ReturnFuncPtrTestCase(unittest.TestCase): # _CFuncPtr instances are now callable with an integer argument # which denotes a function address: strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(addr) - self.assertTrue(strchr(b"abcdef", b"b"), "bcdef") - self.assertEqual(strchr(b"abcdef", b"x"), None) - self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0) - self.assertRaises(TypeError, strchr, b"abcdef") + self.assertTrue(strchr("abcdef", "b"), "bcdef") + self.assertEqual(strchr("abcdef", "x"), None) + self.assertRaises(ArgumentError, strchr, "abcdef", 3) + self.assertRaises(TypeError, strchr, "abcdef") def test_from_dll(self): dll = CDLL(_ctypes_test.__file__) diff --git a/Lib/ctypes/test/test_simplesubclasses.py b/Lib/ctypes/test/test_simplesubclasses.py index 3da2794..1b73fb3 100644 --- a/Lib/ctypes/test/test_simplesubclasses.py +++ b/Lib/ctypes/test/test_simplesubclasses.py @@ -2,10 +2,12 @@ import unittest from ctypes import * class MyInt(c_int): - def __eq__(self, other): + def __cmp__(self, other): if type(other) != MyInt: - return NotImplementedError - return self.value == other.value + return -1 + return cmp(self.value, other.value) + def __hash__(self): # Silence Py3k warning + return hash(self.value) class Test(unittest.TestCase): diff --git a/Lib/ctypes/test/test_sizes.py b/Lib/ctypes/test/test_sizes.py index 4ceacbc..f9b5e97 100644 --- a/Lib/ctypes/test/test_sizes.py +++ b/Lib/ctypes/test/test_sizes.py @@ -2,6 +2,7 @@ from ctypes import * +import sys import unittest diff --git a/Lib/ctypes/test/test_slicing.py b/Lib/ctypes/test/test_slicing.py index a3932f1..a9ee3a8 100644 --- a/Lib/ctypes/test/test_slicing.py +++ b/Lib/ctypes/test/test_slicing.py @@ -6,8 +6,8 @@ import _ctypes_test class SlicesTestCase(unittest.TestCase): def test_getslice_cint(self): - a = (c_int * 100)(*range(1100, 1200)) - b = list(range(1100, 1200)) + a = (c_int * 100)(*xrange(1100, 1200)) + b = range(1100, 1200) self.assertEqual(a[0:2], b[0:2]) self.assertEqual(a[0:2:], b[0:2:]) self.assertEqual(len(a), len(b)) @@ -22,20 +22,20 @@ class SlicesTestCase(unittest.TestCase): self.assertEqual(a[2:6:4], b[2:6:4]) a[0:5] = range(5, 10) - self.assertEqual(a[0:5], list(range(5, 10))) - self.assertEqual(a[0:5:], list(range(5, 10))) - self.assertEqual(a[4::-1], list(range(9, 4, -1))) + self.assertEqual(a[0:5], range(5, 10)) + self.assertEqual(a[0:5:], range(5, 10)) + self.assertEqual(a[4::-1], range(9, 4, -1)) def test_setslice_cint(self): - a = (c_int * 100)(*range(1100, 1200)) - b = list(range(1100, 1200)) + a = (c_int * 100)(*xrange(1100, 1200)) + b = range(1100, 1200) - a[32:47] = list(range(32, 47)) - self.assertEqual(a[32:47], list(range(32, 47))) + a[32:47] = range(32, 47) + self.assertEqual(a[32:47], range(32, 47)) a[32:47] = range(132, 147) - self.assertEqual(a[32:47:], list(range(132, 147))) + self.assertEqual(a[32:47:], range(132, 147)) a[46:31:-1] = range(232, 247) - self.assertEqual(a[32:47:1], list(range(246, 231, -1))) + self.assertEqual(a[32:47:1], range(246, 231, -1)) a[32:47] = range(1132, 1147) self.assertEqual(a[:], b) @@ -46,21 +46,25 @@ class SlicesTestCase(unittest.TestCase): b[33::-3] = range(12) self.assertEqual(a[:], b) - from operator import setitem + from operator import setslice, setitem # TypeError: int expected instead of str instance + self.assertRaises(TypeError, setslice, a, 0, 5, "abcde") self.assertRaises(TypeError, setitem, a, slice(0, 5), "abcde") # TypeError: int expected instead of str instance + self.assertRaises(TypeError, setslice, a, 0, 5, ["a", "b", "c", "d", "e"]) self.assertRaises(TypeError, setitem, a, slice(0, 5), ["a", "b", "c", "d", "e"]) # TypeError: int expected instead of float instance + self.assertRaises(TypeError, setslice, a, 0, 5, [1, 2, 3, 4, 3.14]) self.assertRaises(TypeError, setitem, a, slice(0, 5), [1, 2, 3, 4, 3.14]) # ValueError: Can only assign sequence of same size + self.assertRaises(ValueError, setslice, a, 0, 5, range(32)) self.assertRaises(ValueError, setitem, a, slice(0, 5), range(32)) def test_char_ptr(self): - s = b"abcdefghijklmnopqrstuvwxyz" + s = "abcdefghijklmnopqrstuvwxyz" dll = CDLL(_ctypes_test.__file__) dll.my_strdup.restype = POINTER(c_char) @@ -83,19 +87,21 @@ class SlicesTestCase(unittest.TestCase): self.assertRaises(ValueError, operator.getitem, res, slice(-5, None, None)) + self.assertRaises(TypeError, operator.setslice, + res, 0, 5, u"abcde") self.assertRaises(TypeError, operator.setitem, - res, slice(0, 5), "abcde") + res, slice(0, 5), u"abcde") dll.my_free(res) dll.my_strdup.restype = POINTER(c_byte) res = dll.my_strdup(s) - self.assertEqual(res[:len(s)], list(range(ord("a"), ord("z")+1))) - self.assertEqual(res[:len(s):], list(range(ord("a"), ord("z")+1))) + self.assertEqual(res[:len(s)], range(ord("a"), ord("z")+1)) + self.assertEqual(res[:len(s):], range(ord("a"), ord("z")+1)) dll.my_free(res) def test_char_ptr_with_free(self): dll = CDLL(_ctypes_test.__file__) - s = b"abcdefghijklmnopqrstuvwxyz" + s = "abcdefghijklmnopqrstuvwxyz" class allocated_c_char_p(c_char_p): pass @@ -116,7 +122,7 @@ class SlicesTestCase(unittest.TestCase): def test_char_array(self): - s = b"abcdefghijklmnopqrstuvwxyz\0" + s = "abcdefghijklmnopqrstuvwxyz\0" p = (c_char * 27)(*s) self.assertEqual(p[:], s) @@ -128,21 +134,23 @@ class SlicesTestCase(unittest.TestCase): @need_symbol('c_wchar') def test_wchar_ptr(self): - s = "abcdefghijklmnopqrstuvwxyz\0" + s = u"abcdefghijklmnopqrstuvwxyz\0" dll = CDLL(_ctypes_test.__file__) dll.my_wcsdup.restype = POINTER(c_wchar) dll.my_wcsdup.argtypes = POINTER(c_wchar), dll.my_free.restype = None - res = dll.my_wcsdup(s[:-1]) + res = dll.my_wcsdup(s) self.assertEqual(res[:len(s)], s) self.assertEqual(res[:len(s):], s) self.assertEqual(res[len(s)-1:-1:-1], s[::-1]) self.assertEqual(res[len(s)-1:5:-7], s[:5:-7]) import operator + self.assertRaises(TypeError, operator.setslice, + res, 0, 5, u"abcde") self.assertRaises(TypeError, operator.setitem, - res, slice(0, 5), "abcde") + res, slice(0, 5), u"abcde") dll.my_free(res) if sizeof(c_wchar) == sizeof(c_short): @@ -153,8 +161,8 @@ class SlicesTestCase(unittest.TestCase): dll.my_wcsdup.restype = POINTER(c_long) else: self.skipTest('Pointers to c_wchar are not supported') - res = dll.my_wcsdup(s[:-1]) - tmpl = list(range(ord("a"), ord("z")+1)) + res = dll.my_wcsdup(s) + tmpl = range(ord("a"), ord("z")+1) self.assertEqual(res[:len(s)-1], tmpl) self.assertEqual(res[:len(s)-1:], tmpl) self.assertEqual(res[len(s)-2:-1:-1], tmpl[::-1]) diff --git a/Lib/ctypes/test/test_stringptr.py b/Lib/ctypes/test/test_stringptr.py index c20951f..abed58b 100644 --- a/Lib/ctypes/test/test_stringptr.py +++ b/Lib/ctypes/test/test_stringptr.py @@ -1,5 +1,4 @@ import unittest -from test import support from ctypes import * import _ctypes_test @@ -8,7 +7,6 @@ lib = CDLL(_ctypes_test.__file__) class StringPtrTestCase(unittest.TestCase): - @support.refcount_test def test__POINTER_c_char(self): class X(Structure): _fields_ = [("str", POINTER(c_char))] @@ -16,7 +14,7 @@ class StringPtrTestCase(unittest.TestCase): # NULL pointer access self.assertRaises(ValueError, getattr, x.str, "contents") - b = c_buffer(b"Hello, World") + b = c_buffer("Hello, World") from sys import getrefcount as grc self.assertEqual(grc(b), 2) x.str = b @@ -37,10 +35,10 @@ class StringPtrTestCase(unittest.TestCase): # c_char_p and Python string is compatible # c_char_p and c_buffer is NOT compatible self.assertEqual(x.str, None) - x.str = b"Hello, World" - self.assertEqual(x.str, b"Hello, World") - b = c_buffer(b"Hello, World") - self.assertRaises(TypeError, setattr, x, b"str", b) + x.str = "Hello, World" + self.assertEqual(x.str, "Hello, World") + b = c_buffer("Hello, World") + self.assertRaises(TypeError, setattr, x, "str", b) def test_functions(self): @@ -50,28 +48,28 @@ class StringPtrTestCase(unittest.TestCase): # c_char_p and Python string is compatible # c_char_p and c_buffer are now compatible strchr.argtypes = c_char_p, c_char - self.assertEqual(strchr(b"abcdef", b"c"), b"cdef") - self.assertEqual(strchr(c_buffer(b"abcdef"), b"c"), b"cdef") + self.assertEqual(strchr("abcdef", "c"), "cdef") + self.assertEqual(strchr(c_buffer("abcdef"), "c"), "cdef") # POINTER(c_char) and Python string is NOT compatible # POINTER(c_char) and c_buffer() is compatible strchr.argtypes = POINTER(c_char), c_char - buf = c_buffer(b"abcdef") - self.assertEqual(strchr(buf, b"c"), b"cdef") - self.assertEqual(strchr(b"abcdef", b"c"), b"cdef") + buf = c_buffer("abcdef") + self.assertEqual(strchr(buf, "c"), "cdef") + self.assertEqual(strchr("abcdef", "c"), "cdef") # XXX These calls are dangerous, because the first argument # to strchr is no longer valid after the function returns! # So we must keep a reference to buf separately strchr.restype = POINTER(c_char) - buf = c_buffer(b"abcdef") - r = strchr(buf, b"c") + buf = c_buffer("abcdef") + r = strchr(buf, "c") x = r[0], r[1], r[2], r[3], r[4] - self.assertEqual(x, (b"c", b"d", b"e", b"f", b"\000")) + self.assertEqual(x, ("c", "d", "e", "f", "\000")) del buf - # Because r is a pointer to memory that is freed after deleting buf, - # the pointer is hanging and using it would reference freed memory. + # x1 will NOT be the same as x, usually: + x1 = r[0], r[1], r[2], r[3], r[4] if __name__ == '__main__': unittest.main() diff --git a/Lib/ctypes/test/test_strings.py b/Lib/ctypes/test/test_strings.py index 5434efd..879c58a 100644 --- a/Lib/ctypes/test/test_strings.py +++ b/Lib/ctypes/test/test_strings.py @@ -1,47 +1,54 @@ import unittest from ctypes import * from ctypes.test import need_symbol +from test import test_support class StringArrayTestCase(unittest.TestCase): def test(self): BUF = c_char * 4 - buf = BUF(b"a", b"b", b"c") - self.assertEqual(buf.value, b"abc") - self.assertEqual(buf.raw, b"abc\000") + buf = BUF("a", "b", "c") + self.assertEqual(buf.value, "abc") + self.assertEqual(buf.raw, "abc\000") - buf.value = b"ABCD" - self.assertEqual(buf.value, b"ABCD") - self.assertEqual(buf.raw, b"ABCD") + buf.value = "ABCD" + self.assertEqual(buf.value, "ABCD") + self.assertEqual(buf.raw, "ABCD") - buf.value = b"x" - self.assertEqual(buf.value, b"x") - self.assertEqual(buf.raw, b"x\000CD") + buf.value = "x" + self.assertEqual(buf.value, "x") + self.assertEqual(buf.raw, "x\000CD") - buf[1] = b"Z" - self.assertEqual(buf.value, b"xZCD") - self.assertEqual(buf.raw, b"xZCD") + buf[1] = "Z" + self.assertEqual(buf.value, "xZCD") + self.assertEqual(buf.raw, "xZCD") - self.assertRaises(ValueError, setattr, buf, "value", b"aaaaaaaa") + self.assertRaises(ValueError, setattr, buf, "value", "aaaaaaaa") self.assertRaises(TypeError, setattr, buf, "value", 42) - def test_c_buffer_value(self): + def test_c_buffer_value(self, memoryview=memoryview): buf = c_buffer(32) - buf.value = b"Hello, World" - self.assertEqual(buf.value, b"Hello, World") + buf.value = "Hello, World" + self.assertEqual(buf.value, "Hello, World") - self.assertRaises(TypeError, setattr, buf, "value", memoryview(b"Hello, World")) - self.assertRaises(TypeError, setattr, buf, "value", memoryview(b"abc")) - self.assertRaises(ValueError, setattr, buf, "raw", memoryview(b"x" * 100)) + self.assertRaises(TypeError, setattr, buf, "value", memoryview("Hello, World")) + self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) + self.assertRaises(ValueError, setattr, buf, "raw", memoryview("x" * 100)) - def test_c_buffer_raw(self): + def test_c_buffer_raw(self, memoryview=memoryview): buf = c_buffer(32) - buf.raw = memoryview(b"Hello, World") - self.assertEqual(buf.value, b"Hello, World") - self.assertRaises(TypeError, setattr, buf, "value", memoryview(b"abc")) - self.assertRaises(ValueError, setattr, buf, "raw", memoryview(b"x" * 100)) + buf.raw = memoryview("Hello, World") + self.assertEqual(buf.value, "Hello, World") + self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc")) + self.assertRaises(ValueError, setattr, buf, "raw", memoryview("x" * 100)) + + def test_c_buffer_deprecated(self): + # Compatibility with 2.x + with test_support.check_py3k_warnings(): + self.test_c_buffer_value(buffer) + self.test_c_buffer_raw(buffer) def test_param_1(self): BUF = c_char * 4 @@ -66,24 +73,17 @@ class WStringArrayTestCase(unittest.TestCase): def test(self): BUF = c_wchar * 4 - buf = BUF("a", "b", "c") - self.assertEqual(buf.value, "abc") - - buf.value = "ABCD" - self.assertEqual(buf.value, "ABCD") + buf = BUF(u"a", u"b", u"c") + self.assertEqual(buf.value, u"abc") - buf.value = "x" - self.assertEqual(buf.value, "x") + buf.value = u"ABCD" + self.assertEqual(buf.value, u"ABCD") - buf[1] = "Z" - self.assertEqual(buf.value, "xZCD") + buf.value = u"x" + self.assertEqual(buf.value, u"x") - @unittest.skipIf(sizeof(c_wchar) < 4, - "sizeof(wchar_t) is smaller than 4 bytes") - def test_nonbmp(self): - u = chr(0x10ffff) - w = c_wchar(u) - self.assertEqual(w.value, u) + buf[1] = u"Z" + self.assertEqual(buf.value, u"xZCD") class StringTestCase(unittest.TestCase): @unittest.skip('test disabled') @@ -111,7 +111,7 @@ class StringTestCase(unittest.TestCase): self.assertEqual(cs.value, "XY") self.assertEqual(cs.raw, "XY\000\000\000\000\000") - self.assertRaises(TypeError, c_string, "123") + self.assertRaises(TypeError, c_string, u"123") @unittest.skip('test disabled') def test_sized_strings(self): @@ -157,14 +157,14 @@ class StringTestCase(unittest.TestCase): @need_symbol('c_wchar') class WStringTestCase(unittest.TestCase): def test_wchar(self): - c_wchar("x") - repr(byref(c_wchar("x"))) + c_wchar(u"x") + repr(byref(c_wchar(u"x"))) c_wchar("x") @unittest.skip('test disabled') def test_basic_wstrings(self): - cs = c_wstring("abcdef") + cs = c_wstring(u"abcdef") # XXX This behaviour is about to change: # len returns the size of the internal buffer in bytes. @@ -172,41 +172,41 @@ class WStringTestCase(unittest.TestCase): self.assertEqual(sizeof(cs), 14) # The value property is the string up to the first terminating NUL. - self.assertEqual(cs.value, "abcdef") - self.assertEqual(c_wstring("abc\000def").value, "abc") + self.assertEqual(cs.value, u"abcdef") + self.assertEqual(c_wstring(u"abc\000def").value, u"abc") - self.assertEqual(c_wstring("abc\000def").value, "abc") + self.assertEqual(c_wstring(u"abc\000def").value, u"abc") # The raw property is the total buffer contents: - self.assertEqual(cs.raw, "abcdef\000") - self.assertEqual(c_wstring("abc\000def").raw, "abc\000def\000") + self.assertEqual(cs.raw, u"abcdef\000") + self.assertEqual(c_wstring(u"abc\000def").raw, u"abc\000def\000") # We can change the value: - cs.value = "ab" - self.assertEqual(cs.value, "ab") - self.assertEqual(cs.raw, "ab\000\000\000\000\000") + cs.value = u"ab" + self.assertEqual(cs.value, u"ab") + self.assertEqual(cs.raw, u"ab\000\000\000\000\000") self.assertRaises(TypeError, c_wstring, "123") self.assertRaises(ValueError, c_wstring, 0) @unittest.skip('test disabled') def test_toolong(self): - cs = c_wstring("abcdef") + cs = c_wstring(u"abcdef") # Much too long string: - self.assertRaises(ValueError, setattr, cs, "value", "123456789012345") + self.assertRaises(ValueError, setattr, cs, "value", u"123456789012345") # One char too long values: - self.assertRaises(ValueError, setattr, cs, "value", "1234567") + self.assertRaises(ValueError, setattr, cs, "value", u"1234567") def run_test(rep, msg, func, arg): items = range(rep) - from time import perf_counter as clock + from time import clock start = clock() for i in items: func(arg); func(arg); func(arg); func(arg); func(arg) stop = clock() - print("%20s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))) + print "%20s: %.2f us" % (msg, ((stop-start)*1e6/5/rep)) def check_perf(): # Construct 5 objects diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py index 283ccbf..9a863c9 100644 --- a/Lib/ctypes/test/test_structures.py +++ b/Lib/ctypes/test/test_structures.py @@ -1,16 +1,9 @@ -import platform -import sys import unittest from ctypes import * from ctypes.test import need_symbol from struct import calcsize +import _testcapi import _ctypes_test -from test import support - -# The following definition is meant to be used from time to time to assist -# temporarily disabling tests on specific architectures while investigations -# are in progress, to keep buildbots happy. -MACHINE = platform.machine() class SubclassesTest(unittest.TestCase): def test_subclass(self): @@ -136,7 +129,7 @@ class StructureTestCase(unittest.TestCase): self.assertEqual(sizeof(XX), 0) def test_fields(self): - # test the offset and size attributes of Structure/Union fields. + # test the offset and size attributes of Structure/Unoin fields. class X(Structure): _fields_ = [("x", c_int), ("y", c_char)] @@ -209,10 +202,7 @@ class StructureTestCase(unittest.TestCase): "_pack_": -1} self.assertRaises(ValueError, type(Structure), "X", (Structure,), d) - @support.cpython_only - def test_packed_c_limits(self): # Issue 15989 - import _testcapi d = {"_fields_": [("a", c_byte)], "_pack_": _testcapi.INT_MAX + 1} self.assertRaises(ValueError, type(Structure), "X", (Structure,), d) @@ -226,22 +216,22 @@ class StructureTestCase(unittest.TestCase): ("age", c_int)] self.assertRaises(TypeError, Person, 42) - self.assertRaises(ValueError, Person, b"asldkjaslkdjaslkdj") + self.assertRaises(ValueError, Person, "asldkjaslkdjaslkdj") self.assertRaises(TypeError, Person, "Name", "HI") # short enough - self.assertEqual(Person(b"12345", 5).name, b"12345") + self.assertEqual(Person("12345", 5).name, "12345") # exact fit - self.assertEqual(Person(b"123456", 5).name, b"123456") + self.assertEqual(Person("123456", 5).name, "123456") # too long - self.assertRaises(ValueError, Person, b"1234567", 5) + self.assertRaises(ValueError, Person, "1234567", 5) def test_conflicting_initializers(self): class POINT(Structure): - _fields_ = [("phi", c_float), ("rho", c_float)] + _fields_ = [("x", c_int), ("y", c_int)] # conflicting positional and keyword args - self.assertRaisesRegex(TypeError, "phi", POINT, 2, 3, phi=4) - self.assertRaisesRegex(TypeError, "rho", POINT, 2, 3, rho=4) + self.assertRaises(TypeError, POINT, 2, 3, x=4) + self.assertRaises(TypeError, POINT, 2, 3, y=4) # too many initializers self.assertRaises(TypeError, POINT, 2, 3, 4) @@ -266,7 +256,7 @@ class StructureTestCase(unittest.TestCase): class S(Structure): _fields_ = [(name, c_int)] - self.assertRaises(TypeError, declare_with_name, b"x") + self.assertRaises(TypeError, declare_with_name, u"x\xe9") def test_intarray_fields(self): class SomeInts(Structure): @@ -296,11 +286,11 @@ class StructureTestCase(unittest.TestCase): ("phone", Phone), ("age", c_int)] - p = Person(b"Someone", (b"1234", b"5678"), 5) + p = Person("Someone", ("1234", "5678"), 5) - self.assertEqual(p.name, b"Someone") - self.assertEqual(p.phone.areacode, b"1234") - self.assertEqual(p.phone.number, b"5678") + self.assertEqual(p.name, "Someone") + self.assertEqual(p.phone.areacode, "1234") + self.assertEqual(p.phone.number, "5678") self.assertEqual(p.age, 5) @need_symbol('c_wchar') @@ -309,15 +299,15 @@ class StructureTestCase(unittest.TestCase): _fields_ = [("name", c_wchar * 12), ("age", c_int)] - p = PersonW("Someone \xe9") - self.assertEqual(p.name, "Someone \xe9") + p = PersonW(u"Someone") + self.assertEqual(p.name, "Someone") - self.assertEqual(PersonW("1234567890").name, "1234567890") - self.assertEqual(PersonW("12345678901").name, "12345678901") + self.assertEqual(PersonW(u"1234567890").name, u"1234567890") + self.assertEqual(PersonW(u"12345678901").name, u"12345678901") # exact fit - self.assertEqual(PersonW("123456789012").name, "123456789012") + self.assertEqual(PersonW(u"123456789012").name, u"123456789012") #too long - self.assertRaises(ValueError, PersonW, "1234567890123") + self.assertRaises(ValueError, PersonW, u"1234567890123") def test_init_errors(self): class Phone(Structure): @@ -329,16 +319,26 @@ class StructureTestCase(unittest.TestCase): ("phone", Phone), ("age", c_int)] - cls, msg = self.get_except(Person, b"Someone", (1, 2)) + cls, msg = self.get_except(Person, "Someone", (1, 2)) self.assertEqual(cls, RuntimeError) - self.assertEqual(msg, - "(Phone) <class 'TypeError'>: " - "expected bytes, int found") + # In Python 2.5, Exception is a new-style class, and the repr changed + if issubclass(Exception, object): + self.assertEqual(msg, + "(Phone) <type 'exceptions.TypeError'>: " + "expected string or Unicode object, int found") + else: + # Compatibility no longer strictly required + self.assertEqual(msg, + "(Phone) exceptions.TypeError: " + "expected string or Unicode object, int found") - cls, msg = self.get_except(Person, b"Someone", (b"a", b"b", b"c")) + cls, msg = self.get_except(Person, "Someone", ("a", "b", "c")) self.assertEqual(cls, RuntimeError) - self.assertEqual(msg, - "(Phone) <class 'TypeError'>: too many initializers") + if issubclass(Exception, object): + self.assertEqual(msg, + "(Phone) <type 'exceptions.TypeError'>: too many initializers") + else: + self.assertEqual(msg, "(Phone) exceptions.TypeError: too many initializers") def test_huge_field_name(self): # issue12881: segfault with large structure field names @@ -356,7 +356,7 @@ class StructureTestCase(unittest.TestCase): def get_except(self, func, *args): try: func(*args) - except Exception as detail: + except Exception, detail: return detail.__class__, str(detail) @unittest.skip('test disabled') @@ -403,339 +403,26 @@ class StructureTestCase(unittest.TestCase): self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7)) def test_pass_by_value(self): - # This should mirror the Test structure - # in Modules/_ctypes/_ctypes_test.c - class Test(Structure): + # This should mirror the structure in Modules/_ctypes/_ctypes_test.c + class X(Structure): _fields_ = [ ('first', c_ulong), ('second', c_ulong), ('third', c_ulong), ] - s = Test() + s = X() s.first = 0xdeadbeef s.second = 0xcafebabe s.third = 0x0bad1dea dll = CDLL(_ctypes_test.__file__) func = dll._testfunc_large_struct_update_value - func.argtypes = (Test,) - func.restype = None - func(s) - self.assertEqual(s.first, 0xdeadbeef) - self.assertEqual(s.second, 0xcafebabe) - self.assertEqual(s.third, 0x0bad1dea) - - def test_pass_by_value_finalizer(self): - # bpo-37140: Similar to test_pass_by_value(), but the Python structure - # has a finalizer (__del__() method): the finalizer must only be called - # once. - - finalizer_calls = [] - - class Test(Structure): - _fields_ = [ - ('first', c_ulong), - ('second', c_ulong), - ('third', c_ulong), - ] - def __del__(self): - finalizer_calls.append("called") - - s = Test(1, 2, 3) - # Test the StructUnionType_paramfunc() code path which copies the - # structure: if the stucture is larger than sizeof(void*). - self.assertGreater(sizeof(s), sizeof(c_void_p)) - - dll = CDLL(_ctypes_test.__file__) - func = dll._testfunc_large_struct_update_value - func.argtypes = (Test,) - func.restype = None - func(s) - # bpo-37140: Passing the structure by refrence must not call - # its finalizer! - self.assertEqual(finalizer_calls, []) - self.assertEqual(s.first, 1) - self.assertEqual(s.second, 2) - self.assertEqual(s.third, 3) - - # The finalizer must be called exactly once - s = None - support.gc_collect() - self.assertEqual(finalizer_calls, ["called"]) - - def test_pass_by_value_in_register(self): - class X(Structure): - _fields_ = [ - ('first', c_uint), - ('second', c_uint) - ] - - s = X() - s.first = 0xdeadbeef - s.second = 0xcafebabe - dll = CDLL(_ctypes_test.__file__) - func = dll._testfunc_reg_struct_update_value func.argtypes = (X,) func.restype = None func(s) self.assertEqual(s.first, 0xdeadbeef) self.assertEqual(s.second, 0xcafebabe) - got = X.in_dll(dll, "last_tfrsuv_arg") - self.assertEqual(s.first, got.first) - self.assertEqual(s.second, got.second) - - def test_array_in_struct(self): - # See bpo-22273 - - # These should mirror the structures in Modules/_ctypes/_ctypes_test.c - class Test2(Structure): - _fields_ = [ - ('data', c_ubyte * 16), - ] - - class Test3(Structure): - _fields_ = [ - ('data', c_double * 2), - ] - - class Test3A(Structure): - _fields_ = [ - ('data', c_float * 2), - ] - - class Test3B(Test3A): - _fields_ = [ - ('more_data', c_float * 2), - ] - - s = Test2() - expected = 0 - for i in range(16): - s.data[i] = i - expected += i - dll = CDLL(_ctypes_test.__file__) - func = dll._testfunc_array_in_struct1 - func.restype = c_int - func.argtypes = (Test2,) - result = func(s) - self.assertEqual(result, expected) - # check the passed-in struct hasn't changed - for i in range(16): - self.assertEqual(s.data[i], i) - - s = Test3() - s.data[0] = 3.14159 - s.data[1] = 2.71828 - expected = 3.14159 + 2.71828 - func = dll._testfunc_array_in_struct2 - func.restype = c_double - func.argtypes = (Test3,) - result = func(s) - self.assertEqual(result, expected) - # check the passed-in struct hasn't changed - self.assertEqual(s.data[0], 3.14159) - self.assertEqual(s.data[1], 2.71828) - - s = Test3B() - s.data[0] = 3.14159 - s.data[1] = 2.71828 - s.more_data[0] = -3.0 - s.more_data[1] = -2.0 - - expected = 3.14159 + 2.71828 - 5.0 - func = dll._testfunc_array_in_struct2a - func.restype = c_double - func.argtypes = (Test3B,) - result = func(s) - self.assertAlmostEqual(result, expected, places=6) - # check the passed-in struct hasn't changed - self.assertAlmostEqual(s.data[0], 3.14159, places=6) - self.assertAlmostEqual(s.data[1], 2.71828, places=6) - self.assertAlmostEqual(s.more_data[0], -3.0, places=6) - self.assertAlmostEqual(s.more_data[1], -2.0, places=6) - - def test_38368(self): - class U(Union): - _fields_ = [ - ('f1', c_uint8 * 16), - ('f2', c_uint16 * 8), - ('f3', c_uint32 * 4), - ] - u = U() - u.f3[0] = 0x01234567 - u.f3[1] = 0x89ABCDEF - u.f3[2] = 0x76543210 - u.f3[3] = 0xFEDCBA98 - f1 = [u.f1[i] for i in range(16)] - f2 = [u.f2[i] for i in range(8)] - if sys.byteorder == 'little': - self.assertEqual(f1, [0x67, 0x45, 0x23, 0x01, - 0xef, 0xcd, 0xab, 0x89, - 0x10, 0x32, 0x54, 0x76, - 0x98, 0xba, 0xdc, 0xfe]) - self.assertEqual(f2, [0x4567, 0x0123, 0xcdef, 0x89ab, - 0x3210, 0x7654, 0xba98, 0xfedc]) - - def test_union_by_value(self): - # See bpo-16575 - - # These should mirror the structures in Modules/_ctypes/_ctypes_test.c - - class Nested1(Structure): - _fields_ = [ - ('an_int', c_int), - ('another_int', c_int), - ] - - class Test4(Union): - _fields_ = [ - ('a_long', c_long), - ('a_struct', Nested1), - ] - - class Nested2(Structure): - _fields_ = [ - ('an_int', c_int), - ('a_union', Test4), - ] - - class Test5(Structure): - _fields_ = [ - ('an_int', c_int), - ('nested', Nested2), - ('another_int', c_int), - ] - - test4 = Test4() - dll = CDLL(_ctypes_test.__file__) - with self.assertRaises(TypeError) as ctx: - func = dll._testfunc_union_by_value1 - func.restype = c_long - func.argtypes = (Test4,) - result = func(test4) - self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' - 'a union by value, which is unsupported.') - test5 = Test5() - with self.assertRaises(TypeError) as ctx: - func = dll._testfunc_union_by_value2 - func.restype = c_long - func.argtypes = (Test5,) - result = func(test5) - self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' - 'a union by value, which is unsupported.') - - # passing by reference should be OK - test4.a_long = 12345; - func = dll._testfunc_union_by_reference1 - func.restype = c_long - func.argtypes = (POINTER(Test4),) - result = func(byref(test4)) - self.assertEqual(result, 12345) - self.assertEqual(test4.a_long, 0) - self.assertEqual(test4.a_struct.an_int, 0) - self.assertEqual(test4.a_struct.another_int, 0) - test4.a_struct.an_int = 0x12340000 - test4.a_struct.another_int = 0x5678 - func = dll._testfunc_union_by_reference2 - func.restype = c_long - func.argtypes = (POINTER(Test4),) - result = func(byref(test4)) - self.assertEqual(result, 0x12345678) - self.assertEqual(test4.a_long, 0) - self.assertEqual(test4.a_struct.an_int, 0) - self.assertEqual(test4.a_struct.another_int, 0) - test5.an_int = 0x12000000 - test5.nested.an_int = 0x345600 - test5.another_int = 0x78 - func = dll._testfunc_union_by_reference3 - func.restype = c_long - func.argtypes = (POINTER(Test5),) - result = func(byref(test5)) - self.assertEqual(result, 0x12345678) - self.assertEqual(test5.an_int, 0) - self.assertEqual(test5.nested.an_int, 0) - self.assertEqual(test5.another_int, 0) - - #@unittest.skipIf('s390' in MACHINE, 'Test causes segfault on S390') - def test_bitfield_by_value(self): - # See bpo-16576 - - # These should mirror the structures in Modules/_ctypes/_ctypes_test.c - - class Test6(Structure): - _fields_ = [ - ('A', c_int, 1), - ('B', c_int, 2), - ('C', c_int, 3), - ('D', c_int, 2), - ] - - test6 = Test6() - # As these are signed int fields, all are logically -1 due to sign - # extension. - test6.A = 1 - test6.B = 3 - test6.C = 7 - test6.D = 3 - dll = CDLL(_ctypes_test.__file__) - with self.assertRaises(TypeError) as ctx: - func = dll._testfunc_bitfield_by_value1 - func.restype = c_long - func.argtypes = (Test6,) - result = func(test6) - self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' - 'a struct/union with a bitfield by value, which is ' - 'unsupported.') - # passing by reference should be OK - func = dll._testfunc_bitfield_by_reference1 - func.restype = c_long - func.argtypes = (POINTER(Test6),) - result = func(byref(test6)) - self.assertEqual(result, -4) - self.assertEqual(test6.A, 0) - self.assertEqual(test6.B, 0) - self.assertEqual(test6.C, 0) - self.assertEqual(test6.D, 0) - - class Test7(Structure): - _fields_ = [ - ('A', c_uint, 1), - ('B', c_uint, 2), - ('C', c_uint, 3), - ('D', c_uint, 2), - ] - test7 = Test7() - test7.A = 1 - test7.B = 3 - test7.C = 7 - test7.D = 3 - func = dll._testfunc_bitfield_by_reference2 - func.restype = c_long - func.argtypes = (POINTER(Test7),) - result = func(byref(test7)) - self.assertEqual(result, 14) - self.assertEqual(test7.A, 0) - self.assertEqual(test7.B, 0) - self.assertEqual(test7.C, 0) - self.assertEqual(test7.D, 0) - - # for a union with bitfields, the union check happens first - class Test8(Union): - _fields_ = [ - ('A', c_int, 1), - ('B', c_int, 2), - ('C', c_int, 3), - ('D', c_int, 2), - ] - - test8 = Test8() - with self.assertRaises(TypeError) as ctx: - func = dll._testfunc_bitfield_by_value2 - func.restype = c_long - func.argtypes = (Test8,) - result = func(test8) - self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes ' - 'a union by value, which is unsupported.') + self.assertEqual(s.third, 0x0bad1dea) class PointerMemberTestCase(unittest.TestCase): @@ -785,7 +472,7 @@ class TestRecursiveStructure(unittest.TestCase): try: Recursive._fields_ = [("next", Recursive)] - except AttributeError as details: + except AttributeError, details: self.assertIn("Structure or union cannot contain itself", str(details)) else: @@ -802,7 +489,7 @@ class TestRecursiveStructure(unittest.TestCase): try: Second._fields_ = [("first", First)] - except AttributeError as details: + except AttributeError, details: self.assertIn("_fields_ is final", str(details)) else: self.fail("AttributeError not raised") diff --git a/Lib/ctypes/test/test_unicode.py b/Lib/ctypes/test/test_unicode.py index c200af7..ec5663a 100644 --- a/Lib/ctypes/test/test_unicode.py +++ b/Lib/ctypes/test/test_unicode.py @@ -1,56 +1,138 @@ +# coding: latin-1 import unittest import ctypes from ctypes.test import need_symbol - import _ctypes_test @need_symbol('c_wchar') class UnicodeTestCase(unittest.TestCase): - def test_wcslen(self): + @classmethod + def setUpClass(cls): dll = ctypes.CDLL(_ctypes_test.__file__) - wcslen = dll.my_wcslen - wcslen.argtypes = [ctypes.c_wchar_p] + cls.wcslen = dll.my_wcslen + cls.wcslen.argtypes = [ctypes.c_wchar_p] + def setUp(self): + self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict") + + def tearDown(self): + ctypes.set_conversion_mode(*self.prev_conv_mode) + + def test_ascii_strict(self): + wcslen = self.wcslen + ctypes.set_conversion_mode("ascii", "strict") + # no conversions take place with unicode arguments + self.assertEqual(wcslen(u"abc"), 3) + self.assertEqual(wcslen(u"ab\u2070"), 3) + # string args are converted + self.assertEqual(wcslen("abc"), 3) + self.assertRaises(ctypes.ArgumentError, wcslen, "abä") + + def test_ascii_replace(self): + wcslen = self.wcslen + ctypes.set_conversion_mode("ascii", "replace") + self.assertEqual(wcslen(u"abc"), 3) + self.assertEqual(wcslen(u"ab\u2070"), 3) + self.assertEqual(wcslen("abc"), 3) + self.assertEqual(wcslen("abä"), 3) + def test_ascii_ignore(self): + wcslen = self.wcslen + ctypes.set_conversion_mode("ascii", "ignore") + self.assertEqual(wcslen(u"abc"), 3) + self.assertEqual(wcslen(u"ab\u2070"), 3) + # ignore error mode skips non-ascii characters self.assertEqual(wcslen("abc"), 3) - self.assertEqual(wcslen("ab\u2070"), 3) - self.assertRaises(ctypes.ArgumentError, wcslen, b"ab\xe4") + self.assertEqual(wcslen("äöüß"), 0) + + def test_latin1_strict(self): + wcslen = self.wcslen + ctypes.set_conversion_mode("latin-1", "strict") + self.assertEqual(wcslen(u"abc"), 3) + self.assertEqual(wcslen(u"ab\u2070"), 3) + self.assertEqual(wcslen("abc"), 3) + self.assertEqual(wcslen("äöüß"), 4) def test_buffers(self): + ctypes.set_conversion_mode("ascii", "strict") buf = ctypes.create_unicode_buffer("abc") self.assertEqual(len(buf), 3+1) - buf = ctypes.create_unicode_buffer("ab\xe4\xf6\xfc") - self.assertEqual(buf[:], "ab\xe4\xf6\xfc\0") - self.assertEqual(buf[::], "ab\xe4\xf6\xfc\0") - self.assertEqual(buf[::-1], '\x00\xfc\xf6\xe4ba') - self.assertEqual(buf[::2], 'a\xe4\xfc') - self.assertEqual(buf[6:5:-1], "") + ctypes.set_conversion_mode("ascii", "replace") + buf = ctypes.create_unicode_buffer("abäöü") + self.assertEqual(buf[:], u"ab\uFFFD\uFFFD\uFFFD\0") + self.assertEqual(buf[::], u"ab\uFFFD\uFFFD\uFFFD\0") + self.assertEqual(buf[::-1], u"\0\uFFFD\uFFFD\uFFFDba") + self.assertEqual(buf[::2], u"a\uFFFD\uFFFD") + self.assertEqual(buf[6:5:-1], u"") -func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p + ctypes.set_conversion_mode("ascii", "ignore") + buf = ctypes.create_unicode_buffer("abäöü") + # is that correct? not sure. But with 'ignore', you get what you pay for.. + self.assertEqual(buf[:], u"ab\0\0\0\0") + self.assertEqual(buf[::], u"ab\0\0\0\0") + self.assertEqual(buf[::-1], u"\0\0\0\0ba") + self.assertEqual(buf[::2], u"a\0\0") + self.assertEqual(buf[6:5:-1], u"") +@need_symbol('c_wchar') class StringTestCase(UnicodeTestCase): + @classmethod + def setUpClass(cls): + super(StringTestCase, cls).setUpClass() + cls.func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p + def setUp(self): + func = self.func + self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict") func.argtypes = [ctypes.c_char_p] func.restype = ctypes.c_char_p def tearDown(self): + func = self.func + ctypes.set_conversion_mode(*self.prev_conv_mode) func.argtypes = None func.restype = ctypes.c_int - def test_func(self): - self.assertEqual(func(b"abc\xe4"), b"abc\xe4") + def test_ascii_strict(self): + func = self.func + ctypes.set_conversion_mode("ascii", "strict") + self.assertEqual(func("abc"), "abc") + self.assertEqual(func(u"abc"), "abc") + self.assertRaises(ctypes.ArgumentError, func, u"abä") + + def test_ascii_ignore(self): + func = self.func + ctypes.set_conversion_mode("ascii", "ignore") + self.assertEqual(func("abc"), "abc") + self.assertEqual(func(u"abc"), "abc") + self.assertEqual(func(u"äöüß"), "") + + def test_ascii_replace(self): + func = self.func + ctypes.set_conversion_mode("ascii", "replace") + self.assertEqual(func("abc"), "abc") + self.assertEqual(func(u"abc"), "abc") + self.assertEqual(func(u"äöüß"), "????") def test_buffers(self): - buf = ctypes.create_string_buffer(b"abc") + ctypes.set_conversion_mode("ascii", "strict") + buf = ctypes.create_string_buffer(u"abc") self.assertEqual(len(buf), 3+1) - buf = ctypes.create_string_buffer(b"ab\xe4\xf6\xfc") - self.assertEqual(buf[:], b"ab\xe4\xf6\xfc\0") - self.assertEqual(buf[::], b"ab\xe4\xf6\xfc\0") - self.assertEqual(buf[::-1], b'\x00\xfc\xf6\xe4ba') - self.assertEqual(buf[::2], b'a\xe4\xfc') - self.assertEqual(buf[6:5:-1], b"") + ctypes.set_conversion_mode("ascii", "replace") + buf = ctypes.create_string_buffer(u"abäöü") + self.assertEqual(buf[:], "ab???\0") + self.assertEqual(buf[::], "ab???\0") + self.assertEqual(buf[::-1], "\0???ba") + self.assertEqual(buf[::2], "a??") + self.assertEqual(buf[6:5:-1], "") + ctypes.set_conversion_mode("ascii", "ignore") + buf = ctypes.create_string_buffer(u"abäöü") + # is that correct? not sure. But with 'ignore', you get what you pay for.. + self.assertEqual(buf[:], "ab\0\0\0\0") + self.assertEqual(buf[::], "ab\0\0\0\0") + self.assertEqual(buf[::-1], "\0\0\0\0ba") if __name__ == '__main__': unittest.main() diff --git a/Lib/ctypes/test/test_values.py b/Lib/ctypes/test/test_values.py index 87eb919..fe7dcf0 100644 --- a/Lib/ctypes/test/test_values.py +++ b/Lib/ctypes/test/test_values.py @@ -11,18 +11,12 @@ import _ctypes_test class ValuesTestCase(unittest.TestCase): def test_an_integer(self): - # This test checks and changes an integer stored inside the - # _ctypes_test dll/shared lib. ctdll = CDLL(_ctypes_test.__file__) an_integer = c_int.in_dll(ctdll, "an_integer") x = an_integer.value self.assertEqual(x, ctdll.get_an_integer()) an_integer.value *= 2 self.assertEqual(x*2, ctdll.get_an_integer()) - # To avoid test failures when this test is repeated several - # times the original value must be restored - an_integer.value = x - self.assertEqual(x, ctdll.get_an_integer()) def test_undefined(self): ctdll = CDLL(_ctypes_test.__file__) @@ -32,11 +26,20 @@ class PythonValuesTestCase(unittest.TestCase): """This test only works when python itself is a dll/shared library""" def test_optimizeflag(self): - # This test accesses the Py_OptimizeFlag integer, which is - # exported by the Python dll and should match the sys.flags value + # This test accesses the Py_OptimizeFlag intger, which is + # exported by the Python dll. + # It's value is set depending on the -O and -OO flags: + # if not given, it is 0 and __debug__ is 1. + # If -O is given, the flag is 1, for -OO it is 2. + # docstrings are also removed in the latter case. opt = c_int.in_dll(pythonapi, "Py_OptimizeFlag").value - self.assertEqual(opt, sys.flags.optimize) + if __debug__: + self.assertEqual(opt, 0) + elif ValuesTestCase.__doc__ is not None: + self.assertEqual(opt, 1) + else: + self.assertEqual(opt, 2) def test_frozentable(self): # Python exports a PyImport_FrozenModules symbol. This is a @@ -56,39 +59,18 @@ class PythonValuesTestCase(unittest.TestCase): ft = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules") # ft is a pointer to the struct_frozen entries: items = [] - # _frozen_importlib changes size whenever importlib._bootstrap - # changes, so it gets a special case. We should make sure it's - # found, but don't worry about its size too much. The same - # applies to _frozen_importlib_external. - bootstrap_seen = [] - bootstrap_expected = [ - b'_frozen_importlib', - b'_frozen_importlib_external', - b'zipimport', - ] for entry in ft: # This is dangerous. We *can* iterate over a pointer, but # the loop will not terminate (maybe with an access # violation;-) because the pointer instance has no size. if entry.name is None: break + items.append((entry.name, entry.size)) - if entry.name in bootstrap_expected: - bootstrap_seen.append(entry.name) - self.assertTrue(entry.size, - "{!r} was reported as having no size".format(entry.name)) - continue - items.append((entry.name.decode("ascii"), entry.size)) - - expected = [("__hello__", 141), - ("__phello__", -141), - ("__phello__.spam", 141), - ] - self.assertEqual(items, expected, "PyImport_FrozenModules example " - "in Doc/library/ctypes.rst may be out of date") - - self.assertEqual(sorted(bootstrap_seen), bootstrap_expected, - "frozen bootstrap modules did not match PyImport_FrozenModules") + expected = [("__hello__", 104), + ("__phello__", -104), + ("__phello__.spam", 104)] + self.assertEqual(items, expected) from ctypes import _pointer_type_cache del _pointer_type_cache[struct_frozen] diff --git a/Lib/ctypes/test/test_win32.py b/Lib/ctypes/test/test_win32.py index e51bdc8..13a9863 100644 --- a/Lib/ctypes/test/test_win32.py +++ b/Lib/ctypes/test/test_win32.py @@ -1,45 +1,72 @@ # Windows specific tests from ctypes import * +from ctypes.test import requires import unittest, sys -from test import support +from test import test_support as support import _ctypes_test +# Only windows 32-bit has different calling conventions. +@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') +@unittest.skipUnless(sizeof(c_void_p) == sizeof(c_int), + "sizeof c_void_p and c_int differ") +class WindowsTestCase(unittest.TestCase): + def test_callconv_1(self): + # Testing stdcall function + + IsWindow = windll.user32.IsWindow + # ValueError: Procedure probably called with not enough arguments + # (4 bytes missing) + self.assertRaises(ValueError, IsWindow) + + # This one should succeed... + self.assertEqual(0, IsWindow(0)) + + # ValueError: Procedure probably called with too many arguments + # (8 bytes in excess) + self.assertRaises(ValueError, IsWindow, 0, 0, 0) + + def test_callconv_2(self): + # Calling stdcall function as cdecl + + IsWindow = cdll.user32.IsWindow + + # ValueError: Procedure called with not enough arguments + # (4 bytes missing) or wrong calling convention + self.assertRaises(ValueError, IsWindow, None) + @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') class FunctionCallTestCase(unittest.TestCase): @unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC") - @unittest.skipIf(sys.executable.lower().endswith('_d.exe'), + @unittest.skipIf(sys.executable.endswith('_d.exe'), "SEH not enabled in debug builds") def test_SEH(self): - # Disable faulthandler to prevent logging the warning: - # "Windows fatal exception: access violation" - 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) + requires("SEH") + # Call functions with invalid arguments, and make sure + # that access violations are trapped and raise an + # exception. + self.assertRaises(WindowsError, windll.kernel32.GetModuleHandleA, 32) def test_noargs(self): # This is a special case on win32 x64 windll.user32.GetDesktopWindow() - @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') class ReturnStructSizesTestCase(unittest.TestCase): def test_sizes(self): dll = CDLL(_ctypes_test.__file__) for i in range(1, 11): - fields = [ (f"f{f}", c_char) for f in range(1, i + 1)] + fields = [ ("f%d" % f, c_char) for f in range(1, i + 1)] class S(Structure): _fields_ = fields - f = getattr(dll, f"TestSize{i}") + f = getattr(dll, "TestSize%d" % i) f.restype = S res = f() for i, f in enumerate(fields): value = getattr(res, f[0]) - expected = bytes([ord('a') + i]) - self.assertEqual(value, expected) + expected = chr(ord('a') + i) + self.assertEquals(value, expected) @@ -67,29 +94,6 @@ class TestWintypes(unittest.TestCase): self.assertEqual(ex.text, "text") self.assertEqual(ex.details, ("details",)) -@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') -class TestWinError(unittest.TestCase): - def test_winerror(self): - # see Issue 16169 - import errno - ERROR_INVALID_PARAMETER = 87 - msg = FormatError(ERROR_INVALID_PARAMETER).strip() - args = (errno.EINVAL, msg, None, ERROR_INVALID_PARAMETER) - - e = 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) - try: - raise WinError() - except OSError as exc: - e = exc - self.assertEqual(e.args, args) - self.assertEqual(e.errno, errno.EINVAL) - self.assertEqual(e.winerror, ERROR_INVALID_PARAMETER) - class Structures(unittest.TestCase): def test_struct_by_value(self): class POINT(Structure): diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index 01176bf..ab10ec5 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -1,5 +1,4 @@ import os -import shutil import subprocess import sys @@ -20,8 +19,6 @@ if os.name == "nt": i = i + len(prefix) s, rest = sys.version[i:].split(" ", 1) majorVersion = int(s[:-2]) - 6 - if majorVersion >= 13: - majorVersion += 1 minorVersion = int(s[2:3]) / 10.0 # I don't think paths are affected by minor version in version 6 if majorVersion == 6: @@ -39,16 +36,12 @@ if os.name == "nt": return None if version <= 6: clibname = 'msvcrt' - elif version <= 13: - clibname = 'msvcr%d' % (version * 10) else: - # CRT is no longer directly loadable. See issue23606 for the - # discussion about alternative approaches. - return None + clibname = 'msvcr%d' % (version * 10) # If python was built with in debug mode - import importlib.machinery - if '_d.pyd' in importlib.machinery.EXTENSION_SUFFIXES: + import imp + if imp.get_suffixes()[0][0] == '_d.pyd': clibname += 'd' return clibname+'.dll' @@ -67,7 +60,17 @@ if os.name == "nt": return fname return None -elif os.name == "posix" and sys.platform == "darwin": +if os.name == "ce": + # search path according to MSDN: + # - absolute path specified by filename + # - The .exe launch directory + # - the Windows directory + # - ROM dll files (where are they?) + # - OEM specified search path: HKLM\Loader\SystemPath + def find_library(name): + return name + +if os.name == "posix" and sys.platform == "darwin": from ctypes.macholib.dyld import dyld_find as _dyld_find def find_library(name): possible = ['lib%s.dylib' % name, @@ -80,60 +83,37 @@ elif os.name == "posix" and sys.platform == "darwin": continue return None -elif sys.platform.startswith("aix"): - # AIX has two styles of storing shared libraries - # GNU auto_tools refer to these as svr4 and aix - # svr4 (System V Release 4) is a regular file, often with .so as suffix - # AIX style uses an archive (suffix .a) with members (e.g., shr.o, libssl.so) - # see issue#26439 and _aix.py for more details - - from ctypes._aix import find_library - elif os.name == "posix": # Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump - import re, tempfile + import re, tempfile, errno def _findLib_gcc(name): # Run GCC's linker with the -t (aka --trace) option and examine the # library name it prints out. The GCC command will fail because we # haven't supplied a proper program with main(), but that does not # matter. - expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) - - c_compiler = shutil.which('gcc') - if not c_compiler: - c_compiler = shutil.which('cc') - if not c_compiler: - # No C compiler available, give up - return None + expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) + cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; elif type cc >/dev/null 2>&1; then CC=cc;else exit; fi;' \ + 'LANG=C LC_ALL=C $CC -Wl,-t -o "$2" 2>&1 -l"$1"' temp = tempfile.NamedTemporaryFile() try: - args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] - - env = dict(os.environ) - env['LC_ALL'] = 'C' - env['LANG'] = 'C' - try: - proc = subprocess.Popen(args, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - env=env) - except OSError: # E.g. bad executable - return None - with proc: - trace = proc.stdout.read() + proc = subprocess.Popen((cmd, '_findLib_gcc', name, temp.name), + shell=True, + stdout=subprocess.PIPE) + [trace, _] = proc.communicate() finally: try: temp.close() - except FileNotFoundError: - # Raised if the file was already removed, which is the normal - # behaviour of GCC if linking fails - pass + except OSError, e: + # ENOENT is raised if the file was already removed, which is + # the normal behaviour of GCC if linking fails + if e.errno != errno.ENOENT: + raise res = re.search(expr, trace) if not res: return None - return os.fsdecode(res.group(0)) + return res.group(0) if sys.platform == "sunos5": @@ -142,42 +122,37 @@ elif os.name == "posix": if not f: return None + null = open(os.devnull, "wb") try: - proc = subprocess.Popen(("/usr/ccs/bin/dump", "-Lpv", f), - stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL) + with null: + proc = subprocess.Popen(("/usr/ccs/bin/dump", "-Lpv", f), + stdout=subprocess.PIPE, + stderr=null) except OSError: # E.g. command not found return None - with proc: - data = proc.stdout.read() + [data, _] = proc.communicate() res = re.search(br'\[.*\]\sSONAME\s+([^\s]+)', data) if not res: return None - return os.fsdecode(res.group(1)) + return res.group(1) else: def _get_soname(f): # assuming GNU binutils / ELF if not f: return None - objdump = shutil.which('objdump') - if not objdump: - # objdump is not available, give up - return None - - try: - proc = subprocess.Popen((objdump, '-p', '-j', '.dynamic', f), - stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL) - except OSError: # E.g. bad executable - return None - with proc: - dump = proc.stdout.read() + cmd = 'if ! type objdump >/dev/null 2>&1; then exit; fi;' \ + 'objdump -p -j .dynamic 2>/dev/null "$1"' + proc = subprocess.Popen((cmd, '_get_soname', f), shell=True, + stdout=subprocess.PIPE) + [dump, _] = proc.communicate() res = re.search(br'\sSONAME\s+([^\s]+)', dump) if not res: return None - return os.fsdecode(res.group(1)) + return res.group(1) - if sys.platform.startswith(("freebsd", "openbsd", "dragonfly")): + if (sys.platform.startswith("freebsd") + or sys.platform.startswith("openbsd") + or sys.platform.startswith("dragonfly")): def _num_version(libname): # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ] @@ -188,28 +163,28 @@ elif os.name == "posix": nums.insert(0, int(parts.pop())) except ValueError: pass - return nums or [sys.maxsize] + return nums or [sys.maxint] def find_library(name): ename = re.escape(name) expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename) - expr = os.fsencode(expr) + null = open(os.devnull, 'wb') try: - proc = subprocess.Popen(('/sbin/ldconfig', '-r'), - stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL) + with null: + proc = subprocess.Popen(('/sbin/ldconfig', '-r'), + stdout=subprocess.PIPE, + stderr=null) except OSError: # E.g. command not found data = b'' else: - with proc: - data = proc.stdout.read() + [data, _] = proc.communicate() res = re.findall(expr, data) if not res: return _get_soname(_findLib_gcc(name)) res.sort(key=_num_version) - return os.fsdecode(res[-1]) + return res[-1] elif sys.platform == "sunos5": @@ -226,18 +201,23 @@ elif os.name == "posix": args = ('/usr/bin/crle',) paths = None + null = open(os.devnull, 'wb') try: - proc = subprocess.Popen(args, - stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL, - env=env) + with null: + proc = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=null, + env=env) except OSError: # E.g. bad executable return None - with proc: + try: for line in proc.stdout: line = line.strip() if line.startswith(b'Default Library Path (ELF):'): - paths = os.fsdecode(line).split()[4] + paths = line.split()[4] + finally: + proc.stdout.close() + proc.wait() if not paths: return None @@ -257,9 +237,9 @@ elif os.name == "posix": def _findSoname_ldconfig(name): import struct if struct.calcsize('l') == 4: - machine = os.uname().machine + '-32' + machine = os.uname()[4] + '-32' else: - machine = os.uname().machine + '-64' + machine = os.uname()[4] + '-64' mach_map = { 'x86_64-64': 'libc6,x86-64', 'ppc64-64': 'libc6,64bit', @@ -270,46 +250,28 @@ elif os.name == "posix": abi_type = mach_map.get(machine, 'libc6') # XXX assuming GLIBC's ldconfig (with option -p) - regex = r'\s+(lib%s\.[^\s]+)\s+\(%s' - regex = os.fsencode(regex % (re.escape(name), abi_type)) - try: - with subprocess.Popen(['/sbin/ldconfig', '-p'], - stdin=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - stdout=subprocess.PIPE, - env={'LC_ALL': 'C', 'LANG': 'C'}) as p: - res = re.search(regex, p.stdout.read()) - if res: - return os.fsdecode(res.group(1)) - except OSError: - pass + expr = r'\s+(lib%s\.[^\s]+)\s+\(%s' % (re.escape(name), abi_type) - def _findLib_ld(name): - # See issue #9998 for why this is needed - expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) - cmd = ['ld', '-t'] - libpath = os.environ.get('LD_LIBRARY_PATH') - if libpath: - for d in libpath.split(':'): - cmd.extend(['-L', d]) - cmd.extend(['-o', os.devnull, '-l%s' % name]) - result = None + env = dict(os.environ) + env['LC_ALL'] = 'C' + env['LANG'] = 'C' + null = open(os.devnull, 'wb') try: - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True) - out, _ = p.communicate() - res = re.search(expr, os.fsdecode(out)) - if res: - result = res.group(0) - except Exception: - pass # result will be None - return result + with null: + p = subprocess.Popen(['/sbin/ldconfig', '-p'], + stderr=null, + stdout=subprocess.PIPE, + env=env) + except OSError: # E.g. command not found + return None + [data, _] = p.communicate() + res = re.search(expr, data) + if not res: + return None + return res.group(1) def find_library(name): - # See issue #9998 - return _findSoname_ldconfig(name) or \ - _get_soname(_findLib_gcc(name) or _findLib_ld(name)) + return _findSoname_ldconfig(name) or _get_soname(_findLib_gcc(name)) ################################################################ # test code @@ -317,42 +279,30 @@ elif os.name == "posix": def test(): from ctypes import cdll if os.name == "nt": - print(cdll.msvcrt) - print(cdll.load("msvcrt")) - print(find_library("msvcrt")) + print cdll.msvcrt + print cdll.load("msvcrt") + print find_library("msvcrt") if os.name == "posix": # find and load_version - print(find_library("m")) - print(find_library("c")) - print(find_library("bz2")) + print find_library("m") + print find_library("c") + print find_library("bz2") + + # getattr +## print cdll.m +## print cdll.bz2 # load if sys.platform == "darwin": - print(cdll.LoadLibrary("libm.dylib")) - print(cdll.LoadLibrary("libcrypto.dylib")) - print(cdll.LoadLibrary("libSystem.dylib")) - print(cdll.LoadLibrary("System.framework/System")) - # issue-26439 - fix broken test call for AIX - elif sys.platform.startswith("aix"): - from ctypes import CDLL - if sys.maxsize < 2**32: - print(f"Using CDLL(name, os.RTLD_MEMBER): {CDLL('libc.a(shr.o)', os.RTLD_MEMBER)}") - print(f"Using cdll.LoadLibrary(): {cdll.LoadLibrary('libc.a(shr.o)')}") - # librpm.so is only available as 32-bit shared library - print(find_library("rpm")) - print(cdll.LoadLibrary("librpm.so")) - else: - print(f"Using CDLL(name, os.RTLD_MEMBER): {CDLL('libc.a(shr_64.o)', os.RTLD_MEMBER)}") - print(f"Using cdll.LoadLibrary(): {cdll.LoadLibrary('libc.a(shr_64.o)')}") - print(f"crypt\t:: {find_library('crypt')}") - print(f"crypt\t:: {cdll.LoadLibrary(find_library('crypt'))}") - print(f"crypto\t:: {find_library('crypto')}") - print(f"crypto\t:: {cdll.LoadLibrary(find_library('crypto'))}") + print cdll.LoadLibrary("libm.dylib") + print cdll.LoadLibrary("libcrypto.dylib") + print cdll.LoadLibrary("libSystem.dylib") + print cdll.LoadLibrary("System.framework/System") else: - print(cdll.LoadLibrary("libm.so")) - print(cdll.LoadLibrary("libcrypt.so")) - print(find_library("crypt")) + print cdll.LoadLibrary("libm.so") + print cdll.LoadLibrary("libcrypt.so") + print find_library("crypt") if __name__ == "__main__": test() diff --git a/Lib/ctypes/wintypes.py b/Lib/ctypes/wintypes.py index c619d27..e7f569c 100644 --- a/Lib/ctypes/wintypes.py +++ b/Lib/ctypes/wintypes.py @@ -1,50 +1,49 @@ # The most useful windows datatypes -import ctypes +from ctypes import * -BYTE = ctypes.c_byte -WORD = ctypes.c_ushort -DWORD = ctypes.c_ulong +BYTE = c_byte +WORD = c_ushort +DWORD = c_ulong -#UCHAR = ctypes.c_uchar -CHAR = ctypes.c_char -WCHAR = ctypes.c_wchar -UINT = ctypes.c_uint -INT = ctypes.c_int +WCHAR = c_wchar +UINT = c_uint +INT = c_int -DOUBLE = ctypes.c_double -FLOAT = ctypes.c_float +DOUBLE = c_double +FLOAT = c_float BOOLEAN = BYTE -BOOL = ctypes.c_long +BOOL = c_long -class VARIANT_BOOL(ctypes._SimpleCData): +from ctypes import _SimpleCData +class VARIANT_BOOL(_SimpleCData): _type_ = "v" def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self.value) -ULONG = ctypes.c_ulong -LONG = ctypes.c_long +ULONG = c_ulong +LONG = c_long -USHORT = ctypes.c_ushort -SHORT = ctypes.c_short +USHORT = c_ushort +SHORT = c_short # in the windows header files, these are structures. -_LARGE_INTEGER = LARGE_INTEGER = ctypes.c_longlong -_ULARGE_INTEGER = ULARGE_INTEGER = ctypes.c_ulonglong +_LARGE_INTEGER = LARGE_INTEGER = c_longlong +_ULARGE_INTEGER = ULARGE_INTEGER = c_ulonglong -LPCOLESTR = LPOLESTR = OLESTR = ctypes.c_wchar_p -LPCWSTR = LPWSTR = ctypes.c_wchar_p -LPCSTR = LPSTR = ctypes.c_char_p -LPCVOID = LPVOID = ctypes.c_void_p +LPCOLESTR = LPOLESTR = OLESTR = c_wchar_p +LPCWSTR = LPWSTR = c_wchar_p +LPCSTR = LPSTR = c_char_p +LPCVOID = LPVOID = c_void_p # WPARAM is defined as UINT_PTR (unsigned type) # LPARAM is defined as LONG_PTR (signed type) -if ctypes.sizeof(ctypes.c_long) == ctypes.sizeof(ctypes.c_void_p): - WPARAM = ctypes.c_ulong - LPARAM = ctypes.c_long -elif ctypes.sizeof(ctypes.c_longlong) == ctypes.sizeof(ctypes.c_void_p): - WPARAM = ctypes.c_ulonglong - LPARAM = ctypes.c_longlong +if sizeof(c_long) == sizeof(c_void_p): + WPARAM = c_ulong + LPARAM = c_long +elif sizeof(c_longlong) == sizeof(c_void_p): + WPARAM = c_ulonglong + LPARAM = c_longlong ATOM = WORD LANGID = WORD @@ -57,7 +56,7 @@ LCID = DWORD ################################################################ # HANDLE types -HANDLE = ctypes.c_void_p # in the header files: void * +HANDLE = c_void_p # in the header files: void * HACCEL = HANDLE HBITMAP = HANDLE @@ -94,45 +93,45 @@ SERVICE_STATUS_HANDLE = HANDLE ################################################################ # Some important structure definitions -class RECT(ctypes.Structure): - _fields_ = [("left", LONG), - ("top", LONG), - ("right", LONG), - ("bottom", LONG)] +class RECT(Structure): + _fields_ = [("left", c_long), + ("top", c_long), + ("right", c_long), + ("bottom", c_long)] tagRECT = _RECTL = RECTL = RECT -class _SMALL_RECT(ctypes.Structure): - _fields_ = [('Left', SHORT), - ('Top', SHORT), - ('Right', SHORT), - ('Bottom', SHORT)] +class _SMALL_RECT(Structure): + _fields_ = [('Left', c_short), + ('Top', c_short), + ('Right', c_short), + ('Bottom', c_short)] SMALL_RECT = _SMALL_RECT -class _COORD(ctypes.Structure): - _fields_ = [('X', SHORT), - ('Y', SHORT)] +class _COORD(Structure): + _fields_ = [('X', c_short), + ('Y', c_short)] -class POINT(ctypes.Structure): - _fields_ = [("x", LONG), - ("y", LONG)] +class POINT(Structure): + _fields_ = [("x", c_long), + ("y", c_long)] tagPOINT = _POINTL = POINTL = POINT -class SIZE(ctypes.Structure): - _fields_ = [("cx", LONG), - ("cy", LONG)] +class SIZE(Structure): + _fields_ = [("cx", c_long), + ("cy", c_long)] tagSIZE = SIZEL = SIZE def RGB(red, green, blue): return red + (green << 8) + (blue << 16) -class FILETIME(ctypes.Structure): +class FILETIME(Structure): _fields_ = [("dwLowDateTime", DWORD), ("dwHighDateTime", DWORD)] _FILETIME = FILETIME -class MSG(ctypes.Structure): +class MSG(Structure): _fields_ = [("hWnd", HWND), - ("message", UINT), + ("message", c_uint), ("wParam", WPARAM), ("lParam", LPARAM), ("time", DWORD), @@ -140,7 +139,7 @@ class MSG(ctypes.Structure): tagMSG = MSG MAX_PATH = 260 -class WIN32_FIND_DATAA(ctypes.Structure): +class WIN32_FIND_DATAA(Structure): _fields_ = [("dwFileAttributes", DWORD), ("ftCreationTime", FILETIME), ("ftLastAccessTime", FILETIME), @@ -149,10 +148,10 @@ class WIN32_FIND_DATAA(ctypes.Structure): ("nFileSizeLow", DWORD), ("dwReserved0", DWORD), ("dwReserved1", DWORD), - ("cFileName", CHAR * MAX_PATH), - ("cAlternateFileName", CHAR * 14)] + ("cFileName", c_char * MAX_PATH), + ("cAlternateFileName", c_char * 14)] -class WIN32_FIND_DATAW(ctypes.Structure): +class WIN32_FIND_DATAW(Structure): _fields_ = [("dwFileAttributes", DWORD), ("ftCreationTime", FILETIME), ("ftLastAccessTime", FILETIME), @@ -161,42 +160,22 @@ class WIN32_FIND_DATAW(ctypes.Structure): ("nFileSizeLow", DWORD), ("dwReserved0", DWORD), ("dwReserved1", DWORD), - ("cFileName", WCHAR * MAX_PATH), - ("cAlternateFileName", WCHAR * 14)] - -################################################################ -# Pointer types - -LPBOOL = PBOOL = ctypes.POINTER(BOOL) -PBOOLEAN = ctypes.POINTER(BOOLEAN) -LPBYTE = PBYTE = ctypes.POINTER(BYTE) -PCHAR = ctypes.POINTER(CHAR) -LPCOLORREF = ctypes.POINTER(COLORREF) -LPDWORD = PDWORD = ctypes.POINTER(DWORD) -LPFILETIME = PFILETIME = ctypes.POINTER(FILETIME) -PFLOAT = ctypes.POINTER(FLOAT) -LPHANDLE = PHANDLE = ctypes.POINTER(HANDLE) -PHKEY = ctypes.POINTER(HKEY) -LPHKL = ctypes.POINTER(HKL) -LPINT = PINT = ctypes.POINTER(INT) -PLARGE_INTEGER = ctypes.POINTER(LARGE_INTEGER) -PLCID = ctypes.POINTER(LCID) -LPLONG = PLONG = ctypes.POINTER(LONG) -LPMSG = PMSG = ctypes.POINTER(MSG) -LPPOINT = PPOINT = ctypes.POINTER(POINT) -PPOINTL = ctypes.POINTER(POINTL) -LPRECT = PRECT = ctypes.POINTER(RECT) -LPRECTL = PRECTL = ctypes.POINTER(RECTL) -LPSC_HANDLE = ctypes.POINTER(SC_HANDLE) -PSHORT = ctypes.POINTER(SHORT) -LPSIZE = PSIZE = ctypes.POINTER(SIZE) -LPSIZEL = PSIZEL = ctypes.POINTER(SIZEL) -PSMALL_RECT = ctypes.POINTER(SMALL_RECT) -LPUINT = PUINT = ctypes.POINTER(UINT) -PULARGE_INTEGER = ctypes.POINTER(ULARGE_INTEGER) -PULONG = ctypes.POINTER(ULONG) -PUSHORT = ctypes.POINTER(USHORT) -PWCHAR = ctypes.POINTER(WCHAR) -LPWIN32_FIND_DATAA = PWIN32_FIND_DATAA = ctypes.POINTER(WIN32_FIND_DATAA) -LPWIN32_FIND_DATAW = PWIN32_FIND_DATAW = ctypes.POINTER(WIN32_FIND_DATAW) -LPWORD = PWORD = ctypes.POINTER(WORD) + ("cFileName", c_wchar * MAX_PATH), + ("cAlternateFileName", c_wchar * 14)] + +__all__ = ['ATOM', 'BOOL', 'BOOLEAN', 'BYTE', 'COLORREF', 'DOUBLE', 'DWORD', + 'FILETIME', 'FLOAT', 'HACCEL', 'HANDLE', 'HBITMAP', 'HBRUSH', + 'HCOLORSPACE', 'HDC', 'HDESK', 'HDWP', 'HENHMETAFILE', 'HFONT', + 'HGDIOBJ', 'HGLOBAL', 'HHOOK', 'HICON', 'HINSTANCE', 'HKEY', + 'HKL', 'HLOCAL', 'HMENU', 'HMETAFILE', 'HMODULE', 'HMONITOR', + 'HPALETTE', 'HPEN', 'HRGN', 'HRSRC', 'HSTR', 'HTASK', 'HWINSTA', + 'HWND', 'INT', 'LANGID', 'LARGE_INTEGER', 'LCID', 'LCTYPE', + 'LGRPID', 'LONG', 'LPARAM', 'LPCOLESTR', 'LPCSTR', 'LPCVOID', + 'LPCWSTR', 'LPOLESTR', 'LPSTR', 'LPVOID', 'LPWSTR', 'MAX_PATH', + 'MSG', 'OLESTR', 'POINT', 'POINTL', 'RECT', 'RECTL', 'RGB', + 'SC_HANDLE', 'SERVICE_STATUS_HANDLE', 'SHORT', 'SIZE', 'SIZEL', + 'SMALL_RECT', 'UINT', 'ULARGE_INTEGER', 'ULONG', 'USHORT', + 'VARIANT_BOOL', 'WCHAR', 'WIN32_FIND_DATAA', 'WIN32_FIND_DATAW', + 'WORD', 'WPARAM', '_COORD', '_FILETIME', '_LARGE_INTEGER', + '_POINTL', '_RECTL', '_SMALL_RECT', '_ULARGE_INTEGER', 'tagMSG', + 'tagPOINT', 'tagRECT', 'tagSIZE'] |