Skip to content

Commit c1bf7cc

Browse files
Add more tests for metabases pointers
1 parent 8505d4b commit c1bf7cc

1 file changed

Lines changed: 123 additions & 2 deletions

File tree

Lib/test/test_ctypes/test_c_simple_type_meta.py

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import unittest
22
from test.support import MS_WINDOWS
33
import ctypes
4-
from ctypes import POINTER, c_void_p
4+
from ctypes import POINTER, Structure, c_void_p
55

6-
from ._support import PyCSimpleType
6+
from ._support import PyCSimpleType, PyCPointerType, PyCStructType
77

88

99
class PyCSimpleTypeAsMetaclassTest(unittest.TestCase):
@@ -222,3 +222,124 @@ class F(metaclass=PyCSimpleType):
222222
if not MS_WINDOWS:
223223
expected_type_chars.remove('X')
224224
self.assertIn("'" + ''.join(expected_type_chars) + "'", message)
225+
226+
def test_creating_pointer_in_dunder_init_3(self):
227+
228+
class StructureMeta(PyCStructType):
229+
def __new__(cls, name, bases, dct, /, create_pointer_type=True):
230+
if len(bases) > 1:
231+
bases = (bases[0],)
232+
233+
return super().__new__(cls, name, bases, dct)
234+
235+
def __init__(self, name, bases, dct, /, create_pointer_type=True):
236+
237+
super().__init__(name, bases, dct)
238+
if create_pointer_type:
239+
p_bases = (POINTER(bases[0]),)
240+
p = PointerMeta(f"p{name}", p_bases, {'_type_': self})
241+
assert isinstance(p, PyCPointerType)
242+
assert self.__pointer_type__ is not None
243+
assert self.__pointer_type__ == p
244+
245+
246+
class PointerMeta(PyCPointerType):
247+
def __new__(cls, name, bases, dct):
248+
target = dct.get('_type_', None)
249+
if target is None:
250+
251+
# Create corresponding interface type and then set it as target
252+
target = StructureMeta(
253+
f"_{name}_",
254+
(bases[0]._type_,),
255+
{},
256+
create_pointer_type=False
257+
)
258+
dct['_type_'] = target
259+
260+
pointer_type = super().__new__(cls, name, bases, dct)
261+
assert target.__pointer_type__ is None
262+
263+
return pointer_type
264+
265+
def __init__(self, name, bases, dct, /, create_pointer_type=True):
266+
target = dct.get('_type_', None)
267+
super().__init__(name, bases, dct)
268+
assert target.__pointer_type__ is self
269+
270+
271+
class Interface(Structure, metaclass=StructureMeta, create_pointer_type=False):
272+
pass
273+
274+
class pInterface(POINTER(c_void_p), metaclass=PointerMeta):
275+
_type_ = Interface
276+
277+
class IUnknown(Interface):
278+
pass
279+
280+
class pIUnknown(pInterface):
281+
pass
282+
283+
self.assertTrue(issubclass(POINTER(IUnknown), pInterface))
284+
self.assertTrue(issubclass(pIUnknown, pInterface))
285+
286+
self.assertIs(POINTER(Interface), pInterface)
287+
self.assertIsNot(POINTER(IUnknown), pIUnknown)
288+
289+
def test_creating_pointer_in_dunder_init_4(self):
290+
291+
class StructureMeta(PyCStructType):
292+
def __new__(cls, name, bases, dct, /, create_pointer_type=True):
293+
if len(bases) > 1:
294+
bases = (bases[0],)
295+
296+
return super().__new__(cls, name, bases, dct)
297+
298+
def __init__(self, name, bases, dct, /, create_pointer_type=True):
299+
300+
super().__init__(name, bases, dct)
301+
if create_pointer_type:
302+
p_bases = (POINTER(bases[0]),)
303+
p = PointerMeta(f"p{name}", p_bases, {'_type_': self})
304+
assert isinstance(p, PyCPointerType)
305+
assert self.__pointer_type__ is not None
306+
assert self.__pointer_type__ == p
307+
308+
309+
class PointerMeta(PyCPointerType):
310+
def __new__(cls, name, bases, dct):
311+
target = dct.get('_type_', None)
312+
assert target is not None
313+
pointer_type = target.__pointer_type__
314+
315+
if pointer_type is None:
316+
pointer_type = super().__new__(cls, name, bases, dct)
317+
318+
return pointer_type
319+
320+
def __init__(self, name, bases, dct, /, create_pointer_type=True):
321+
target = dct.get('_type_', None)
322+
if target.__pointer_type__ is None:
323+
# target.__pointer_type__ was created by super().__new__
324+
super().__init__(name, bases, dct)
325+
326+
assert target.__pointer_type__ is self
327+
328+
329+
class Interface(Structure, metaclass=StructureMeta, create_pointer_type=False):
330+
pass
331+
332+
class pInterface(POINTER(c_void_p), metaclass=PointerMeta):
333+
_type_ = Interface
334+
335+
class IUnknown(Interface):
336+
pass
337+
338+
class pIUnknown(pInterface):
339+
_type_ = IUnknown
340+
341+
self.assertTrue(issubclass(POINTER(IUnknown), pInterface))
342+
self.assertTrue(issubclass(pIUnknown, pInterface))
343+
344+
self.assertIs(POINTER(Interface), pInterface)
345+
self.assertIs(POINTER(IUnknown), pIUnknown)

0 commit comments

Comments
 (0)