8000 gh-84489: C API: Add tests for Py_BuildValue() (GH-110596) · python/cpython@5c6e854 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5c6e854

Browse files
gh-84489: C API: Add tests for Py_BuildValue() (GH-110596)
1 parent 3dd593e commit 5c6e854

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

Lib/test/test_capi/test_misc.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,86 @@ def test_getitem_with_error(self):
298298
# test _Py_CheckFunctionResult() instead.
299299
self.assertIn('returned a result with an exception set', err)
300300

301+
def test_buildvalue(self):
302+
# Test Py_BuildValue() with object arguments
303+
buildvalue = _testcapi.py_buildvalue
304+
self.assertEqual(buildvalue(''), None)
305+
self.assertEqual(buildvalue('()'), ())
306+
self.assertEqual(buildvalue('[]'), [])
307+
self.assertEqual(buildvalue('{}'), {})
308+
self.assertEqual(buildvalue('()[]{}'), ((), [], {}))
309+
self.assertEqual(buildvalue('O', 1), 1)
310+
self.assertEqual(buildvalue('(O)', 1), (1,))
311+
self.assertEqual(buildvalue('[O]', 1), [1])
312+
self.assertRaises(SystemError, buildvalue, '{O}', 1)
313+
self.assertEqual(buildvalue('OO', 1, 2), (1, 2))
314+
self.assertEqual(buildvalue('(OO)', 1, 2), (1, 2))
315+
self.assertEqual(buildvalue('[OO]', 1, 2), [1, 2])
316+
self.assertEqual(buildvalue('{OO}', 1, 2), {1: 2})
317+
self.assertEqual(buildvalue('{OOOO}', 1, 2, 3, 4), {1: 2, 3: 4})
318+
self.assertEqual(buildvalue('((O))', 1), ((1,),))
319+
self.assertEqual(buildvalue('((OO))', 1, 2), ((1, 2),))
320+
321+
self.assertEqual(buildvalue(' \t,:'), None)
322+
self.assertEqual(buildvalue(' O ', 1), 1)
323+
self.assertEqual(buildvalue('\tO\t', 1), 1)
324+
self.assertEqual(buildvalue('O,O', 1, 2), (1, 2))
325+
self.assertEqual(buildvalue('O, O', 1, 2), (1, 2))
326+
self.assertEqual(buildvalue('O,\tO', 1, 2), (1, 2))
327+
self.assertEqual(buildvalue('O O', 1, 2), (1, 2))
328+
self.assertEqual(buildvalue('O\tO', 1, 2), (1, 2))
329+
self.assertEqual(buildvalue('(O,O)', 1, 2), (1, 2))
330+
self.assertEqual(buildvalue('(O, O)', 1, 2), (1, 2))
331+
self.assertEqual(buildvalue(' ( O O) ', 1, 2), (1, 2))
332+
self.assertEqual(buildvalue('\t(\tO\tO)\t', 1, 2), (1, 2))
333+
self.assertEqual(buildvalue('[O,O]', 1, 2), [1, 2])
334+
self.assertEqual(buildvalue('[O, O]', 1, 2), [1, 2])
335+
self.assertEqual(buildvalue(' [ O O] ', 1, 2), [1, 2])
336+
self.assertEqual(buildvalue('{O:O}', 1, 2), {1: 2})
337+
self.assertEqual(buildvalue('{O:O,O:O}', 1, 2, 3, 4), {1: 2, 3: 4})
338+
self.assertEqual(buildvalue('{O: O, O: O}', 1, 2, 3, 4), {1: 2, 3: 4})
339+
self.assertEqual(buildvalue(' { O O O O} ', 1, 2, 3, 4), {1: 2, 3: 4})
340+
self.assertEqual(buildvalue('\t{\tO\tO\tO\tO}\t', 1, 2, 3, 4), {1: 2, 3: 4})
341+
342+
self.assertRaises(SystemError, buildvalue, 'O', NULL)
343+
self.assertRaises(SystemError, buildvalue, '(O)', NULL)
344+
self.assertRaises(SystemError, buildvalue, '[O]', NULL)
345+
self.assertRaises(SystemError, buildvalue, '{O}', NULL)
346+
self.assertRaises(SystemError, buildvalue, 'OO', 1, NULL)
347+
self.assertRaises(SystemError, buildvalue, 'OO', NULL, 2)
348+
self.assertRaises(SystemError, buildvalue, '(OO)', 1, NULL)
349+
self.assertRaises(SystemError, buildvalue, '(OO)', NULL, 2)
350+
self.assertRaises(SystemError, buildvalue, '[OO]', 1, NULL)
351+
self.assertRaises(SystemError, buildvalue, '[OO]', NULL, 2)
352+
self.assertRaises(SystemError, buildvalue, '{OO}', 1, NULL)
353+
self.assertRaises(SystemError, buildvalue, '{OO}', NULL, 2)
354+
355+
def test_buildvalue_ints(self):
356+
# Test Py_BuildValue() with integer arguments
357+
buildvalue = _testcapi.py_buildvalue_ints
358+
from _testcapi import SHRT_MIN, SHRT_MAX, USHRT_MAX, INT_MIN, INT_MAX, UINT_MAX
359+
self.assertEqual(buildvalue('i', INT_MAX), INT_MAX)
360+
self.assertEqual(buildvalue('i', INT_MIN), INT_MIN)
361+
self.assertEqual(buildvalue('I', UINT_MAX), UINT_MAX)
362+
363+
self.assertEqual(buildvalue('h', SHRT_MAX), SHRT_MAX)
364+
self.assertEqual(buildvalue('h', SHRT_MIN), SHRT_MIN)
365+
self.assertEqual(buildvalue('H', USHRT_MAX), USHRT_MAX)
366+
367+
self.assertEqual(buildvalue('b', 127), 127)
368+
self.assertEqual(buildvalue('b', -128), -128)
369+
self.assertEqual(buildvalue('B', 255), 255)
370+
371+
self.assertEqual(buildvalue('c', ord('A')), b'A')
372+
self.assertEqual(buildvalue('c', 255), b'\xff')
373+
self.assertEqual(buildvalue('c', 256), b'\x00')
374+
self.assertEqual(buildvalue('c', -1), b'\xff')
375+
376+
self.assertEqual(buildvalue('C', 255), chr(255))
377+
self.assertEqual(buildvalue('C', 256), chr(256))
378+
self.assertEqual(buildvalue('C', sys.maxunicode), chr(sys.maxunicode))
379+
self.assertRaises(ValueError, buildvalue, 'C', -1)
380+
self.assertRaises(ValueError, buildvalue, 'C', sys.maxunicode+1)
301381
def test_buildvalue_N(self):
302382
_testcapi.test_buildvalue_N()
303383

Modules/_testcapimodule.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,41 @@ raise_error(void *unused)
386386
return NULL;
387387
}
388388

389+
static PyObject *
390+
py_buildvalue(PyObject *self, PyObject *args)
391+
{
392+
const char *fmt;
393+
PyObject *objs[10] = {NULL};
394+
if (!PyArg_ParseTuple(args, "s|OOOOOOOOOO", &fmt,
395+
&objs[0], &objs[1], &objs[2], &objs[3], &objs[4],
396+
&objs[5], &objs[6], &objs[7], &objs[8], &objs[9]))
397+
{
398+
return NULL;
399+
}
400+
for(int i = 0; i < 10; i++) {
401+
NULLABLE(objs[i]);
402+
}
403+
return Py_BuildValue(fmt,
404+
objs[0], objs[1], objs[2], objs[3], objs[4],
405+
objs[5], objs[6], objs[7], objs[8], objs[9]);
406+
}
407+
408+
static PyObject *
409+
py_buildvalue_ints(PyObject *self, PyObject *args)
410+
{
411+
const char *fmt;
412+
unsigned int values[10] = {0};
413+
if (!PyArg_ParseTuple(args, "s|IIIIIIIIII", &fmt,
414+
&values[0], &values[1], &values[2], &values[3], &values[4],
415+
&values[5], &values[6], &values[7], &values[8], &values[9]))
416+
{
417+
return NULL;
418+
}
419+
return Py_BuildValue(fmt,
420+
values[0], values[1], values[2], values[3], values[4],
421+
values[5], values[6], values[7], values[8], values[9]);
422+
}
423+
389424
static int
390425
test_buildvalue_N_error(const char *fmt)
391426
{
@@ -3252,6 +3287,8 @@ static PyMethodDef TestMethods[] = {
32523287
#endif
32533288
{"getbuffer_with_null_view", getbuffer_with_null_view, METH_O},
32543289
{"PyBuffer_SizeFromFormat", test_PyBuffer_SizeFromFormat, METH_VARARGS},
3290+
{"py_buildvalue", py_buildvalue, METH_VARARGS},
3291+
{"py_buildvalue_ints", py_buildvalue_ints, METH_VARARGS},
32553292
{"test_buildvalue_N", test_buildvalue_N, METH_NOARGS},
32563293
{"test_get_statictype_slots", test_get_statictype_slots, METH_NOARGS},
32573294
{"test_get_type_name", test_get_type_name, METH_NOARGS},

0 commit comments

Comments
 (0)
0