Caffe2 - C++ API
A deep learning, cross platform ML framework
python_compat.h
1 #pragma once
2 
3 #include <torch/csrc/python_headers.h>
4 
5 // PyPy 3.6 does not yet have PySlice_Unpack
6 #if PY_VERSION_HEX < 0x03060100 || defined(PYPY_VERSION)
7 
8 // PySlice_Unpack not introduced till python 3.6.1
9 // included here for backwards compatibility
10 // https://docs.python.org/3/c-api/slice.html#c.PySlice_Unpack
11 // https://github.com/python/cpython/blob/master/Objects/sliceobject.c#L196
12 
13 inline int
14 __PySlice_Unpack(PyObject *_r,
15  Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
16 {
17  PySliceObject *r = (PySliceObject*)_r;
18  /* this is harder to get right than you might think */
19 
20  // Py_BUILD_ASSERT replaced because it is not available in all versions
21  static_assert(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX, "Build failed");
22 
23  if (r->step == Py_None) {
24  *step = 1;
25  }
26  else {
27  if (!_PyEval_SliceIndex(r->step, step)) return -1;
28  if (*step == 0) {
29  PyErr_SetString(PyExc_ValueError,
30  "slice step cannot be zero");
31  return -1;
32  }
33  /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
34  * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it
35  * guards against later undefined behaviour resulting from code that
36  * does "step = -step" as part of a slice reversal.
37  */
38  if (*step < -PY_SSIZE_T_MAX)
39  *step = -PY_SSIZE_T_MAX;
40  }
41 
42  if (r->start == Py_None) {
43  *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
44  }
45  else {
46  if (!_PyEval_SliceIndex(r->start, start)) return -1;
47  }
48 
49  if (r->stop == Py_None) {
50  *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
51  }
52  else {
53  if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
54  }
55 
56  return 0;
57 }
58 
59 #define THPUtils_unpackSlice(SLICE, START, STOP, STEP) \
60  (__PySlice_Unpack(SLICE, START, STOP, STEP) == 0)
61 #else
62 #define THPUtils_unpackSlice(SLICE, START, STOP, STEP) \
63  (PySlice_Unpack(SLICE, START, STOP, STEP) == 0)
64 #endif
65 
66 // https://bugsfiles.kde.org/attachment.cgi?id=61186
67 #if PY_VERSION_HEX >= 0x03020000
68 #define THPUtils_parseSlice(SLICE, LEN, START, STOP, LENGTH, STEP) \
69  (PySlice_GetIndicesEx(SLICE, LEN, START, STOP, LENGTH, STEP) == 0)
70 #else
71 #define THPUtils_parseSlice(SLICE, LEN, START, STOP, LENGTH, STEP) \
72  (PySlice_GetIndicesEx((PySliceObject*)SLICE, LEN, START, STOP, LENGTH, STEP) == 0)
73 #endif