mirror of https://github.com/python/cpython
bpo-36030: Add _PyTuple_FromArray() function (GH-11954)
This commit is contained in:
parent
55e335d7d5
commit
234531b446
|
@ -11,6 +11,7 @@ extern "C" {
|
||||||
#include "tupleobject.h"
|
#include "tupleobject.h"
|
||||||
|
|
||||||
#define _PyTuple_ITEMS(op) (_PyTuple_CAST(op)->ob_item)
|
#define _PyTuple_ITEMS(op) (_PyTuple_CAST(op)->ob_item)
|
||||||
|
PyAPI_FUNC(PyObject *) _PyTuple_FromArray(PyObject *const *, Py_ssize_t);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#define PY_SSIZE_T_CLEAN
|
#define PY_SSIZE_T_CLEAN
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "pycore_tupleobject.h"
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
/* Itertools module written and maintained
|
/* Itertools module written and maintained
|
||||||
|
@ -2239,15 +2240,10 @@ product_next(productobject *lz)
|
||||||
/* Copy the previous result tuple or re-use it if available */
|
/* Copy the previous result tuple or re-use it if available */
|
||||||
if (Py_REFCNT(result) > 1) {
|
if (Py_REFCNT(result) > 1) {
|
||||||
PyObject *old_result = result;
|
PyObject *old_result = result;
|
||||||
result = PyTuple_New(npools);
|
result = _PyTuple_FromArray(_PyTuple_ITEMS(old_result), npools);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
goto empty;
|
goto empty;
|
||||||
lz->result = result;
|
lz->result = result;
|
||||||
for (i=0; i < npools; i++) {
|
|
||||||
elem = PyTuple_GET_ITEM(old_result, i);
|
|
||||||
Py_INCREF(elem);
|
|
||||||
PyTuple_SET_ITEM(result, i, elem);
|
|
||||||
}
|
|
||||||
Py_DECREF(old_result);
|
Py_DECREF(old_result);
|
||||||
}
|
}
|
||||||
/* Now, we've got the only copy so we can update it in-place */
|
/* Now, we've got the only copy so we can update it in-place */
|
||||||
|
@ -2569,15 +2565,10 @@ combinations_next(combinationsobject *co)
|
||||||
/* Copy the previous result tuple or re-use it if available */
|
/* Copy the previous result tuple or re-use it if available */
|
||||||
if (Py_REFCNT(result) > 1) {
|
if (Py_REFCNT(result) > 1) {
|
||||||
PyObject *old_result = result;
|
PyObject *old_result = result;
|
||||||
result = PyTuple_New(r);
|
result = _PyTuple_FromArray(_PyTuple_ITEMS(old_result), r);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
goto empty;
|
goto empty;
|
||||||
co->result = result;
|
co->result = result;
|
||||||
for (i=0; i<r ; i++) {
|
|
||||||
elem = PyTuple_GET_ITEM(old_result, i);
|
|
||||||
Py_INCREF(elem);
|
|
||||||
PyTuple_SET_ITEM(result, i, elem);
|
|
||||||
}
|
|
||||||
Py_DECREF(old_result);
|
Py_DECREF(old_result);
|
||||||
}
|
}
|
||||||
/* Now, we've got the only copy so we can update it in-place
|
/* Now, we've got the only copy so we can update it in-place
|
||||||
|
@ -2910,15 +2901,10 @@ cwr_next(cwrobject *co)
|
||||||
/* Copy the previous result tuple or re-use it if available */
|
/* Copy the previous result tuple or re-use it if available */
|
||||||
if (Py_REFCNT(result) > 1) {
|
if (Py_REFCNT(result) > 1) {
|
||||||
PyObject *old_result = result;
|
PyObject *old_result = result;
|
||||||
result = PyTuple_New(r);
|
result = _PyTuple_FromArray(_PyTuple_ITEMS(old_result), r);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
goto empty;
|
goto empty;
|
||||||
co->result = result;
|
co->result = result;
|
||||||
for (i=0; i<r ; i++) {
|
|
||||||
elem = PyTuple_GET_ITEM(old_result, i);
|
|
||||||
Py_INCREF(elem);
|
|
||||||
PyTuple_SET_ITEM(result, i, elem);
|
|
||||||
}
|
|
||||||
Py_DECREF(old_result);
|
Py_DECREF(old_result);
|
||||||
}
|
}
|
||||||
/* Now, we've got the only copy so we can update it in-place CPython's
|
/* Now, we've got the only copy so we can update it in-place CPython's
|
||||||
|
@ -3258,15 +3244,10 @@ permutations_next(permutationsobject *po)
|
||||||
/* Copy the previous result tuple or re-use it if available */
|
/* Copy the previous result tuple or re-use it if available */
|
||||||
if (Py_REFCNT(result) > 1) {
|
if (Py_REFCNT(result) > 1) {
|
||||||
PyObject *old_result = result;
|
PyObject *old_result = result;
|
||||||
result = PyTuple_New(r);
|
result = _PyTuple_FromArray(_PyTuple_ITEMS(old_result), r);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
goto empty;
|
goto empty;
|
||||||
po->result = result;
|
po->result = result;
|
||||||
for (i=0; i<r ; i++) {
|
|
||||||
elem = PyTuple_GET_ITEM(old_result, i);
|
|
||||||
Py_INCREF(elem);
|
|
||||||
PyTuple_SET_ITEM(result, i, elem);
|
|
||||||
}
|
|
||||||
Py_DECREF(old_result);
|
Py_DECREF(old_result);
|
||||||
}
|
}
|
||||||
/* Now, we've got the only copy so we can update it in-place */
|
/* Now, we've got the only copy so we can update it in-place */
|
||||||
|
|
|
@ -1276,20 +1276,7 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...)
|
||||||
_Py_NO_INLINE PyObject *
|
_Py_NO_INLINE PyObject *
|
||||||
_PyStack_AsTuple(PyObject *const *stack, Py_ssize_t nargs)
|
_PyStack_AsTuple(PyObject *const *stack, Py_ssize_t nargs)
|
||||||
{
|
{
|
||||||
PyObject *args;
|
return _PyTuple_FromArray(stack, nargs);
|
||||||
Py_ssize_t i;
|
|
||||||
|
|
||||||
args = PyTuple_New(nargs);
|
|
||||||
if (args == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i < nargs; i++) {
|
|
||||||
PyObject *item = stack[i];
|
|
||||||
Py_INCREF(item);
|
|
||||||
PyTuple_SET_ITEM(args, i, item);
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1297,24 +1284,11 @@ PyObject*
|
||||||
_PyStack_AsTupleSlice(PyObject *const *stack, Py_ssize_t nargs,
|
_PyStack_AsTupleSlice(PyObject *const *stack, Py_ssize_t nargs,
|
||||||
Py_ssize_t start, Py_ssize_t end)
|
Py_ssize_t start, Py_ssize_t end)
|
||||||
{
|
{
|
||||||
PyObject *args;
|
|
||||||
Py_ssize_t i;
|
|
||||||
|
|
||||||
assert(0 <= start);
|
assert(0 <= start);
|
||||||
assert(end <= nargs);
|
assert(end <= nargs);
|
||||||
assert(start <= end);
|
assert(start <= end);
|
||||||
|
|
||||||
args = PyTuple_New(end - start);
|
return _PyTuple_FromArray(stack + start, end - start);
|
||||||
if (args == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=start; i < end; i++) {
|
|
||||||
PyObject *item = stack[i];
|
|
||||||
Py_INCREF(item);
|
|
||||||
PyTuple_SET_ITEM(args, i - start, item);
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_object.h"
|
#include "pycore_object.h"
|
||||||
#include "pycore_pystate.h"
|
#include "pycore_pystate.h"
|
||||||
|
#include "pycore_tupleobject.h"
|
||||||
#include "pycore_accu.h"
|
#include "pycore_accu.h"
|
||||||
|
|
||||||
#ifdef STDC_HEADERS
|
#ifdef STDC_HEADERS
|
||||||
|
@ -2501,26 +2502,11 @@ PyList_Reverse(PyObject *v)
|
||||||
PyObject *
|
PyObject *
|
||||||
PyList_AsTuple(PyObject *v)
|
PyList_AsTuple(PyObject *v)
|
||||||
{
|
{
|
||||||
PyObject *w;
|
|
||||||
PyObject **p, **q;
|
|
||||||
Py_ssize_t n;
|
|
||||||
if (v == NULL || !PyList_Check(v)) {
|
if (v == NULL || !PyList_Check(v)) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
n = Py_SIZE(v);
|
return _PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(v));
|
||||||
w = PyTuple_New(n);
|
|
||||||
if (w == NULL)
|
|
||||||
return NULL;
|
|
||||||
p = ((PyTupleObject *)w)->ob_item;
|
|
||||||
q = ((PyListObject *)v)->ob_item;
|
|
||||||
while (--n >= 0) {
|
|
||||||
Py_INCREF(*q);
|
|
||||||
*p = *q;
|
|
||||||
p++;
|
|
||||||
q++;
|
|
||||||
}
|
|
||||||
return w;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
and posixmodule for example uses. */
|
and posixmodule for example uses. */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "pycore_tupleobject.h"
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
static const char visible_length_key[] = "n_sequence_fields";
|
static const char visible_length_key[] = "n_sequence_fields";
|
||||||
|
@ -250,7 +251,7 @@ structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored))
|
||||||
n_fields = REAL_SIZE(self);
|
n_fields = REAL_SIZE(self);
|
||||||
n_visible_fields = VISIBLE_SIZE(self);
|
n_visible_fields = VISIBLE_SIZE(self);
|
||||||
n_unnamed_fields = UNNAMED_FIELDS(self);
|
n_unnamed_fields = UNNAMED_FIELDS(self);
|
||||||
tup = PyTuple_New(n_visible_fields);
|
tup = _PyTuple_FromArray(self->ob_item, n_visible_fields);
|
||||||
if (!tup)
|
if (!tup)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -258,12 +259,7 @@ structseq_reduce(PyStructSequence* self, PyObject *Py_UNUSED(ignored))
|
||||||
if (!dict)
|
if (!dict)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
for (i = 0; i < n_visible_fields; i++) {
|
for (i = n_visible_fields; i < n_fields; i++) {
|
||||||
Py_INCREF(self->ob_item[i]);
|
|
||||||
PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i < n_fields; i++) {
|
|
||||||
const char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
|
const char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
|
||||||
if (PyDict_SetItemString(dict, n, self->ob_item[i]) < 0)
|
if (PyDict_SetItemString(dict, n, self->ob_item[i]) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -419,14 +419,26 @@ tupleitem(PyTupleObject *a, Py_ssize_t i)
|
||||||
return a->ob_item[i];
|
return a->ob_item[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
|
||||||
|
{
|
||||||
|
PyTupleObject *tuple = (PyTupleObject *)PyTuple_New(n);
|
||||||
|
if (tuple == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyObject **dst = tuple->ob_item;
|
||||||
|
for (Py_ssize_t i = 0; i < n; i++) {
|
||||||
|
PyObject *item = src[i];
|
||||||
|
Py_INCREF(item);
|
||||||
|
dst[i] = item;
|
||||||
|
}
|
||||||
|
return (PyObject *)tuple;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
tupleslice(PyTupleObject *a, Py_ssize_t ilow,
|
tupleslice(PyTupleObject *a, Py_ssize_t ilow,
|
||||||
Py_ssize_t ihigh)
|
Py_ssize_t ihigh)
|
||||||
{
|
{
|
||||||
PyTupleObject *np;
|
|
||||||
PyObject **src, **dest;
|
|
||||||
Py_ssize_t i;
|
|
||||||
Py_ssize_t len;
|
|
||||||
if (ilow < 0)
|
if (ilow < 0)
|
||||||
ilow = 0;
|
ilow = 0;
|
||||||
if (ihigh > Py_SIZE(a))
|
if (ihigh > Py_SIZE(a))
|
||||||
|
@ -437,18 +449,7 @@ tupleslice(PyTupleObject *a, Py_ssize_t ilow,
|
||||||
Py_INCREF(a);
|
Py_INCREF(a);
|
||||||
return (PyObject *)a;
|
return (PyObject *)a;
|
||||||
}
|
}
|
||||||
len = ihigh - ilow;
|
return _PyTuple_FromArray(a->ob_item + ilow, ihigh - ilow);
|
||||||
np = (PyTupleObject *)PyTuple_New(len);
|
|
||||||
if (np == NULL)
|
|
||||||
return NULL;
|
|
||||||
src = a->ob_item + ilow;
|
|
||||||
dest = np->ob_item;
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
PyObject *v = src[i];
|
|
||||||
Py_INCREF(v);
|
|
||||||
dest[i] = v;
|
|
||||||
}
|
|
||||||
return (PyObject *)np;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
|
|
@ -3831,16 +3831,11 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
||||||
|
|
||||||
/* Pack other positional arguments into the *args argument */
|
/* Pack other positional arguments into the *args argument */
|
||||||
if (co->co_flags & CO_VARARGS) {
|
if (co->co_flags & CO_VARARGS) {
|
||||||
u = PyTuple_New(argcount - n);
|
u = _PyTuple_FromArray(args + n, argcount - n);
|
||||||
if (u == NULL) {
|
if (u == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
SETLOCAL(total_args, u);
|
SETLOCAL(total_args, u);
|
||||||
for (i = n; i < argcount; i++) {
|
|
||||||
x = args[i];
|
|
||||||
Py_INCREF(x);
|
|
||||||
PyTuple_SET_ITEM(u, i-n, x);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle keyword arguments passed as two strided arrays */
|
/* Handle keyword arguments passed as two strided arrays */
|
||||||
|
|
Loading…
Reference in New Issue