Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6e08baf

Browse files
Issue #27867: Function PySlice_GetIndicesEx() is deprecated and replaced with
a macro if Py_LIMITED_API is not set or set to the value between 0x03050400 and 0x03060000 (not including) or 0x03060100 or higher. Added functions PySlice_Unpack() and PySlice_AdjustIndices().
2 parents a8df847 + 512c57c commit 6e08baf

6 files changed

Lines changed: 119 additions & 26 deletions

File tree

Doc/c-api/slice.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,40 @@ Slice Objects
5656
.. versionchanged:: 3.2
5757
The parameter type for the *slice* parameter was ``PySliceObject*``
5858
before.
59+
60+
.. versionchanged:: 3.6.1
61+
If ``Py_LIMITED_API`` is not set or set to the value between ``0x03050400``
62+
and ``0x03060000`` (not including) or ``0x03060100`` or higher
63+
:c:func:`!PySlice_GetIndicesEx` is implemented as a macro using
64+
:c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`.
65+
Arguments *start*, *stop* and *step* are evaluated more than once.
66+
67+
.. deprecated:: 3.6.1
68+
If ``Py_LIMITED_API`` is set to the value less than ``0x03050400`` or
69+
between ``0x03060000`` and ``0x03060100`` (not including)
70+
:c:func:`!PySlice_GetIndicesEx` is a deprecated function.
71+
72+
73+
.. c:function:: int PySlice_Unpack(PyObject *slice, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
74+
75+
Extract the start, stop and step data members from a slice object as
76+
C integers. Silently reduce values larger than ``PY_SSIZE_T_MAX`` to
77+
``PY_SSIZE_T_MAX``, silently boost the start and stop values less than
78+
``-PY_SSIZE_T_MAX-1`` to ``-PY_SSIZE_T_MAX-1``, and silently boost the step
79+
values less than ``-PY_SSIZE_T_MAX`` to ``-PY_SSIZE_T_MAX``.
80+
81+
Return ``-1`` on error, ``0`` on success.
82+
83+
.. versionadded:: 3.6.1
84+
85+
86+
.. c:function:: Py_ssize_t PySlice_AdjustIndices(Py_ssize_t length, Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
87+
88+
Adjust start/end slice indices assuming a sequence of the specified length.
89+
Out of bounds indices are clipped in a manner consistent with the handling
90+
of normal slices.
91+
92+
Return the length of the slice. Always successful. Doesn't call Python
93+
code.
94+
95+
.. versionadded:: 3.6.1

Doc/whatsnew/3.7.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,17 @@ Build and C API Changes
128128
is now of type ``const char *`` rather of ``char *``.
129129
(Contributed by Serhiy Storchaka in :issue:`28769`.)
130130

131+
* Added functions :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`.
132+
(Contributed by Serhiy Storchaka in :issue:`27867`.)
133+
131134

132135
Deprecated
133136
==========
134137

138+
- Function :c:func:`PySlice_GetIndicesEx` is deprecated and replaced with
139+
a macro if ``Py_LIMITED_API`` is not set or set to the value between
140+
``0x03050400`` and ``0x03060000`` (not including) or ``0x03060100`` or
141+
higher. (Contributed by Serhiy Storchaka in :issue:`27867`.)
135142

136143

137144
Removed

Include/sliceobject.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,20 @@ PyAPI_FUNC(int) _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
4141
PyAPI_FUNC(int) PySlice_GetIndices(PyObject *r, Py_ssize_t length,
4242
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step);
4343
PyAPI_FUNC(int) PySlice_GetIndicesEx(PyObject *r, Py_ssize_t length,
44-
Py_ssize_t *start, Py_ssize_t *stop,
45-
Py_ssize_t *step, Py_ssize_t *slicelength);
44+
Py_ssize_t *start, Py_ssize_t *stop,
45+
Py_ssize_t *step, Py_ssize_t *slicelength) Py_DEPRECATED(3.7);
46+
47+
#if !defined(Py_LIMITED_API) || (Py_LIMITED_API+0 >= 0x03050400 && Py_LIMITED_API+0 < 0x03060000) || Py_LIMITED_API+0 >= 0x03060100
48+
#define PySlice_GetIndicesEx(slice, length, start, stop, step, slicelen) ( \
49+
PySlice_Unpack((slice), (start), (stop), (step)) < 0 ? -1 : \
50+
((*slicelen = PySlice_AdjustIndices((length), (start), (stop), *(step))), \
51+
0))
52+
PyAPI_FUNC(int) PySlice_Unpack(PyObject *slice,
53+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step);
54+
PyAPI_FUNC(Py_ssize_t) PySlice_AdjustIndices(Py_ssize_t length,
55+
Py_ssize_t *start, Py_ssize_t *stop,
56+
Py_ssize_t step);
57+
#endif
4658

4759
#ifdef __cplusplus
4860
}

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,11 @@ Windows
623623
C API
624624
-----
625625

626+
- Issue #27867: Function PySlice_GetIndicesEx() is deprecated and replaced with
627+
a macro if Py_LIMITED_API is not set or set to the value between 0x03050400
628+
and 0x03060000 (not including) or 0x03060100 or higher. Added functions
629+
PySlice_Unpack() and PySlice_AdjustIndices().
630+
626631
- Issue #29083: Fixed the declaration of some public API functions.
627632
PyArg_VaParse() and PyArg_VaParseTupleAndKeywords() were not available in
628633
limited API. PyArg_ValidateKeywordArguments(), PyArg_UnpackTuple() and

Objects/sliceobject.c

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,12 @@ PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
191191
}
192192

193193
int
194-
PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
195-
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
196-
Py_ssize_t *slicelength)
194+
PySlice_Unpack(PyObject *_r,
195+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
197196
{
198197
PySliceObject *r = (PySliceObject*)_r;
199198
/* this is harder to get right than you might think */
200199

201-
Py_ssize_t defstart, defstop;
202-
203200
if (r->step == Py_None) {
204201
*step = 1;
205202
}
@@ -219,42 +216,75 @@ PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
219216
*step = -PY_SSIZE_T_MAX;
220217
}
221218

222-
defstart = *step < 0 ? length-1 : 0;
223-
defstop = *step < 0 ? -1 : length;
224-
225219
if (r->start == Py_None) {
226-
*start = defstart;
220+
*start = *step < 0 ? PY_SSIZE_T_MAX-1 : 0;;
227221
}
228222
else {
229223
if (!_PyEval_SliceIndex(r->start, start)) return -1;
230-
if (*start < 0) *start += length;
231-
if (*start < 0) *start = (*step < 0) ? -1 : 0;
232-
if (*start >= length)
233-
*start = (*step < 0) ? length - 1 : length;
234224
}
235225

236226
if (r->stop == Py_None) {
237-
*stop = defstop;
227+
*stop = *step < 0 ? -PY_SSIZE_T_MAX : PY_SSIZE_T_MAX;
238228
}
239229
else {
240230
if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
241-
if (*stop < 0) *stop += length;
242-
if (*stop < 0) *stop = (*step < 0) ? -1 : 0;
243-
if (*stop >= length)
244-
*stop = (*step < 0) ? length - 1 : length;
245231
}
246232

247-
if ((*step < 0 && *stop >= *start)
248-
|| (*step > 0 && *start >= *stop)) {
249-
*slicelength = 0;
233+
return 0;
234+
}
235+
236+
Py_ssize_t
237+
PySlice_AdjustIndices(Py_ssize_t length,
238+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
239+
{
240+
/* this is harder to get right than you might think */
241+
242+
assert(step != 0);
243+
assert(step >= -PY_SSIZE_T_MAX);
244+
245+
if (*start < 0) {
246+
*start += length;
247+
if (*start < 0) {
248+
*start = (step < 0) ? -1 : 0;
249+
}
250250
}
251-
else if (*step < 0) {
252-
*slicelength = (*stop-*start+1)/(*step)+1;
251+
else if (*start >= length) {
252+
*start = (step < 0) ? length - 1 : length;
253+
}
254+
255+
if (*stop < 0) {
256+
*stop += length;
257+
if (*stop < 0) {
258+
*stop = (step < 0) ? -1 : 0;
259+
}
260+
}
261+
else if (*stop >= length) {
262+
*stop = (step < 0) ? length - 1 : length;
263+
}
264+
265+
if (step < 0) {
266+
if (*stop < *start) {
267+
return (*start - *stop - 1) / (-step) + 1;
268+
}
253269
}
254270
else {
255-
*slicelength = (*stop-*start-1)/(*step)+1;
271+
if (*start < *stop) {
272+
return (*stop - *start - 1) / step + 1;
273+
}
256274
}
275+
return 0;
276+
}
277+
278+
#undef PySlice_GetIndicesEx
257279

280+
int
281+
PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
282+
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
283+
Py_ssize_t *slicelength)
284+
{
285+
if (PySlice_Unpack(_r, start, stop, step) < 0)
286+
return -1;
287+
*slicelength = PySlice_AdjustIndices(length, start, stop, *step);
258288
return 0;
259289
}
260290

PC/python3.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,10 +531,12 @@ EXPORTS
531531
PySet_Pop=python37.PySet_Pop
532532
PySet_Size=python37.PySet_Size
533533
PySet_Type=python37.PySet_Type DATA
534+
PySlice_AdjustIndices=python37.PySlice_AdjustIndices
534535
PySlice_GetIndices=python37.PySlice_GetIndices
535536
PySlice_GetIndicesEx=python37.PySlice_GetIndicesEx
536537
PySlice_New=python37.PySlice_New
537538
PySlice_Type=python37.PySlice_Type DATA
539+
PySlice_Unpack=python37.PySlice_Unpack
538540
PySortWrapper_Type=python37.PySortWrapper_Type DATA
539541
PyState_AddModule=python37.PyState_AddModule
540542
PyState_FindModule=python37.PyState_FindModule

0 commit comments

Comments
 (0)