mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-111489: Add PyTuple_FromArray() function (#139691)
This commit is contained in:
parent
8f14bddeae
commit
e31c22dbf9
8 changed files with 76 additions and 2 deletions
|
|
@ -37,6 +37,19 @@ Tuple Objects
|
||||||
or ``NULL`` with an exception set on failure.
|
or ``NULL`` with an exception set on failure.
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: PyObject* PyTuple_FromArray(PyObject *const *array, Py_ssize_t size)
|
||||||
|
|
||||||
|
Create a tuple of *size* items and copy references from *array* to the new
|
||||||
|
tuple.
|
||||||
|
|
||||||
|
*array* can be NULL if *size* is ``0``.
|
||||||
|
|
||||||
|
On success, return a new reference.
|
||||||
|
On error, set an exception and return ``NULL``.
|
||||||
|
|
||||||
|
.. versionadded:: next
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: PyObject* PyTuple_Pack(Py_ssize_t n, ...)
|
.. c:function:: PyObject* PyTuple_Pack(Py_ssize_t n, ...)
|
||||||
|
|
||||||
Return a new tuple object of size *n*,
|
Return a new tuple object of size *n*,
|
||||||
|
|
|
||||||
|
|
@ -852,6 +852,9 @@ New features
|
||||||
|
|
||||||
(Contributed by Victor Stinner in :gh:`129813`.)
|
(Contributed by Victor Stinner in :gh:`129813`.)
|
||||||
|
|
||||||
|
* Add :c:func:`PyTuple_FromArray` to create a :class:`tuple` from an array.
|
||||||
|
(Contributed by Victor Stinner in :gh:`111489`.)
|
||||||
|
|
||||||
|
|
||||||
Porting to Python 3.15
|
Porting to Python 3.15
|
||||||
----------------------
|
----------------------
|
||||||
|
|
|
||||||
|
|
@ -38,3 +38,7 @@ PyTuple_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) {
|
||||||
}
|
}
|
||||||
#define PyTuple_SET_ITEM(op, index, value) \
|
#define PyTuple_SET_ITEM(op, index, value) \
|
||||||
PyTuple_SET_ITEM(_PyObject_CAST(op), (index), _PyObject_CAST(value))
|
PyTuple_SET_ITEM(_PyObject_CAST(op), (index), _PyObject_CAST(value))
|
||||||
|
|
||||||
|
PyAPI_FUNC(PyObject*) PyTuple_FromArray(
|
||||||
|
PyObject *const *array,
|
||||||
|
Py_ssize_t size);
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
|
||||||
|
|
||||||
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
|
#define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item)
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *)_PyTuple_FromArray(PyObject *const *, Py_ssize_t);
|
// Alias for backward compatibility
|
||||||
|
#define _PyTuple_FromArray PyTuple_FromArray
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t);
|
PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRef *, Py_ssize_t);
|
||||||
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
|
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,28 @@ def test_tuple_new(self):
|
||||||
self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN)
|
self.assertRaises(SystemError, tuple_new, PY_SSIZE_T_MIN)
|
||||||
self.assertRaises(MemoryError, tuple_new, PY_SSIZE_T_MAX)
|
self.assertRaises(MemoryError, tuple_new, PY_SSIZE_T_MAX)
|
||||||
|
|
||||||
|
def test_tuple_fromarray(self):
|
||||||
|
# Test PyTuple_FromArray()
|
||||||
|
tuple_fromarray = _testcapi.tuple_fromarray
|
||||||
|
|
||||||
|
tup = tuple([i] for i in range(5))
|
||||||
|
copy = tuple_fromarray(tup)
|
||||||
|
self.assertEqual(copy, tup)
|
||||||
|
|
||||||
|
tup = ()
|
||||||
|
copy = tuple_fromarray(tup)
|
||||||
|
self.assertIs(copy, tup)
|
||||||
|
|
||||||
|
copy = tuple_fromarray(NULL, 0)
|
||||||
|
self.assertIs(copy, ())
|
||||||
|
|
||||||
|
with self.assertRaises(SystemError):
|
||||||
|
tuple_fromarray(NULL, -1)
|
||||||
|
with self.assertRaises(SystemError):
|
||||||
|
tuple_fromarray(NULL, PY_SSIZE_T_MIN)
|
||||||
|
with self.assertRaises(MemoryError):
|
||||||
|
tuple_fromarray(NULL, PY_SSIZE_T_MAX)
|
||||||
|
|
||||||
def test_tuple_pack(self):
|
def test_tuple_pack(self):
|
||||||
# Test PyTuple_Pack()
|
# Test PyTuple_Pack()
|
||||||
pack = _testlimitedcapi.tuple_pack
|
pack = _testlimitedcapi.tuple_pack
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
Add :c:func:`PyTuple_FromArray` to create a :class:`tuple` from an array.
|
||||||
|
Patch by Victor Stinner.
|
||||||
|
|
@ -104,12 +104,40 @@ _check_tuple_item_is_NULL(PyObject *Py_UNUSED(module), PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
tuple_fromarray(PyObject* Py_UNUSED(module), PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *src;
|
||||||
|
Py_ssize_t size = UNINITIALIZED_SIZE;
|
||||||
|
if (!PyArg_ParseTuple(args, "O|n", &src, &size)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (src != Py_None && !PyTuple_Check(src)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expect a tuple");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject **items;
|
||||||
|
if (src != Py_None) {
|
||||||
|
items = &PyTuple_GET_ITEM(src, 0);
|
||||||
|
if (size == UNINITIALIZED_SIZE) {
|
||||||
|
size = PyTuple_GET_SIZE(src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
items = NULL;
|
||||||
|
}
|
||||||
|
return PyTuple_FromArray(items, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyMethodDef test_methods[] = {
|
static PyMethodDef test_methods[] = {
|
||||||
{"tuple_get_size", tuple_get_size, METH_O},
|
{"tuple_get_size", tuple_get_size, METH_O},
|
||||||
{"tuple_get_item", tuple_get_item, METH_VARARGS},
|
{"tuple_get_item", tuple_get_item, METH_VARARGS},
|
||||||
{"tuple_set_item", tuple_set_item, METH_VARARGS},
|
{"tuple_set_item", tuple_set_item, METH_VARARGS},
|
||||||
{"_tuple_resize", _tuple_resize, METH_VARARGS},
|
{"_tuple_resize", _tuple_resize, METH_VARARGS},
|
||||||
{"_check_tuple_item_is_NULL", _check_tuple_item_is_NULL, METH_VARARGS},
|
{"_check_tuple_item_is_NULL", _check_tuple_item_is_NULL, METH_VARARGS},
|
||||||
|
{"tuple_fromarray", tuple_fromarray, METH_VARARGS},
|
||||||
{NULL},
|
{NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -366,7 +366,7 @@ tuple_item(PyObject *op, Py_ssize_t i)
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
|
PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
|
||||||
{
|
{
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return tuple_get_empty();
|
return tuple_get_empty();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue