Skip to content

Commit a2ead7e

Browse files
committed
gh-117518: Add PyTuple_GetItemRef() function
Replace Py_NewRef(PyTuple_GET_ITEM(tuple, pos)) with PyTuple_GetItemRef(tuple, pos).
1 parent c43f6a4 commit a2ead7e

24 files changed

+72
-36
lines changed

Doc/c-api/tuple.rst

+13-2
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,21 @@ Tuple Objects
5454
no error checking is performed.
5555
5656
57+
.. c:function:: PyObject* PyTuple_GetItemRef(PyObject *p, Py_ssize_t pos)
58+
59+
Return a :term:`strong reference` to the object at position *pos* in the
60+
tuple pointed to by *p*.
61+
62+
If *pos* is negative or out of bounds, return ``NULL`` and set an
63+
:exc:`IndexError` exception.
64+
65+
.. versionadded:: 3.13
66+
67+
5768
.. c:function:: PyObject* PyTuple_GetItem(PyObject *p, Py_ssize_t pos)
5869
59-
Return the object at position *pos* in the tuple pointed to by *p*. If *pos* is
60-
negative or out of bounds, return ``NULL`` and set an :exc:`IndexError` exception.
70+
Similar to :c:func:`PyTuple_GetItemRef`, but return a :term:`borrowed
71+
reference`.
6172
6273
6374
.. c:function:: PyObject* PyTuple_GET_ITEM(PyObject *p, Py_ssize_t pos)

Doc/data/stable_abi.dat

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Doc/whatsnew/3.13.rst

+5
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,11 @@ New Features
17731773
* Add :c:func:`PyType_GetModuleByDef` to the limited C API
17741774
(Contributed by Victor Stinner in :gh:`116936`.)
17751775

1776+
* Add :c:func:`PyTuple_GetItemRef` function, similar to
1777+
:c:func:`PyTuple_GetItem` but return a :term:`strong reference` instead of a
1778+
:term:`borrowed reference`.
1779+
(Contributed by Victor Stinner in :gh:`117518`.)
1780+
17761781

17771782
Porting to Python 3.13
17781783
----------------------

Include/internal/pycore_opcode_metadata.h

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/tupleobject.h

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ PyAPI_DATA(PyTypeObject) PyTupleIter_Type;
3030
PyAPI_FUNC(PyObject *) PyTuple_New(Py_ssize_t size);
3131
PyAPI_FUNC(Py_ssize_t) PyTuple_Size(PyObject *);
3232
PyAPI_FUNC(PyObject *) PyTuple_GetItem(PyObject *, Py_ssize_t);
33+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030d0000
34+
PyAPI_FUNC(PyObject *) PyTuple_GetItemRef(PyObject *, Py_ssize_t);
35+
#endif
3336
PyAPI_FUNC(int) PyTuple_SetItem(PyObject *, Py_ssize_t, PyObject *);
3437
PyAPI_FUNC(PyObject *) PyTuple_GetSlice(PyObject *, Py_ssize_t, Py_ssize_t);
3538
PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...);

Lib/test/test_stable_abi_ctypes.py

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add :c:func:`PyTuple_GetItemRef` function, similar to
2+
:c:func:`PyTuple_GetItem` but return a :term:`strong reference` instead of a
3+
:term:`borrowed reference`. Patch by Victor Stinner.

Misc/stable_abi.toml

+2
Original file line numberDiff line numberDiff line change
@@ -2506,3 +2506,5 @@
25062506
added = '3.13'
25072507
[function.PyType_GetModuleByDef]
25082508
added = '3.13'
2509+
[function.PyTuple_GetItemRef]
2510+
added = '3.13'

Modules/_datetimemodule.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ divide_nearest(PyObject *m, PyObject *n)
213213
temp = _PyLong_DivmodNear(m, n);
214214
if (temp == NULL)
215215
return NULL;
216-
result = Py_NewRef(PyTuple_GET_ITEM(temp, 0));
216+
result = PyTuple_GetItemRef(temp, 0);
217217
Py_DECREF(temp);
218218

219219
return result;
@@ -1978,7 +1978,7 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
19781978
goto BadDivmod;
19791979
}
19801980

1981-
num = Py_NewRef(PyTuple_GET_ITEM(tuple, 0)); /* leftover seconds */
1981+
num = PyTuple_GetItemRef(tuple, 0); /* leftover seconds */
19821982
Py_DECREF(tuple);
19831983

19841984
tuple = checked_divmod(num, st->seconds_per_day);
@@ -1996,7 +1996,7 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
19961996
goto BadDivmod;
19971997
}
19981998

1999-
num = Py_NewRef(PyTuple_GET_ITEM(tuple, 0)); /* leftover days */
1999+
num = PyTuple_GetItemRef(tuple, 0); /* leftover days */
20002000
d = PyLong_AsInt(num);
20012001
if (d == -1 && PyErr_Occurred()) {
20022002
goto Done;

Modules/_testcapi/heaptype.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ test_from_spec_invalid_metatype_inheritance(PyObject *self, PyObject *Py_UNUSED(
164164
"TypeError args are not a one-tuple");
165165
goto finally;
166166
}
167-
message = Py_NewRef(PyTuple_GET_ITEM(args, 0));
167+
message = PyTuple_GetItemRef(args, 0);
168168
meta_error_string = PyUnicode_FromString("metaclass conflict:");
169169
if (meta_error_string == NULL) {
170170
goto finally;
@@ -1028,7 +1028,7 @@ HeapCCollection_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
10281028
}
10291029

10301030
for (Py_ssize_t i = 0; i < size; i++) {
1031-
data[i] = Py_NewRef(PyTuple_GET_ITEM(args, i));
1031+
data[i] = PyTuple_GetItemRef(args, i);
10321032
}
10331033

10341034
result = self;

Objects/exceptions.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds)
641641
if (size == 0)
642642
return 0;
643643
if (size == 1) {
644-
Py_XSETREF(self->code, Py_NewRef(PyTuple_GET_ITEM(args, 0)));
644+
Py_XSETREF(self->code, PyTuple_GetItemRef(args, 0));
645645
}
646646
else { /* size > 1 */
647647
Py_XSETREF(self->code, Py_NewRef(args));
@@ -1546,7 +1546,7 @@ ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds)
15461546
Py_XSETREF(self->name_from, Py_XNewRef(name_from));
15471547

15481548
if (PyTuple_GET_SIZE(args) == 1) {
1549-
msg = Py_NewRef(PyTuple_GET_ITEM(args, 0));
1549+
msg = PyTuple_GetItemRef(args, 0);
15501550
}
15511551
Py_XSETREF(self->msg, msg);
15521552

@@ -2034,8 +2034,8 @@ OSError_reduce(PyOSErrorObject *self, PyObject *Py_UNUSED(ignored))
20342034
if (!args)
20352035
return NULL;
20362036

2037-
PyTuple_SET_ITEM(args, 0, Py_NewRef(PyTuple_GET_ITEM(self->args, 0)));
2038-
PyTuple_SET_ITEM(args, 1, Py_NewRef(PyTuple_GET_ITEM(self->args, 1)));
2037+
PyTuple_SET_ITEM(args, 0, PyTuple_GetItemRef(self->args, 0));
2038+
PyTuple_SET_ITEM(args, 1, PyTuple_GetItemRef(self->args, 1));
20392039
PyTuple_SET_ITEM(args, 2, Py_NewRef(self->filename));
20402040

20412041
if (self->filename2) {
@@ -2389,7 +2389,7 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
23892389
return -1;
23902390

23912391
if (lenargs >= 1) {
2392-
Py_XSETREF(self->msg, Py_NewRef(PyTuple_GET_ITEM(args, 0)));
2392+
Py_XSETREF(self->msg, PyTuple_GetItemRef(args, 0));
23932393
}
23942394
if (lenargs == 2) {
23952395
info = PyTuple_GET_ITEM(args, 1);

Objects/memoryobject.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2121,7 +2121,7 @@ struct_unpack_single(const char *ptr, struct unpacker *x)
21212121
return NULL;
21222122

21232123
if (PyTuple_GET_SIZE(v) == 1) {
2124-
PyObject *res = Py_NewRef(PyTuple_GET_ITEM(v, 0));
2124+
PyObject *res = PyTuple_GetItemRef(v, 0);
21252125
Py_DECREF(v);
21262126
return res;
21272127
}

Objects/tupleobject.c

+9
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,15 @@ PyTuple_GetItem(PyObject *op, Py_ssize_t i)
109109
return ((PyTupleObject *)op) -> ob_item[i];
110110
}
111111

112+
113+
PyObject *
114+
PyTuple_GetItemRef(PyObject *op, Py_ssize_t index)
115+
{
116+
PyObject *item = PyTuple_GetItem(op, index);
117+
return Py_XNewRef(item);
118+
}
119+
120+
112121
int
113122
PyTuple_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem)
114123
{

Objects/typeobject.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -6453,8 +6453,8 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
64536453
Py_DECREF(newargs);
64546454
return -1;
64556455
}
6456-
*args = Py_NewRef(PyTuple_GET_ITEM(newargs, 0));
6457-
*kwargs = Py_NewRef(PyTuple_GET_ITEM(newargs, 1));
6456+
*args = PyTuple_GetItemRef(newargs, 0);
6457+
*kwargs = PyTuple_GetItemRef(newargs, 1);
64586458
Py_DECREF(newargs);
64596459

64606460
/* XXX We should perhaps allow None to be passed here. */

Objects/unionobject.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ union_getitem(PyObject *self, PyObject *item)
293293
res = make_union(newargs);
294294
}
295295
else {
296-
res = Py_NewRef(PyTuple_GET_ITEM(newargs, 0));
296+
res = PyTuple_GetItemRef(newargs, 0);
297297
for (Py_ssize_t iarg = 1; iarg < nargs; iarg++) {
298298
PyObject *arg = PyTuple_GET_ITEM(newargs, iarg);
299299
Py_SETREF(res, PyNumber_Or(res, arg));

PC/python3dll.c

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/bytecodes.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -1237,8 +1237,8 @@ dummy_func(
12371237
DEOPT_IF(!PyTuple_CheckExact(seq));
12381238
DEOPT_IF(PyTuple_GET_SIZE(seq) != 2);
12391239
STAT_INC(UNPACK_SEQUENCE, hit);
1240-
val0 = Py_NewRef(PyTuple_GET_ITEM(seq, 0));
1241-
val1 = Py_NewRef(PyTuple_GET_ITEM(seq, 1));
1240+
val0 = PyTuple_GetItemRef(seq, 0);
1241+
val1 = PyTuple_GetItemRef(seq, 1);
12421242
DECREF_INPUTS();
12431243
}
12441244

@@ -2702,7 +2702,7 @@ dummy_func(
27022702
PyTupleObject *seq = it->it_seq;
27032703
assert(seq);
27042704
assert(it->it_index < PyTuple_GET_SIZE(seq));
2705-
next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++));
2705+
next = PyTuple_GetItemRef((PyObject*)seq, it->it_index++);
27062706
}
27072707

27082708
macro(FOR_ITER_TUPLE) =

Python/ceval.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -2031,8 +2031,8 @@ _PyEval_ExceptionGroupMatch(PyObject* exc_value, PyObject *match_type,
20312031
}
20322032
assert(PyTuple_CheckExact(pair));
20332033
assert(PyTuple_GET_SIZE(pair) == 2);
2034-
*match = Py_NewRef(PyTuple_GET_ITEM(pair, 0));
2035-
*rest = Py_NewRef(PyTuple_GET_ITEM(pair, 1));
2034+
*match = PyTuple_GetItemRef(pair, 0);
2035+
*rest = PyTuple_GetItemRef(pair, 1);
20362036
Py_DECREF(pair);
20372037
return 0;
20382038
}

Python/codecs.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ _PyCodec_EncodeInternal(PyObject *object,
411411
"encoder must return a tuple (object, integer)");
412412
goto onError;
413413
}
414-
v = Py_NewRef(PyTuple_GET_ITEM(result,0));
414+
v = PyTuple_GetItemRef(result, 0);
415415
/* We don't check or use the second (integer) entry. */
416416

417417
Py_DECREF(args);
@@ -455,7 +455,7 @@ _PyCodec_DecodeInternal(PyObject *object,
455455
"decoder must return a tuple (object,integer)");
456456
goto onError;
457457
}
458-
v = Py_NewRef(PyTuple_GET_ITEM(result,0));
458+
v = PyTuple_GetItemRef(result, 0);
459459
/* We don't check or use the second (integer) entry. */
460460

461461
Py_DECREF(args);
@@ -550,7 +550,7 @@ PyObject *codec_getitem_checked(const char *encoding,
550550
if (codec == NULL)
551551
return NULL;
552552

553-
v = Py_NewRef(PyTuple_GET_ITEM(codec, index));
553+
v = PyTuple_GetItemRef(codec, index);
554554
Py_DECREF(codec);
555555
return v;
556556
}

Python/compile.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1064,7 +1064,7 @@ merge_consts_recursive(PyObject *const_cache, PyObject *o)
10641064
}
10651065
PyObject *u;
10661066
if (PyTuple_CheckExact(k)) {
1067-
u = Py_NewRef(PyTuple_GET_ITEM(k, 1));
1067+
u = PyTuple_GetItemRef(k, 1);
10681068
Py_DECREF(k);
10691069
}
10701070
else {

Python/executor_cases.c.h

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/getargs.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1625,7 +1625,7 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
16251625
if (!skip) {
16261626
PyObject *current_arg;
16271627
if (i < nargs) {
1628-
current_arg = Py_NewRef(PyTuple_GET_ITEM(args, i));
1628+
current_arg = PyTuple_GetItemRef(args, i);
16291629
}
16301630
else if (nkwargs && i >= pos) {
16311631
if (PyDict_GetItemStringRef(kwargs, kwlist[i], &current_arg) < 0) {

0 commit comments

Comments
 (0)