diff options
author | Thomas Wouters <thomas@python.org> | 2006-04-21 10:40:58 (GMT) |
---|---|---|
committer | Thomas Wouters <thomas@python.org> | 2006-04-21 10:40:58 (GMT) |
commit | 49fd7fa4431da299196d74087df4a04f99f9c46f (patch) | |
tree | 35ace5fe78d3d52c7a9ab356ab9f6dbf8d4b71f4 /Lib/ctypes | |
parent | 9ada3d6e29d5165dadacbe6be07bcd35cfbef59d (diff) | |
download | cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.zip cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.gz cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.bz2 |
Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
number of tests, all because of the codecs/_multibytecodecs issue described
here (it's not a Py3K issue, just something Py3K discovers):
http://mail.python.org/pipermail/python-dev/2006-April/064051.html
Hye-Shik Chang promised to look for a fix, so no need to fix it here. The
tests that are expected to break are:
test_codecencodings_cn
test_codecencodings_hk
test_codecencodings_jp
test_codecencodings_kr
test_codecencodings_tw
test_codecs
test_multibytecodec
This merge fixes an actual test failure (test_weakref) in this branch,
though, so I believe merging is the right thing to do anyway.
Diffstat (limited to 'Lib/ctypes')
-rw-r--r-- | Lib/ctypes/__init__.py | 31 | ||||
-rw-r--r-- | Lib/ctypes/_loader.py | 12 | ||||
-rw-r--r-- | Lib/ctypes/test/test_byteswap.py | 70 | ||||
-rw-r--r-- | Lib/ctypes/test/test_cfuncs.py | 2 | ||||
-rw-r--r-- | Lib/ctypes/test/test_keeprefs.py | 5 | ||||
-rw-r--r-- | Lib/ctypes/test/test_loading.py | 80 | ||||
-rw-r--r-- | Lib/ctypes/test/test_pointers.py | 12 | ||||
-rw-r--r-- | Lib/ctypes/test/test_posix.py | 6 | ||||
-rw-r--r-- | Lib/ctypes/test/test_prototypes.py | 16 | ||||
-rw-r--r-- | Lib/ctypes/test/test_random_things.py | 10 | ||||
-rw-r--r-- | Lib/ctypes/test/test_sizes.py | 3 | ||||
-rw-r--r-- | Lib/ctypes/test/test_unaligned_structures.py | 45 |
12 files changed, 233 insertions, 59 deletions
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index dd0f640..28ac180 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -9,11 +9,7 @@ from _ctypes import Union, Structure, Array from _ctypes import _Pointer from _ctypes import CFuncPtr as _CFuncPtr from _ctypes import __version__ as _ctypes_version -try: - from _ctypes import RTLD_LOCAL, RTLD_GLOBAL -except (ImportError, AttributeError): - RTLD_GLOBAL = RTLD_LOCAL = None - +from _ctypes import RTLD_LOCAL, RTLD_GLOBAL from _ctypes import ArgumentError from struct import calcsize as _calcsize @@ -304,10 +300,11 @@ class CDLL(object): raise AttributeError, name return self.__getitem__(name) - def __getitem__(self, name): - func = self._FuncPtr(name, self) - func.__name__ = name - setattr(self, name, func) + def __getitem__(self, name_or_ordinal): + func = self._FuncPtr((name_or_ordinal, self)) + if not isinstance(name_or_ordinal, (int, long)): + func.__name__ = name_or_ordinal + setattr(self, name_or_ordinal, func) return func class PyDLL(CDLL): @@ -384,21 +381,29 @@ if _os.name in ("nt", "ce"): _pointer_type_cache[None] = c_void_p -# functions - -from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, cast - if sizeof(c_uint) == sizeof(c_void_p): c_size_t = c_uint elif sizeof(c_ulong) == sizeof(c_void_p): c_size_t = c_ulong +# functions + +from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr + ## void *memmove(void *, const void *, size_t); memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr) ## void *memset(void *, int, size_t) memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr) +def PYFUNCTYPE(restype, *argtypes): + class CFunctionType(_CFuncPtr): + _argtypes_ = argtypes + _restype_ = restype + _flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI + return CFunctionType +cast = PYFUNCTYPE(py_object, c_void_p, py_object)(_cast_addr) + _string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) def string_at(ptr, size=0): """string_at(addr[, size]) -> string diff --git a/Lib/ctypes/_loader.py b/Lib/ctypes/_loader.py index 7bde6c6..7a48c1c 100644 --- a/Lib/ctypes/_loader.py +++ b/Lib/ctypes/_loader.py @@ -1,14 +1,11 @@ -# WORK IN PROGRESS! DO NOT (yet) USE! import sys, os import ctypes -__all__ = ["LibraryLoader", "RTLD_LOCAL", "RTLD_GLOBAL"] - if os.name in ("nt", "ce"): from _ctypes import LoadLibrary as dlopen - RTLD_LOCAL = RTLD_GLOBAL = None else: - from _ctypes import dlopen, RTLD_LOCAL, RTLD_GLOBAL + from _ctypes import dlopen +from _ctypes import RTLD_LOCAL, RTLD_GLOBAL # _findLib(name) returns an iterable of possible names for a library. if os.name in ("nt", "ce"): @@ -56,7 +53,10 @@ elif os.name == "posix": expr = '/[^\(\)\s]*lib%s\.[^\(\)\s]*' % name res = re.search(expr, os.popen('/sbin/ldconfig -p 2>/dev/null').read()) if not res: - return None + cmd = 'ldd %s 2>/dev/null' % sys.executable + res = re.search(expr, os.popen(cmd).read()) + if not res: + return None return res.group(0) def _get_soname(f): diff --git a/Lib/ctypes/test/test_byteswap.py b/Lib/ctypes/test/test_byteswap.py index 1b31f90..d0ada40 100644 --- a/Lib/ctypes/test/test_byteswap.py +++ b/Lib/ctypes/test/test_byteswap.py @@ -149,7 +149,7 @@ class Test(unittest.TestCase): self.failUnless(c_char.__ctype_le__ is c_char) self.failUnless(c_char.__ctype_be__ is c_char) - def test_struct_fields(self): + def test_struct_fields_1(self): if sys.byteorder == "little": base = BigEndianStructure else: @@ -198,17 +198,20 @@ class Test(unittest.TestCase): pass self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)]) - # crashes on solaris with a core dump. - def X_test_struct_fields(self): + def test_struct_fields_2(self): + # standard packing in struct uses no alignment. + # So, we have to align using pad bytes. + # + # Unaligned accesses will crash Python (on those platforms that + # don't allow it, like sparc solaris). if sys.byteorder == "little": base = BigEndianStructure - fmt = ">bhid" + fmt = ">bxhid" else: base = LittleEndianStructure - fmt = "<bhid" + fmt = "<bxhid" class S(base): - _pack_ = 1 # struct with '<' or '>' uses standard alignment. _fields_ = [("b", c_byte), ("h", c_short), ("i", c_int), @@ -218,5 +221,60 @@ class Test(unittest.TestCase): s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) self.failUnlessEqual(bin(s1), bin(s2)) + def test_unaligned_nonnative_struct_fields(self): + if sys.byteorder == "little": + base = BigEndianStructure + fmt = ">b h xi xd" + else: + base = LittleEndianStructure + fmt = "<b h xi xd" + + class S(base): + _pack_ = 1 + _fields_ = [("b", c_byte), + + ("h", c_short), + + ("_1", c_byte), + ("i", c_int), + + ("_2", c_byte), + ("d", c_double)] + + s1 = S() + s1.b = 0x12 + s1.h = 0x1234 + s1.i = 0x12345678 + s1.d = 3.14 + s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) + self.failUnlessEqual(bin(s1), bin(s2)) + + def test_unaligned_native_struct_fields(self): + if sys.byteorder == "little": + fmt = "<b h xi xd" + else: + base = LittleEndianStructure + fmt = ">b h xi xd" + + class S(Structure): + _pack_ = 1 + _fields_ = [("b", c_byte), + + ("h", c_short), + + ("_1", c_byte), + ("i", c_int), + + ("_2", c_byte), + ("d", c_double)] + + s1 = S() + s1.b = 0x12 + s1.h = 0x1234 + s1.i = 0x12345678 + s1.d = 3.14 + s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14) + self.failUnlessEqual(bin(s1), bin(s2)) + if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_cfuncs.py b/Lib/ctypes/test/test_cfuncs.py index 7c2b28b..6e0798d 100644 --- a/Lib/ctypes/test/test_cfuncs.py +++ b/Lib/ctypes/test/test_cfuncs.py @@ -179,7 +179,7 @@ else: def __getattr__(self, name): if name[:2] == '__' and name[-2:] == '__': raise AttributeError, name - func = self._FuncPtr("s_" + name, self) + func = self._FuncPtr(("s_" + name, self)) setattr(self, name, func) return func diff --git a/Lib/ctypes/test/test_keeprefs.py b/Lib/ctypes/test/test_keeprefs.py index 39e70e3..7318f29 100644 --- a/Lib/ctypes/test/test_keeprefs.py +++ b/Lib/ctypes/test/test_keeprefs.py @@ -140,5 +140,10 @@ class PointerToStructure(unittest.TestCase): r.a[0].x = 42 r.a[0].y = 99 + # to avoid leaking when tests are run several times + # clean up the types left in the cache. + from ctypes import _pointer_type_cache + del _pointer_type_cache[POINT] + if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_loading.py b/Lib/ctypes/test/test_loading.py index 80564b8..4558417 100644 --- a/Lib/ctypes/test/test_loading.py +++ b/Lib/ctypes/test/test_loading.py @@ -2,40 +2,72 @@ from ctypes import * import sys, unittest import os, StringIO +libc_name = None +if os.name == "nt": + libc_name = "msvcrt" +elif os.name == "ce": + libc_name = "coredll" +elif sys.platform == "darwin": + libc_name = "libc.dylib" +elif sys.platform == "cygwin": + libc_name = "cygwin1.dll" +else: + for line in os.popen("ldd %s" % sys.executable): + if "libc.so" in line: + if sys.platform == "openbsd3": + libc_name = line.split()[4] + else: + libc_name = line.split()[2] +## print "libc_name is", libc_name + break + class LoaderTest(unittest.TestCase): unknowndll = "xxrandomnamexx" - def test_load(self): - if os.name == "nt": - name = "msvcrt" - elif os.name == "ce": - name = "coredll" - elif sys.platform == "darwin": - name = "libc.dylib" - elif sys.platform.startswith("freebsd"): - name = "libc.so" - elif sys.platform == "sunos5": - name = "libc.so" - else: - name = "libc.so.6" - cdll.load(name) - self.assertRaises(OSError, cdll.load, self.unknowndll) - - def test_load_version(self): - version = "6" - name = "c" - if sys.platform == "linux2": - cdll.load_version(name, version) + if libc_name is not None: + def test_load(self): + cdll.load(libc_name) + cdll.load(os.path.basename(libc_name)) + self.assertRaises(OSError, cdll.load, self.unknowndll) + + if libc_name is not None and os.path.basename(libc_name) == "libc.so.6": + def test_load_version(self): + cdll.load_version("c", "6") # linux uses version, libc 9 should not exist - self.assertRaises(OSError, cdll.load_version, name, "9") - self.assertRaises(OSError, cdll.load_version, self.unknowndll, "") + self.assertRaises(OSError, cdll.load_version, "c", "9") + self.assertRaises(OSError, cdll.load_version, self.unknowndll, "") - if os.name == "posix" and sys.platform != "sunos5": def test_find(self): name = "c" cdll.find(name) self.assertRaises(OSError, cdll.find, self.unknowndll) + if os.name in ("nt", "ce"): + def test_load_library(self): + if os.name == "nt": + windll.load_library("kernel32").GetModuleHandleW + windll.LoadLibrary("kernel32").GetModuleHandleW + WinDLL("kernel32").GetModuleHandleW + elif os.name == "ce": + windll.load_library("coredll").GetModuleHandleW + windll.LoadLibrary("coredll").GetModuleHandleW + WinDLL("coredll").GetModuleHandleW + + def test_load_ordinal_functions(self): + import _ctypes_test + dll = WinDLL(_ctypes_test.__file__) + # We load the same function both via ordinal and name + func_ord = dll[2] + func_name = dll.GetString + # addressof gets the address where the function pointer is stored + a_ord = addressof(func_ord) + a_name = addressof(func_name) + f_ord_addr = c_void_p.from_address(a_ord).value + f_name_addr = c_void_p.from_address(a_name).value + self.failUnlessEqual(hex(f_ord_addr), hex(f_name_addr)) + + self.failUnlessRaises(AttributeError, dll.__getitem__, 1234) + if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_pointers.py b/Lib/ctypes/test/test_pointers.py index 6172abb..3a324a6 100644 --- a/Lib/ctypes/test/test_pointers.py +++ b/Lib/ctypes/test/test_pointers.py @@ -166,6 +166,18 @@ class PointersTestCase(unittest.TestCase): result = func( byref(argc), argv ) assert result == 'world', result + def test_bug_1467852(self): + # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702 + x = c_int(5) + dummy = [] + for i in range(32000): + dummy.append(c_int(i)) + y = c_int(6) + p = pointer(x) + pp = pointer(p) + q = pointer(y) + pp[0] = q # <== + self.failUnlessEqual(p[0], 6) if __name__ == '__main__': unittest.main() diff --git a/Lib/ctypes/test/test_posix.py b/Lib/ctypes/test/test_posix.py index 2b4fdff..fe0a40a 100644 --- a/Lib/ctypes/test/test_posix.py +++ b/Lib/ctypes/test/test_posix.py @@ -8,8 +8,10 @@ if os.name == "posix" and sys.platform == "linux2": class TestRTLD_GLOBAL(unittest.TestCase): def test_GL(self): - cdll.load('libGL.so', mode=RTLD_GLOBAL) - cdll.load('libGLU.so') + if os.path.exists('/usr/lib/libGL.so'): + cdll.load('libGL.so', mode=RTLD_GLOBAL) + if os.path.exists('/usr/lib/libGLU.so'): + cdll.load('libGLU.so') ##if os.name == "posix" and sys.platform != "darwin": diff --git a/Lib/ctypes/test/test_prototypes.py b/Lib/ctypes/test/test_prototypes.py index 2c3d75b..47f5da1 100644 --- a/Lib/ctypes/test/test_prototypes.py +++ b/Lib/ctypes/test/test_prototypes.py @@ -24,6 +24,19 @@ import unittest import _ctypes_test testdll = cdll.load(_ctypes_test.__file__) +# Return machine address `a` as a (possibly long) non-negative integer. +# Starting with Python 2.5, id(anything) is always non-negative, and +# the ctypes addressof() inherits that via PyLong_FromVoidPtr(). +def positive_address(a): + if a >= 0: + return a + # View the bits in `a` as unsigned instead. + import struct + num_bits = struct.calcsize("P") * 8 # num bits in native machine address + a += 1L << num_bits + assert a >= 0 + return a + def c_wbuffer(init): n = len(init) + 1 return (c_wchar * n)(*init) @@ -43,7 +56,8 @@ class CharPointersTestCase(unittest.TestCase): ci = c_int(0) func.argtypes = POINTER(c_int), - self.failUnlessEqual(addressof(ci), func(byref(ci))) + self.failUnlessEqual(positive_address(addressof(ci)), + positive_address(func(byref(ci)))) func.argtypes = c_char_p, self.assertRaises(ArgumentError, func, byref(ci)) diff --git a/Lib/ctypes/test/test_random_things.py b/Lib/ctypes/test/test_random_things.py index cd50ca8..78a665b 100644 --- a/Lib/ctypes/test/test_random_things.py +++ b/Lib/ctypes/test/test_random_things.py @@ -51,16 +51,14 @@ class CallbackTracbackTestCase(unittest.TestCase): def test_IntegerDivisionError(self): cb = CFUNCTYPE(c_int, c_int)(callback_func) out = self.capture_stderr(cb, 0) - self.failUnlessEqual(out.splitlines()[-1], - "ZeroDivisionError: " - "integer division or modulo by zero") + self.failUnlessEqual(out.splitlines()[-1][:19], + "ZeroDivisionError: ") def test_FloatDivisionError(self): cb = CFUNCTYPE(c_int, c_double)(callback_func) out = self.capture_stderr(cb, 0.0) - self.failUnlessEqual(out.splitlines()[-1], - "ZeroDivisionError: " - "float division") + self.failUnlessEqual(out.splitlines()[-1][:19], + "ZeroDivisionError: ") def test_TypeErrorDivisionError(self): cb = CFUNCTYPE(c_int, c_char_p)(callback_func) diff --git a/Lib/ctypes/test/test_sizes.py b/Lib/ctypes/test/test_sizes.py index 6fb9ca0..208c00e 100644 --- a/Lib/ctypes/test/test_sizes.py +++ b/Lib/ctypes/test/test_sizes.py @@ -20,5 +20,8 @@ class SizesTestCase(unittest.TestCase): self.failUnlessEqual(8, sizeof(c_int64)) self.failUnlessEqual(8, sizeof(c_uint64)) + def test_size_t(self): + self.failUnlessEqual(sizeof(c_void_p), sizeof(c_size_t)) + if __name__ == "__main__": unittest.main() diff --git a/Lib/ctypes/test/test_unaligned_structures.py b/Lib/ctypes/test/test_unaligned_structures.py new file mode 100644 index 0000000..89343ba --- /dev/null +++ b/Lib/ctypes/test/test_unaligned_structures.py @@ -0,0 +1,45 @@ +import sys, unittest +from ctypes import * + +structures = [] +byteswapped_structures = [] + + +if sys.byteorder == "little": + SwappedStructure = BigEndianStructure +else: + SwappedStructure = LittleEndianStructure + +for typ in [c_short, c_int, c_long, c_longlong, + c_float, c_double, + c_ushort, c_uint, c_ulong, c_ulonglong]: + class X(Structure): + _pack_ = 1 + _fields_ = [("pad", c_byte), + ("value", typ)] + class Y(SwappedStructure): + _pack_ = 1 + _fields_ = [("pad", c_byte), + ("value", typ)] + structures.append(X) + byteswapped_structures.append(Y) + +class TestStructures(unittest.TestCase): + def test_native(self): + for typ in structures: +## print typ.value + self.failUnlessEqual(typ.value.offset, 1) + o = typ() + o.value = 4 + self.failUnlessEqual(o.value, 4) + + def test_swapped(self): + for typ in byteswapped_structures: +## print >> sys.stderr, typ.value + self.failUnlessEqual(typ.value.offset, 1) + o = typ() + o.value = 4 + self.failUnlessEqual(o.value, 4) + +if __name__ == '__main__': + unittest.main() |