mirror of https://github.com/python/cpython
gh-103092: Test _ctypes type hierarchy and features (#113727)
Test the following features for _ctypes types: - disallow instantiation - inheritance (MRO) - immutability - type name The following _ctypes types are tested: - Array - CField - COMError - PyCArrayType - PyCFuncPtrType - PyCPointerType - PyCSimpleType - PyCStructType - Structure - Union - UnionType - _CFuncPtr - _Pointer - _SimpleCData Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
This commit is contained in:
parent
c31be58da8
commit
be89ee5649
|
@ -0,0 +1,24 @@
|
|||
# Some classes and types are not export to _ctypes module directly.
|
||||
|
||||
import ctypes
|
||||
from _ctypes import Structure, Union, _Pointer, Array, _SimpleCData, CFuncPtr
|
||||
|
||||
|
||||
_CData = Structure.__base__
|
||||
assert _CData.__name__ == "_CData"
|
||||
|
||||
class _X(Structure):
|
||||
_fields_ = [("x", ctypes.c_int)]
|
||||
CField = type(_X.x)
|
||||
|
||||
# metaclasses
|
||||
PyCStructType = type(Structure)
|
||||
UnionType = type(Union)
|
||||
PyCPointerType = type(_Pointer)
|
||||
PyCArrayType = type(Array)
|
||||
PyCSimpleType = type(_SimpleCData)
|
||||
PyCFuncPtrType = type(CFuncPtr)
|
||||
|
||||
# type flags
|
||||
Py_TPFLAGS_DISALLOW_INSTANTIATION = 1 << 7
|
||||
Py_TPFLAGS_IMMUTABLETYPE = 1 << 8
|
|
@ -7,6 +7,8 @@ from ctypes import (Structure, Array, sizeof, addressof,
|
|||
c_char, c_wchar, c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
|
||||
c_long, c_ulonglong, c_float, c_double, c_longdouble)
|
||||
from test.support import bigmemtest, _2G
|
||||
from ._support import (_CData, PyCArrayType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
Py_TPFLAGS_IMMUTABLETYPE)
|
||||
|
||||
|
||||
formats = "bBhHiIlLqQfd"
|
||||
|
@ -23,6 +25,18 @@ def ARRAY(*args):
|
|||
|
||||
|
||||
class ArrayTestCase(unittest.TestCase):
|
||||
def test_inheritance_hierarchy(self):
|
||||
self.assertEqual(Array.mro(), [Array, _CData, object])
|
||||
|
||||
self.assertEqual(PyCArrayType.__name__, "PyCArrayType")
|
||||
self.assertEqual(type(PyCArrayType), type)
|
||||
|
||||
def test_type_flags(self):
|
||||
for cls in Array, PyCArrayType:
|
||||
with self.subTest(cls=cls):
|
||||
self.assertTrue(cls.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
|
||||
self.assertFalse(cls.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
|
||||
|
||||
def test_simple(self):
|
||||
# create classes holding simple numeric types, and check
|
||||
# various properties.
|
||||
|
|
|
@ -3,6 +3,8 @@ import ctypes
|
|||
import unittest
|
||||
from ctypes import (CDLL, Structure, CFUNCTYPE, sizeof, _CFuncPtr,
|
||||
c_void_p, c_char_p, c_char, c_int, c_uint, c_long)
|
||||
from ._support import (_CData, PyCFuncPtrType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
Py_TPFLAGS_IMMUTABLETYPE)
|
||||
|
||||
|
||||
try:
|
||||
|
@ -15,6 +17,18 @@ lib = CDLL(_ctypes_test.__file__)
|
|||
|
||||
|
||||
class CFuncPtrTestCase(unittest.TestCase):
|
||||
def test_inheritance_hierarchy(self):
|
||||
self.assertEqual(_CFuncPtr.mro(), [_CFuncPtr, _CData, object])
|
||||
|
||||
self.assertEqual(PyCFuncPtrType.__name__, "PyCFuncPtrType")
|
||||
self.assertEqual(type(PyCFuncPtrType), type)
|
||||
|
||||
def test_type_flags(self):
|
||||
for cls in _CFuncPtr, PyCFuncPtrType:
|
||||
with self.subTest(cls=cls):
|
||||
self.assertTrue(_CFuncPtr.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
|
||||
self.assertFalse(_CFuncPtr.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
|
||||
|
||||
def test_basic(self):
|
||||
X = WINFUNCTYPE(c_int, c_int, c_int)
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ from ctypes import (CDLL, CFUNCTYPE, Structure,
|
|||
c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
|
||||
c_long, c_ulong, c_longlong, c_ulonglong,
|
||||
c_float, c_double)
|
||||
from ._support import (_CData, PyCPointerType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
Py_TPFLAGS_IMMUTABLETYPE)
|
||||
|
||||
|
||||
ctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
|
||||
|
@ -19,6 +21,18 @@ python_types = [int, int, int, int, int, int,
|
|||
|
||||
|
||||
class PointersTestCase(unittest.TestCase):
|
||||
def test_inheritance_hierarchy(self):
|
||||
self.assertEqual(_Pointer.mro(), [_Pointer, _CData, object])
|
||||
|
||||
self.assertEqual(PyCPointerType.__name__, "PyCPointerType")
|
||||
self.assertEqual(type(PyCPointerType), type)
|
||||
|
||||
def test_type_flags(self):
|
||||
for cls in _Pointer, PyCPointerType:
|
||||
with self.subTest(cls=cls):
|
||||
self.assertTrue(_Pointer.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
|
||||
self.assertFalse(_Pointer.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
|
||||
|
||||
def test_pointer_crash(self):
|
||||
|
||||
class A(POINTER(c_ulong)):
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import unittest
|
||||
from ctypes import Structure, CFUNCTYPE, c_int
|
||||
from ctypes import Structure, CFUNCTYPE, c_int, _SimpleCData
|
||||
from ._support import (_CData, PyCSimpleType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
Py_TPFLAGS_IMMUTABLETYPE)
|
||||
|
||||
|
||||
class MyInt(c_int):
|
||||
|
@ -10,6 +12,19 @@ class MyInt(c_int):
|
|||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_inheritance_hierarchy(self):
|
||||
self.assertEqual(_SimpleCData.mro(), [_SimpleCData, _CData, object])
|
||||
|
||||
self.assertEqual(PyCSimpleType.__name__, "PyCSimpleType")
|
||||
self.assertEqual(type(PyCSimpleType), type)
|
||||
|
||||
self.assertEqual(c_int.mro(), [c_int, _SimpleCData, _CData, object])
|
||||
|
||||
def test_type_flags(self):
|
||||
for cls in _SimpleCData, PyCSimpleType:
|
||||
with self.subTest(cls=cls):
|
||||
self.assertTrue(_SimpleCData.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
|
||||
self.assertFalse(_SimpleCData.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
|
||||
|
||||
def test_compare(self):
|
||||
self.assertEqual(MyInt(3), MyInt(3))
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import unittest
|
||||
from ctypes import Structure, Union, sizeof, c_char, c_int
|
||||
from ._support import (CField, Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
Py_TPFLAGS_IMMUTABLETYPE)
|
||||
|
||||
|
||||
class StructFieldsTestCase(unittest.TestCase):
|
||||
|
@ -12,7 +14,6 @@ class StructFieldsTestCase(unittest.TestCase):
|
|||
# 4. The type is subclassed
|
||||
#
|
||||
# When they are finalized, assigning _fields_ is no longer allowed.
|
||||
|
||||
def test_1_A(self):
|
||||
class X(Structure):
|
||||
pass
|
||||
|
@ -56,11 +57,15 @@ class StructFieldsTestCase(unittest.TestCase):
|
|||
self.assertEqual(bytes(x), b'a\x00###')
|
||||
|
||||
def test_6(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("x", c_int)]
|
||||
CField = type(X.x)
|
||||
self.assertRaises(TypeError, CField)
|
||||
|
||||
def test_cfield_type_flags(self):
|
||||
self.assertTrue(CField.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
|
||||
self.assertTrue(CField.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
|
||||
|
||||
def test_cfield_inheritance_hierarchy(self):
|
||||
self.assertEqual(CField.mro(), [CField, object])
|
||||
|
||||
def test_gh99275(self):
|
||||
class BrokenStructure(Structure):
|
||||
def __init_subclass__(cls, **kwargs):
|
||||
|
|
|
@ -12,6 +12,8 @@ from ctypes.util import find_library
|
|||
from struct import calcsize
|
||||
from collections import namedtuple
|
||||
from test import support
|
||||
from ._support import (_CData, PyCStructType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
Py_TPFLAGS_IMMUTABLETYPE)
|
||||
|
||||
|
||||
class SubclassesTest(unittest.TestCase):
|
||||
|
@ -70,6 +72,19 @@ class StructureTestCase(unittest.TestCase):
|
|||
"d": c_double,
|
||||
}
|
||||
|
||||
def test_inheritance_hierarchy(self):
|
||||
self.assertEqual(Structure.mro(), [Structure, _CData, object])
|
||||
|
||||
self.assertEqual(PyCStructType.__name__, "PyCStructType")
|
||||
self.assertEqual(type(PyCStructType), type)
|
||||
|
||||
|
||||
def test_type_flags(self):
|
||||
for cls in Structure, PyCStructType:
|
||||
with self.subTest(cls=cls):
|
||||
self.assertTrue(Structure.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
|
||||
self.assertFalse(Structure.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
|
||||
|
||||
def test_simple_structs(self):
|
||||
for code, tp in self.formats.items():
|
||||
class X(Structure):
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import unittest
|
||||
from ctypes import Union
|
||||
from ._support import (_CData, UnionType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
Py_TPFLAGS_IMMUTABLETYPE)
|
||||
|
||||
|
||||
class ArrayTestCase(unittest.TestCase):
|
||||
def test_inheritance_hierarchy(self):
|
||||
self.assertEqual(Union.mro(), [Union, _CData, object])
|
||||
|
||||
self.assertEqual(UnionType.__name__, "UnionType")
|
||||
self.assertEqual(type(UnionType), type)
|
||||
|
||||
def test_type_flags(self):
|
||||
for cls in Union, UnionType:
|
||||
with self.subTest(cls=Union):
|
||||
self.assertTrue(Union.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
|
||||
self.assertFalse(Union.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
|
|
@ -9,6 +9,7 @@ from ctypes import (CDLL, Structure, POINTER, pointer, sizeof, byref,
|
|||
_pointer_type_cache,
|
||||
c_void_p, c_char, c_int, c_long)
|
||||
from test import support
|
||||
from ._support import Py_TPFLAGS_DISALLOW_INSTANTIATION, Py_TPFLAGS_IMMUTABLETYPE
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||||
|
@ -73,6 +74,11 @@ class TestWintypes(unittest.TestCase):
|
|||
self.assertEqual(ex.text, "text")
|
||||
self.assertEqual(ex.details, ("details",))
|
||||
|
||||
self.assertEqual(COMError.mro(),
|
||||
[COMError, Exception, BaseException, object])
|
||||
self.assertFalse(COMError.__flags__ & Py_TPFLAGS_DISALLOW_INSTANTIATION)
|
||||
self.assertTrue(COMError.__flags__ & Py_TPFLAGS_IMMUTABLETYPE)
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||||
class TestWinError(unittest.TestCase):
|
||||
|
|
Loading…
Reference in New Issue