From 7525a389a2619beab806db64919b5c01f3735495 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 9 Nov 2020 12:51:46 +0100 Subject: [PATCH 1/2] bpo-42294: Add PyTuple_GetItemRef() function Added PyTuple_GetItemRef() function: similar to PyTuple_GetItem(), but return a strong reference. --- Doc/c-api/tuple.rst | 13 ++++++++++-- Doc/data/refcounts.dat | 4 ++++ Doc/whatsnew/3.10.rst | 4 ++++ Include/tupleobject.h | 1 + .../2020-11-09-12-10-23.bpo-42294.Kt0LG9.rst | 3 +++ Modules/_datetimemodule.c | 21 +++---------------- Modules/_sqlite/row.c | 16 +++++--------- Objects/tupleobject.c | 11 +++++++++- PC/python3dll.c | 1 + Python/ceval.c | 4 ++-- 10 files changed, 44 insertions(+), 34 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-11-09-12-10-23.bpo-42294.Kt0LG9.rst diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst index bf751e44acde09..3d0b2bcbe1e061 100644 --- a/Doc/c-api/tuple.rst +++ b/Doc/c-api/tuple.rst @@ -54,10 +54,19 @@ Tuple Objects no error checking is performed. +.. c:function:: PyObject* PyTuple_GetItemRef(PyObject *p, Py_ssize_t pos) + + Return a :term:`strong reference` to the object at position *pos* in the + tuple pointed to by *p*. If *pos* is out of bounds, return ``NULL`` and set + an :exc:`IndexError` exception. + + .. versionadded:: 3.10 + + .. c:function:: PyObject* PyTuple_GetItem(PyObject *p, Py_ssize_t pos) - Return the object at position *pos* in the tuple pointed to by *p*. If *pos* is - out of bounds, return ``NULL`` and set an :exc:`IndexError` exception. + Similar to :c:func:`PyTuple_GetItemRef`, but return a :term:`borrowed + reference`. .. c:function:: PyObject* PyTuple_GET_ITEM(PyObject *p, Py_ssize_t pos) diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 8a6ee718a012dd..a9144b8a14c85a 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2251,6 +2251,10 @@ PyTuple_GetItem:PyObject*::0: PyTuple_GetItem:PyObject*:p:0: PyTuple_GetItem:Py_ssize_t:pos:: +PyTuple_GetItemRef:PyObject*::+1: +PyTuple_GetItemRef:PyObject*:p:0: +PyTuple_GetItemRef:Py_ssize_t:pos:: + PyTuple_GET_SIZE:Py_ssize_t::: PyTuple_GET_SIZE:PyObject*:p:0: diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index a735bf235435ca..ef699ff1c2054b 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -429,6 +429,10 @@ New Features slot. (Contributed by Hai Shi in :issue:`41832`.) +* Added :c:func:`PyTuple_GetItemRef` function: similar to + :c:func:`PyTuple_GetItem`, but return a :term:`strong reference`. + (Contributed by Victor Stinner in :issue:`42262`.) + Porting to Python 3.10 ---------------------- diff --git a/Include/tupleobject.h b/Include/tupleobject.h index e796a320192c20..da6610a1a2f871 100644 --- a/Include/tupleobject.h +++ b/Include/tupleobject.h @@ -30,6 +30,7 @@ PyAPI_DATA(PyTypeObject) PyTupleIter_Type; PyAPI_FUNC(PyObject *) PyTuple_New(Py_ssize_t size); PyAPI_FUNC(Py_ssize_t) PyTuple_Size(PyObject *); PyAPI_FUNC(PyObject *) PyTuple_GetItem(PyObject *, Py_ssize_t); +PyAPI_FUNC(PyObject *) PyTuple_GetItemRef(PyObject *, Py_ssize_t); PyAPI_FUNC(int) PyTuple_SetItem(PyObject *, Py_ssize_t, PyObject *); PyAPI_FUNC(PyObject *) PyTuple_GetSlice(PyObject *, Py_ssize_t, Py_ssize_t); PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...); diff --git a/Misc/NEWS.d/next/C API/2020-11-09-12-10-23.bpo-42294.Kt0LG9.rst b/Misc/NEWS.d/next/C API/2020-11-09-12-10-23.bpo-42294.Kt0LG9.rst new file mode 100644 index 00000000000000..377d95d1ab3b46 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-11-09-12-10-23.bpo-42294.Kt0LG9.rst @@ -0,0 +1,3 @@ +Added :c:func:`PyTuple_GetItemRef` function: similar to +:c:func:`PyTuple_GetItem`, but return a :term:`strong reference`. +Patch by Victor Stinner. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index e59f89b3d10fb0..b880a59b937dd0 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3264,34 +3264,19 @@ iso_calendar_date_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) static PyObject * iso_calendar_date_year(PyDateTime_IsoCalendarDate *self, void *unused) { - PyObject *year = PyTuple_GetItem((PyObject *)self, 0); - if (year == NULL) { - return NULL; - } - Py_INCREF(year); - return year; + return PyTuple_GetItemRef((PyObject *)self, 0); } static PyObject * iso_calendar_date_week(PyDateTime_IsoCalendarDate *self, void *unused) { - PyObject *week = PyTuple_GetItem((PyObject *)self, 1); - if (week == NULL) { - return NULL; - } - Py_INCREF(week); - return week; + return PyTuple_GetItemRef((PyObject *)self, 1); } static PyObject * iso_calendar_date_weekday(PyDateTime_IsoCalendarDate *self, void *unused) { - PyObject *weekday = PyTuple_GetItem((PyObject *)self, 2); - if (weekday == NULL) { - return NULL; - } - Py_INCREF(weekday); - return weekday; + return PyTuple_GetItem((PyObject *)self, 2); } static PyGetSetDef iso_calendar_date_getset[] = { diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index 76b6f04f0ccbfd..2afaf0a8fccabf 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -74,9 +74,7 @@ pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx) { - PyObject* item = PyTuple_GetItem(self->data, idx); - Py_XINCREF(item); - return item; + return PyTuple_GetItemRef(self->data, idx); } static int @@ -111,7 +109,6 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) { Py_ssize_t _idx; Py_ssize_t nitems, i; - PyObject* item; if (PyLong_Check(idx)) { _idx = PyNumber_AsSsize_t(idx, PyExc_IndexError); @@ -119,10 +116,9 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) return NULL; if (_idx < 0) _idx += PyTuple_GET_SIZE(self->data); - item = PyTuple_GetItem(self->data, _idx); - Py_XINCREF(item); - return item; - } else if (PyUnicode_Check(idx)) { + return PyTuple_GetItemRef(self->data, _idx); + } + else if (PyUnicode_Check(idx)) { nitems = PyTuple_Size(self->description); for (i = 0; i < nitems; i++) { @@ -135,9 +131,7 @@ PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) } if (eq) { /* found item */ - item = PyTuple_GetItem(self->data, i); - Py_INCREF(item); - return item; + return PyTuple_GetItemRef(self->data, i); } } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 41677d7e710aa6..315ebb056d708d 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -187,7 +187,16 @@ PyTuple_GetItem(PyObject *op, Py_ssize_t i) PyErr_SetString(PyExc_IndexError, "tuple index out of range"); return NULL; } - return ((PyTupleObject *)op) -> ob_item[i]; + return PyTuple_GET_ITEM(op, i); +} + +PyObject * +PyTuple_GetItemRef(PyObject *op, Py_ssize_t i) +{ + PyObject *item = PyTuple_GetItem(op, i); + // On a newly created tuple, an item can still be NULL + Py_XINCREF(item); + return item; } int diff --git a/PC/python3dll.c b/PC/python3dll.c index d1fdd0ac54ca8d..4fe88156a5b5e4 100644 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -539,6 +539,7 @@ EXPORT_FUNC(PyThreadState_Swap) EXPORT_FUNC(PyTraceBack_Here) EXPORT_FUNC(PyTraceBack_Print) EXPORT_FUNC(PyTuple_GetItem) +EXPORT_FUNC(PyTuple_GetItemRef) EXPORT_FUNC(PyTuple_GetSlice) EXPORT_FUNC(PyTuple_New) EXPORT_FUNC(PyTuple_Pack) diff --git a/Python/ceval.c b/Python/ceval.c index 32e3019682f0ae..099ee2a6a03d5d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1091,9 +1091,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) /* Tuple access macros */ #ifndef Py_DEBUG -#define GETITEM(v, i) PyTuple_GET_ITEM((PyTupleObject *)(v), (i)) +# define GETITEM(v, i) PyTuple_GET_ITEM((PyTupleObject *)(v), (i)) #else -#define GETITEM(v, i) PyTuple_GetItem((v), (i)) +# define GETITEM(v, i) PyTuple_GetItem((v), (i)) #endif /* Code access macros */ From 89aabcbf8ba45bd66f84b1b5e946000a33aa0a1e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 9 Nov 2020 15:33:57 +0100 Subject: [PATCH 2/2] Fix typo --- Modules/_datetimemodule.c | 2 +- Objects/tupleobject.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index b880a59b937dd0..c4dbd7a1b1c3e1 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3276,7 +3276,7 @@ iso_calendar_date_week(PyDateTime_IsoCalendarDate *self, void *unused) static PyObject * iso_calendar_date_weekday(PyDateTime_IsoCalendarDate *self, void *unused) { - return PyTuple_GetItem((PyObject *)self, 2); + return PyTuple_GetItemRef((PyObject *)self, 2); } static PyGetSetDef iso_calendar_date_getset[] = { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 315ebb056d708d..c7d3e19123d39f 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -195,8 +195,7 @@ PyTuple_GetItemRef(PyObject *op, Py_ssize_t i) { PyObject *item = PyTuple_GetItem(op, i); // On a newly created tuple, an item can still be NULL - Py_XINCREF(item); - return item; + return Py_XNewRef(item); } int