Skip to content

Commit 03b0de1

Browse files
Use _testbuffer instead of a new helper in _ctypes_test
_testbuffer.ndarray already exposes the raw Py_buffer, and it can also request particular flags, which the buffer_info() helper could not.
1 parent f6be10a commit 03b0de1

2 files changed

Lines changed: 38 additions & 119 deletions

File tree

Lib/test/test_ctypes/test_pep3118.py

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import re
22
import sys
33
import unittest
4-
from _ctypes_test import buffer_info
4+
from test.support import import_helper
55
from ctypes import (CFUNCTYPE, POINTER, sizeof, Union,
66
Structure, LittleEndianStructure, BigEndianStructure,
77
c_char, c_byte, c_ubyte,
88
c_short, c_ushort, c_int, c_uint,
99
c_long, c_ulong, c_longlong, c_ulonglong, c_uint64,
1010
c_bool, c_float, c_double, c_longdouble, py_object)
1111

12+
_testbuffer = import_helper.import_module('_testbuffer')
13+
1214

1315
if sys.byteorder == "little":
1416
THIS_ENDIAN = "<"
@@ -50,17 +52,43 @@ def test_native_types(self):
5052
self.assertEqual(n * v.itemsize, len(v.tobytes()))
5153

5254
def test_native_types_shape_strides(self):
53-
# check that ctypes (not memoryview) correctly fills out shape and
54-
# strides in the buffer protocol
55+
# memoryview fills in the shape and the strides which the exporter
56+
# does not provide, and always requests all of them, so check what
57+
# ctypes exports itself.
5558
for tp, fmt, shape, stride, itemtp in native_types:
5659
with self.subTest(tp=tp):
57-
v = buffer_info(tp())
58-
if v['ndim'] == 0:
59-
self.assertIsNone(v['shape'])
60-
self.assertIsNone(v['strides'])
61-
else:
62-
self.assertEqual(v['shape'], shape)
63-
self.assertEqual(v['strides'], stride)
60+
v = _testbuffer.ndarray(tp(), getbuf=_testbuffer.PyBUF_FULL_RO)
61+
self.assertEqual(v.shape, shape)
62+
self.assertEqual(v.strides, stride)
63+
64+
def test_flags(self):
65+
ob = (c_int * 3 * 2)()
66+
67+
v = _testbuffer.ndarray(ob, getbuf=_testbuffer.PyBUF_SIMPLE)
68+
# ndim > 1 implies shape != NULL, so a flat buffer is exported.
69+
self.assertEqual(v.ndim, 1)
70+
self.assertEqual(v.shape, ())
71+
self.assertEqual(v.strides, ())
72+
73+
v = _testbuffer.ndarray(ob, getbuf=_testbuffer.PyBUF_ND)
74+
self.assertEqual(v.shape, (2, 3))
75+
self.assertEqual(v.strides, ())
76+
77+
v = _testbuffer.ndarray(ob, getbuf=_testbuffer.PyBUF_STRIDES)
78+
self.assertEqual(v.shape, (2, 3))
79+
self.assertEqual(v.strides, (12, 4))
80+
81+
def test_fortran_contiguous(self):
82+
# A multidimensional array is C contiguous, but not Fortran
83+
# contiguous. A one-dimensional array is contiguous in both orders.
84+
ob = (c_int * 3 * 2)()
85+
with self.assertRaises(BufferError):
86+
_testbuffer.ndarray(ob, getbuf=_testbuffer.PyBUF_F_CONTIGUOUS)
87+
_testbuffer.ndarray(ob, getbuf=_testbuffer.PyBUF_C_CONTIGUOUS)
88+
89+
ob = (c_int * 3)()
90+
_testbuffer.ndarray(ob, getbuf=_testbuffer.PyBUF_F_CONTIGUOUS)
91+
_testbuffer.ndarray(ob, getbuf=_testbuffer.PyBUF_C_CONTIGUOUS)
6492

6593
def test_endian_types(self):
6694
for tp, fmt, shape, stride, itemtp in endian_types:

Modules/_ctypes/_ctypes_test.c

Lines changed: 0 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -852,120 +852,11 @@ EXPORT(TestReg) get_last_tfrsuv_arg(void)
852852
return last_tfrsuv_arg;
853853
}
854854

855-
PyObject *py_getBufferInfo(PyObject *self, PyObject *obj)
856-
{
857-
int flags = PyBUF_FULL;
858-
int ii;
859-
Py_buffer view;
860-
PyObject *v;
861-
PyObject *x;
862-
PyObject *d;
863-
int buffer_err;
864-
865-
d = PyDict_New();
866-
if (NULL == d) Py_RETURN_NONE;
867-
buffer_err = PyObject_GetBuffer(obj, &view, flags);
868-
v = PyLong_FromLong(buffer_err);
869-
if (NULL != v){
870-
PyDict_SetItemString(d, "err", v);
871-
Py_DECREF(v);
872-
}
873-
874-
if (0 == buffer_err) {
875-
v = PyLong_FromSsize_t(view.len);
876-
if (NULL != v){
877-
PyDict_SetItemString(d, "len", v);
878-
Py_DECREF(v);
879-
}
880-
v = PyBool_FromLong(view.readonly);
881-
if (NULL != v){
882-
PyDict_SetItemString(d, "readonly", v);
883-
Py_DECREF(v);
884-
}
885-
v = PyLong_FromSsize_t(view.itemsize);
886-
if (NULL != v){
887-
PyDict_SetItemString(d, "itemsize", v);
888-
Py_DECREF(v);
889-
}
890-
if(NULL == view.format) {
891-
v = PyUnicode_FromString("");
892-
} else {
893-
v = PyUnicode_FromString(view.format);
894-
}
895-
if (NULL != v){
896-
PyDict_SetItemString(d, "format", v);
897-
Py_DECREF(v);
898-
}
899-
v = PyLong_FromLong(view.ndim);
900-
if (NULL != v){
901-
PyDict_SetItemString(d, "ndim", v);
902-
Py_DECREF(v);
903-
}
904-
if (NULL == view.shape) {
905-
PyDict_SetItemString(d, "shape", Py_None);
906-
} else {
907-
v = PyTuple_New(view.ndim);
908-
if (NULL != v){
909-
for (ii=0; ii<view.ndim; ++ii) {
910-
x = PyLong_FromSsize_t(view.shape[ii]);
911-
if (NULL == x) {
912-
Py_DECREF(v);
913-
Py_DECREF(d);
914-
return NULL;
915-
}
916-
PyTuple_SetItem(v, ii, x);
917-
}
918-
PyDict_SetItemString(d, "shape", v);
919-
Py_DECREF(v);
920-
}
921-
}
922-
if (NULL == view.strides) {
923-
PyDict_SetItemString(d, "strides", Py_None);
924-
} else {
925-
v = PyTuple_New(view.ndim);
926-
if (NULL != v){
927-
for (ii=0; ii<view.ndim; ++ii) {
928-
x = PyLong_FromSsize_t(view.strides[ii]);
929-
if (NULL == x) {
930-
Py_DECREF(v);
931-
Py_DECREF(d);
932-
return NULL;
933-
}
934-
PyTuple_SetItem(v, ii, x);
935-
}
936-
PyDict_SetItemString(d, "strides", v);
937-
Py_DECREF(v);
938-
}
939-
}
940-
if (NULL == view.suboffsets) {
941-
PyDict_SetItemString(d, "suboffsets", Py_None);
942-
} else {
943-
v = PyTuple_New(view.ndim);
944-
if (NULL != v){
945-
for (ii=0; ii<view.ndim; ++ii) {
946-
x = PyLong_FromSsize_t(view.suboffsets[ii]);
947-
if (NULL == x) {
948-
Py_DECREF(v);
949-
Py_DECREF(d);
950-
return NULL;
951-
}
952-
PyTuple_SetItem(v, ii, x);
953-
}
954-
PyDict_SetItemString(d, "suboffsets", v);
955-
Py_DECREF(v);
956-
}
957-
}
958-
PyBuffer_Release(&view);
959-
}
960-
return d;
961-
}
962-
963855
static PyMethodDef module_methods[] = {
964856
{"get_last_tf_arg_s", get_last_tf_arg_s, METH_NOARGS},
965857
{"get_last_tf_arg_u", get_last_tf_arg_u, METH_NOARGS},
966858
{"func_si", py_func_si, METH_VARARGS},
967859
{"func", py_func, METH_NOARGS},
968-
{"buffer_info", py_getBufferInfo, METH_O},
969860
{"get_generated_test_data", get_generated_test_data, METH_O},
970861
{ NULL, NULL, 0, NULL},
971862
};

0 commit comments

Comments
 (0)