Skip to content

Commit 4dc1890

Browse files
Added all test cases
1 parent 8abda12 commit 4dc1890

2 files changed

Lines changed: 72 additions & 12 deletions

File tree

Lib/test/test_ctypes/test_arrays.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from ctypes import (Structure, Array, ARRAY, sizeof, addressof,
55
create_string_buffer, create_unicode_buffer,
66
c_char, c_wchar, c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
7-
c_long, c_ulonglong, c_float, c_double, c_longdouble)
7+
c_long, c_ulonglong, c_float, c_double, c_longdouble, POINTER)
88
from test.support import bigmemtest, _2G, threading_helper, Py_GIL_DISABLED
99
from ._support import (_CData, PyCArrayType, Py_TPFLAGS_DISALLOW_INSTANTIATION,
1010
Py_TPFLAGS_IMMUTABLETYPE)
@@ -147,6 +147,61 @@ def test_ctypes_array_class_assignment_signed_unsigned(self):
147147
with self.assertRaises(TypeError):
148148
a.__class__ = B
149149

150+
def test_ctypes_array_class_assignment_compatible(self):
151+
A = c_int * 3
152+
class SameArray(Array):
153+
_type_ = c_int
154+
_length_ = 3
155+
a = A(1, 2, 3)
156+
a.__class__ = SameArray
157+
158+
def test_ctypes_array_class_assignment_non_ctypes_target(self):
159+
A = c_int * 3
160+
a = A()
161+
class Dummy:
162+
pass
163+
164+
with self.assertRaises(TypeError):
165+
a.__class__ = Dummy
166+
167+
def test_ctypes_array_class_assignment_abstract_target(self):
168+
A = c_int * 3
169+
a = A()
170+
AbstractArray = PyCArrayType.__new__(PyCArrayType, "AbstractArray", (Array,), {})
171+
172+
with self.assertRaises(TypeError):
173+
a.__class__ = AbstractArray
174+
175+
def test_ctypes_array_class_assignment_same_size_ints(self):
176+
if sizeof(c_int) != sizeof(c_long):
177+
self.skipTest("sizes differ on this platform")
178+
A = c_int * 3
179+
B = c_long * 3
180+
a = A(1, 2, 3)
181+
a.__class__ = B
182+
183+
def test_ctypes_array_class_assignment_structs(self):
184+
class S1(Structure):
185+
_fields_ = [("x", c_int)]
186+
class S2(Structure):
187+
_fields_ = [("x", c_int)]
188+
A = S1 * 2
189+
B = S2 * 2
190+
a = A()
191+
a.__class__ = B
192+
193+
def test_ctypes_array_class_assignment_pointer_arrays(self):
194+
A = POINTER(c_int) * 2
195+
B = POINTER(c_int) * 2
196+
a = A()
197+
a.__class__ = B
198+
199+
def test_ctypes_array_from_param_incompatible(self):
200+
A = c_int * 3
201+
B = c_double * 3
202+
with self.assertRaises(TypeError):
203+
A.from_param(B())
204+
150205
def test_step_overflow(self):
151206
a = (c_int * 5)()
152207
a[3::sys.maxsize] = (1,)

Modules/_ctypes/_ctypes.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5041,17 +5041,22 @@ PyCArray_setattro(PyObject *self, PyObject *key, PyObject *value)
50415041
}
50425042

50435043
/* Only care about array to array */
5044-
if (old_info->length >= 0 && new_info->length >= 0) {
5045-
if (old_info->length != new_info->length ||
5046-
old_info->size != new_info->size ||
5047-
old_info->proto != new_info->proto)
5048-
{
5049-
PyErr_SetString(
5050-
PyExc_TypeError,
5051-
"cannot assign incompatible ctypes array type"
5052-
);
5053-
return -1;
5054-
}
5044+
if (old_info->length < 0 || new_info->length < 0) {
5045+
PyErr_SetString(
5046+
PyExc_TypeError,
5047+
"cannot assign incompatible ctypes array type");
5048+
return -1;
5049+
}
5050+
5051+
/* Must match layout */
5052+
if (old_info->length != new_info->length ||
5053+
old_info->size != new_info->size ||
5054+
old_info->proto != new_info->proto)
5055+
{
5056+
PyErr_SetString(
5057+
PyExc_TypeError,
5058+
"cannot assign incompatible ctypes array type");
5059+
return -1;
50555060
}
50565061
}
50575062

0 commit comments

Comments
 (0)