Skip to content

Commit cddecf2

Browse files
[3.13] gh-125783: Add more tests to prevent regressions with the combination of ctypes and metaclasses. (GH-126126) (GH-126275)
gh-125783: Add more tests to prevent regressions with the combination of ctypes and metaclasses. (GH-126126) (cherry picked from commit 6c67446) Co-authored-by: Jun Komoda <[email protected]>
1 parent 6245ee2 commit cddecf2

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

Lib/test/test_ctypes/test_c_simple_type_meta.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,68 @@ class Sub(CtBase):
8585

8686
self.assertIsInstance(POINTER(Sub), p_meta)
8787
self.assertTrue(issubclass(POINTER(Sub), Sub))
88+
89+
def test_creating_pointer_in_dunder_init_1(self):
90+
class ct_meta(type):
91+
def __init__(self, name, bases, namespace):
92+
super().__init__(name, bases, namespace)
93+
94+
# Avoid recursion.
95+
# (See test_creating_pointer_in_dunder_new_1)
96+
if bases == (c_void_p,):
97+
return
98+
if issubclass(self, PtrBase):
99+
return
100+
if bases == (object,):
101+
ptr_bases = (self, PtrBase)
102+
else:
103+
ptr_bases = (self, POINTER(bases[0]))
104+
p = p_meta(f"POINTER({self.__name__})", ptr_bases, {})
105+
ctypes._pointer_type_cache[self] = p
106+
107+
class p_meta(PyCSimpleType, ct_meta):
108+
pass
109+
110+
class PtrBase(c_void_p, metaclass=p_meta):
111+
pass
112+
113+
class CtBase(object, metaclass=ct_meta):
114+
pass
115+
116+
class Sub(CtBase):
117+
pass
118+
119+
class Sub2(Sub):
120+
pass
121+
122+
self.assertIsInstance(POINTER(Sub2), p_meta)
123+
self.assertTrue(issubclass(POINTER(Sub2), Sub2))
124+
self.assertTrue(issubclass(POINTER(Sub2), POINTER(Sub)))
125+
self.assertTrue(issubclass(POINTER(Sub), POINTER(CtBase)))
126+
127+
def test_creating_pointer_in_dunder_init_2(self):
128+
class ct_meta(type):
129+
def __init__(self, name, bases, namespace):
130+
super().__init__(name, bases, namespace)
131+
132+
# Avoid recursion.
133+
# (See test_creating_pointer_in_dunder_new_2)
134+
if isinstance(self, p_meta):
135+
return
136+
p = p_meta(f"POINTER({self.__name__})", (self, c_void_p), {})
137+
ctypes._pointer_type_cache[self] = p
138+
139+
class p_meta(PyCSimpleType, ct_meta):
140+
pass
141+
142+
class Core(object):
143+
pass
144+
145+
class CtBase(Core, metaclass=ct_meta):
146+
pass
147+
148+
class Sub(CtBase):
149+
pass
150+
151+
self.assertIsInstance(POINTER(Sub), p_meta)
152+
self.assertTrue(issubclass(POINTER(Sub), Sub))

0 commit comments

Comments
 (0)