diff --git a/Doc/deprecations/c-api-pending-removal-in-3.18.rst b/Doc/deprecations/c-api-pending-removal-in-3.18.rst index d04c746cd9f33e..9da3d73c9e1252 100644 --- a/Doc/deprecations/c-api-pending-removal-in-3.18.rst +++ b/Doc/deprecations/c-api-pending-removal-in-3.18.rst @@ -6,6 +6,7 @@ Pending removal in Python 3.18 * :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`. * :c:func:`!_PyDict_GetItemStringWithError`: use :c:func:`PyDict_GetItemStringRef`. * :c:func:`!_PyDict_Pop()`: :c:func:`PyDict_Pop`. + * :c:func:`!_PyLong_Sign()`: use :c:func:`PyLong_GetSign`. * :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`. * :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`. * :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 685a09dc70eec2..aa2f5cf93a7a68 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1390,6 +1390,7 @@ Deprecated * :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`. * :c:func:`!_PyDict_GetItemStringWithError`: use :c:func:`PyDict_GetItemStringRef`. * :c:func:`!_PyDict_Pop()`: use :c:func:`PyDict_Pop`. + * :c:func:`!_PyLong_Sign()`: use :c:func:`PyLong_GetSign`. * :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`. * :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`. * :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`. diff --git a/Include/cpython/longobject.h b/Include/cpython/longobject.h index 4d6e618f831ad8..7f28ad60b7467b 100644 --- a/Include/cpython/longobject.h +++ b/Include/cpython/longobject.h @@ -86,7 +86,7 @@ PyAPI_FUNC(int) PyLong_IsZero(PyObject *obj); - On failure, set an exception, and return -1. */ PyAPI_FUNC(int) PyLong_GetSign(PyObject *v, int *sign); -PyAPI_FUNC(int) _PyLong_Sign(PyObject *v); +Py_DEPRECATED(3.14) PyAPI_FUNC(int) _PyLong_Sign(PyObject *v); /* _PyLong_NumBits. Return the number of bits needed to represent the absolute value of a long. For example, this returns 1 for 1 and -1, 2 diff --git a/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst b/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst index a94d7933ad32ef..5e55cfb3c74a4b 100644 --- a/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst +++ b/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst @@ -4,6 +4,7 @@ Python 3.18: * :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`. * :c:func:`!_PyDict_GetItemStringWithError`: use :c:func:`PyDict_GetItemStringRef`. * :c:func:`!_PyDict_Pop()`: use :c:func:`PyDict_Pop`. +* :c:func:`!_PyLong_Sign()`: use :c:func:`PyLong_GetSign`. * :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`. * :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`. * :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`. diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 599b5f92c2a1f7..a6cfb2deeb23c1 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -2159,8 +2159,10 @@ save_long(PicklerObject *self, PyObject *obj) unsigned char *pdata; char header[5]; int i; - int sign = _PyLong_Sign(obj); + int sign; + assert(PyLong_Check(obj)); + (void)PyLong_GetSign(obj, &sign); if (sign == 0) { header[0] = LONG1; header[1] = 0; /* It's 0 -- an empty bytestring. */ diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index e77df5b57b0504..f3d234a7f9595e 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -25,7 +25,6 @@ #include "pycore_hashtable.h" // _Py_hashtable_new() #include "pycore_initconfig.h" // _Py_GetConfigsAsDict() #include "pycore_instruction_sequence.h" // _PyInstructionSequence_New() -#include "pycore_long.h" // _PyLong_Sign() #include "pycore_object.h" // _PyObject_IsFreed() #include "pycore_optimizer.h" // JitOptSymbol, etc. #include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal() @@ -1798,14 +1797,14 @@ _testinternalcapi_test_long_numbits_impl(PyObject *module) for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) { uint64_t nbits; - int sign; + int sign = -7; PyObject *plong; plong = PyLong_FromLong(testcases[i].input); if (plong == NULL) return NULL; nbits = _PyLong_NumBits(plong); - sign = _PyLong_Sign(plong); + (void)PyLong_GetSign(plong, &sign); Py_DECREF(plong); if (nbits != testcases[i].nbits) @@ -1813,7 +1812,7 @@ _testinternalcapi_test_long_numbits_impl(PyObject *module) "wrong result for _PyLong_NumBits"); if (sign != testcases[i].sign) return raiseTestError("test_long_numbits", - "wrong result for _PyLong_Sign"); + "wrong result for PyLong_GetSign()"); } Py_RETURN_NONE; } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index bcc77287454768..7ca43033d722ab 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -428,9 +428,10 @@ float_richcompare(PyObject *v, PyObject *w, int op) else if (PyLong_Check(w)) { int vsign = i == 0.0 ? 0 : i < 0.0 ? -1 : 1; - int wsign = _PyLong_Sign(w); + int wsign; int exponent; + (void)PyLong_GetSign(w, &wsign); if (vsign != wsign) { /* Magnitudes are irrelevant -- the signs alone * determine the outcome. diff --git a/Objects/longobject.c b/Objects/longobject.c index d449a01cedf886..370931e64d3627 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -827,19 +827,25 @@ PyLong_IsZero(PyObject *obj) return _PyLong_IsZero((PyLongObject *)obj); } -int -_PyLong_Sign(PyObject *vv) +static int +long_sign(PyObject *vv) { + assert(vv != NULL); + assert(PyLong_Check(vv)); PyLongObject *v = (PyLongObject *)vv; - assert(v != NULL); - assert(PyLong_Check(v)); if (_PyLong_IsCompact(v)) { return _PyLong_CompactSign(v); } return _PyLong_NonCompactSign(v); } +int +_PyLong_Sign(PyObject *vv) +{ + return long_sign(vv); +} + int PyLong_GetSign(PyObject *vv, int *sign) { @@ -848,7 +854,7 @@ PyLong_GetSign(PyObject *vv, int *sign) return -1; } - *sign = _PyLong_Sign(vv); + *sign = long_sign(vv); return 0; } diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index 4fef0af93fe095..1b07c2a2c498b9 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -399,11 +399,14 @@ _PySlice_GetLongIndices(PySliceObject *self, PyObject *length, step_is_negative = 0; } else { - int step_sign; step = evaluate_slice_index(self->step); - if (step == NULL) + if (step == NULL) { goto error; - step_sign = _PyLong_Sign(step); + } + assert(PyLong_Check(step)); + + int step_sign; + (void)PyLong_GetSign(step, &step_sign); if (step_sign == 0) { PyErr_SetString(PyExc_ValueError, "slice step cannot be zero");