/ lib / numpy / core / include / numpy / npy_3kcompat.h
npy_3kcompat.h
  1  /*
  2   * This is a convenience header file providing compatibility utilities
  3   * for supporting different minor versions of Python 3.
  4   * It was originally used to support the transition from Python 2,
  5   * hence the "3k" naming.
  6   *
  7   * If you want to use this for your own projects, it's recommended to make a
  8   * copy of it. Although the stuff below is unlikely to change, we don't provide
  9   * strong backwards compatibility guarantees at the moment.
 10   */
 11  
 12  #ifndef NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_
 13  #define NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_
 14  
 15  #include <Python.h>
 16  #include <stdio.h>
 17  
 18  #ifndef NPY_PY3K
 19  #define NPY_PY3K 1
 20  #endif
 21  
 22  #include "numpy/npy_common.h"
 23  #include "numpy/ndarrayobject.h"
 24  
 25  #ifdef __cplusplus
 26  extern "C" {
 27  #endif
 28  
 29  /*
 30   * PyInt -> PyLong
 31   */
 32  
 33  
 34  /*
 35   * This is a renamed copy of the Python non-limited API function _PyLong_AsInt. It is
 36   * included here because it is missing from the PyPy API. It completes the PyLong_As*
 37   * group of functions and can be useful in replacing PyInt_Check.
 38   */
 39  static NPY_INLINE int
 40  Npy__PyLong_AsInt(PyObject *obj)
 41  {
 42      int overflow;
 43      long result = PyLong_AsLongAndOverflow(obj, &overflow);
 44  
 45      /* INT_MAX and INT_MIN are defined in Python.h */
 46      if (overflow || result > INT_MAX || result < INT_MIN) {
 47          /* XXX: could be cute and give a different
 48             message for overflow == -1 */
 49          PyErr_SetString(PyExc_OverflowError,
 50                          "Python int too large to convert to C int");
 51          return -1;
 52      }
 53      return (int)result;
 54  }
 55  
 56  
 57  #if defined(NPY_PY3K)
 58  /* Return True only if the long fits in a C long */
 59  static NPY_INLINE int PyInt_Check(PyObject *op) {
 60      int overflow = 0;
 61      if (!PyLong_Check(op)) {
 62          return 0;
 63      }
 64      PyLong_AsLongAndOverflow(op, &overflow);
 65      return (overflow == 0);
 66  }
 67  
 68  
 69  #define PyInt_FromLong PyLong_FromLong
 70  #define PyInt_AsLong PyLong_AsLong
 71  #define PyInt_AS_LONG PyLong_AsLong
 72  #define PyInt_AsSsize_t PyLong_AsSsize_t
 73  #define PyNumber_Int PyNumber_Long
 74  
 75  /* NOTE:
 76   *
 77   * Since the PyLong type is very different from the fixed-range PyInt,
 78   * we don't define PyInt_Type -> PyLong_Type.
 79   */
 80  #endif /* NPY_PY3K */
 81  
 82  /* Py3 changes PySlice_GetIndicesEx' first argument's type to PyObject* */
 83  #ifdef NPY_PY3K
 84  #  define NpySlice_GetIndicesEx PySlice_GetIndicesEx
 85  #else
 86  #  define NpySlice_GetIndicesEx(op, nop, start, end, step, slicelength) \
 87      PySlice_GetIndicesEx((PySliceObject *)op, nop, start, end, step, slicelength)
 88  #endif
 89  
 90  #if PY_VERSION_HEX < 0x030900a4
 91      /* Introduced in https://github.com/python/cpython/commit/d2ec81a8c99796b51fb8c49b77a7fe369863226f */
 92      #define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0)
 93      /* Introduced in https://github.com/python/cpython/commit/b10dc3e7a11fcdb97e285882eba6da92594f90f9 */
 94      #define Py_SET_SIZE(obj, size) ((Py_SIZE(obj) = (size)), (void)0)
 95      /* Introduced in https://github.com/python/cpython/commit/c86a11221df7e37da389f9c6ce6e47ea22dc44ff */
 96      #define Py_SET_REFCNT(obj, refcnt) ((Py_REFCNT(obj) = (refcnt)), (void)0)
 97  #endif
 98  
 99  
100  #define Npy_EnterRecursiveCall(x) Py_EnterRecursiveCall(x)
101  
102  /* Py_SETREF was added in 3.5.2, and only if Py_LIMITED_API is absent */
103  #if PY_VERSION_HEX < 0x03050200
104      #define Py_SETREF(op, op2)                      \
105          do {                                        \
106              PyObject *_py_tmp = (PyObject *)(op);   \
107              (op) = (op2);                           \
108              Py_DECREF(_py_tmp);                     \
109          } while (0)
110  #endif
111  
112  /* introduced in https://github.com/python/cpython/commit/a24107b04c1277e3c1105f98aff5bfa3a98b33a0 */
113  #if PY_VERSION_HEX < 0x030800A3
114      static NPY_INLINE PyObject *
115      _PyDict_GetItemStringWithError(PyObject *v, const char *key)
116      {
117          PyObject *kv, *rv;
118          kv = PyUnicode_FromString(key);
119          if (kv == NULL) {
120              return NULL;
121          }
122          rv = PyDict_GetItemWithError(v, kv);
123          Py_DECREF(kv);
124          return rv;
125      }
126  #endif
127  
128  /*
129   * PyString -> PyBytes
130   */
131  
132  #if defined(NPY_PY3K)
133  
134  #define PyString_Type PyBytes_Type
135  #define PyString_Check PyBytes_Check
136  #define PyStringObject PyBytesObject
137  #define PyString_FromString PyBytes_FromString
138  #define PyString_FromStringAndSize PyBytes_FromStringAndSize
139  #define PyString_AS_STRING PyBytes_AS_STRING
140  #define PyString_AsStringAndSize PyBytes_AsStringAndSize
141  #define PyString_FromFormat PyBytes_FromFormat
142  #define PyString_Concat PyBytes_Concat
143  #define PyString_ConcatAndDel PyBytes_ConcatAndDel
144  #define PyString_AsString PyBytes_AsString
145  #define PyString_GET_SIZE PyBytes_GET_SIZE
146  #define PyString_Size PyBytes_Size
147  
148  #define PyUString_Type PyUnicode_Type
149  #define PyUString_Check PyUnicode_Check
150  #define PyUStringObject PyUnicodeObject
151  #define PyUString_FromString PyUnicode_FromString
152  #define PyUString_FromStringAndSize PyUnicode_FromStringAndSize
153  #define PyUString_FromFormat PyUnicode_FromFormat
154  #define PyUString_Concat PyUnicode_Concat2
155  #define PyUString_ConcatAndDel PyUnicode_ConcatAndDel
156  #define PyUString_GET_SIZE PyUnicode_GET_SIZE
157  #define PyUString_Size PyUnicode_Size
158  #define PyUString_InternFromString PyUnicode_InternFromString
159  #define PyUString_Format PyUnicode_Format
160  
161  #define PyBaseString_Check(obj) (PyUnicode_Check(obj))
162  
163  #else
164  
165  #define PyBytes_Type PyString_Type
166  #define PyBytes_Check PyString_Check
167  #define PyBytesObject PyStringObject
168  #define PyBytes_FromString PyString_FromString
169  #define PyBytes_FromStringAndSize PyString_FromStringAndSize
170  #define PyBytes_AS_STRING PyString_AS_STRING
171  #define PyBytes_AsStringAndSize PyString_AsStringAndSize
172  #define PyBytes_FromFormat PyString_FromFormat
173  #define PyBytes_Concat PyString_Concat
174  #define PyBytes_ConcatAndDel PyString_ConcatAndDel
175  #define PyBytes_AsString PyString_AsString
176  #define PyBytes_GET_SIZE PyString_GET_SIZE
177  #define PyBytes_Size PyString_Size
178  
179  #define PyUString_Type PyString_Type
180  #define PyUString_Check PyString_Check
181  #define PyUStringObject PyStringObject
182  #define PyUString_FromString PyString_FromString
183  #define PyUString_FromStringAndSize PyString_FromStringAndSize
184  #define PyUString_FromFormat PyString_FromFormat
185  #define PyUString_Concat PyString_Concat
186  #define PyUString_ConcatAndDel PyString_ConcatAndDel
187  #define PyUString_GET_SIZE PyString_GET_SIZE
188  #define PyUString_Size PyString_Size
189  #define PyUString_InternFromString PyString_InternFromString
190  #define PyUString_Format PyString_Format
191  
192  #define PyBaseString_Check(obj) (PyBytes_Check(obj) || PyUnicode_Check(obj))
193  
194  #endif /* NPY_PY3K */
195  
196  
197  static NPY_INLINE void
198  PyUnicode_ConcatAndDel(PyObject **left, PyObject *right)
199  {
200      Py_SETREF(*left, PyUnicode_Concat(*left, right));
201      Py_DECREF(right);
202  }
203  
204  static NPY_INLINE void
205  PyUnicode_Concat2(PyObject **left, PyObject *right)
206  {
207      Py_SETREF(*left, PyUnicode_Concat(*left, right));
208  }
209  
210  /*
211   * PyFile_* compatibility
212   */
213  
214  /*
215   * Get a FILE* handle to the file represented by the Python object
216   */
217  static NPY_INLINE FILE*
218  npy_PyFile_Dup2(PyObject *file, char *mode, npy_off_t *orig_pos)
219  {
220      int fd, fd2, unbuf;
221      Py_ssize_t fd2_tmp;
222      PyObject *ret, *os, *io, *io_raw;
223      npy_off_t pos;
224      FILE *handle;
225  
226      /* For Python 2 PyFileObject, use PyFile_AsFile */
227  #if !defined(NPY_PY3K)
228      if (PyFile_Check(file)) {
229          return PyFile_AsFile(file);
230      }
231  #endif
232  
233      /* Flush first to ensure things end up in the file in the correct order */
234      ret = PyObject_CallMethod(file, "flush", "");
235      if (ret == NULL) {
236          return NULL;
237      }
238      Py_DECREF(ret);
239      fd = PyObject_AsFileDescriptor(file);
240      if (fd == -1) {
241          return NULL;
242      }
243  
244      /*
245       * The handle needs to be dup'd because we have to call fclose
246       * at the end
247       */
248      os = PyImport_ImportModule("os");
249      if (os == NULL) {
250          return NULL;
251      }
252      ret = PyObject_CallMethod(os, "dup", "i", fd);
253      Py_DECREF(os);
254      if (ret == NULL) {
255          return NULL;
256      }
257      fd2_tmp = PyNumber_AsSsize_t(ret, PyExc_IOError);
258      Py_DECREF(ret);
259      if (fd2_tmp == -1 && PyErr_Occurred()) {
260          return NULL;
261      }
262      if (fd2_tmp < INT_MIN || fd2_tmp > INT_MAX) {
263          PyErr_SetString(PyExc_IOError,
264                          "Getting an 'int' from os.dup() failed");
265          return NULL;
266      }
267      fd2 = (int)fd2_tmp;
268  
269      /* Convert to FILE* handle */
270  #ifdef _WIN32
271      handle = _fdopen(fd2, mode);
272  #else
273      handle = fdopen(fd2, mode);
274  #endif
275      if (handle == NULL) {
276          PyErr_SetString(PyExc_IOError,
277                          "Getting a FILE* from a Python file object failed");
278          return NULL;
279      }
280  
281      /* Record the original raw file handle position */
282      *orig_pos = npy_ftell(handle);
283      if (*orig_pos == -1) {
284          /* The io module is needed to determine if buffering is used */
285          io = PyImport_ImportModule("io");
286          if (io == NULL) {
287              fclose(handle);
288              return NULL;
289          }
290          /* File object instances of RawIOBase are unbuffered */
291          io_raw = PyObject_GetAttrString(io, "RawIOBase");
292          Py_DECREF(io);
293          if (io_raw == NULL) {
294              fclose(handle);
295              return NULL;
296          }
297          unbuf = PyObject_IsInstance(file, io_raw);
298          Py_DECREF(io_raw);
299          if (unbuf == 1) {
300              /* Succeed if the IO is unbuffered */
301              return handle;
302          }
303          else {
304              PyErr_SetString(PyExc_IOError, "obtaining file position failed");
305              fclose(handle);
306              return NULL;
307          }
308      }
309  
310      /* Seek raw handle to the Python-side position */
311      ret = PyObject_CallMethod(file, "tell", "");
312      if (ret == NULL) {
313          fclose(handle);
314          return NULL;
315      }
316      pos = PyLong_AsLongLong(ret);
317      Py_DECREF(ret);
318      if (PyErr_Occurred()) {
319          fclose(handle);
320          return NULL;
321      }
322      if (npy_fseek(handle, pos, SEEK_SET) == -1) {
323          PyErr_SetString(PyExc_IOError, "seeking file failed");
324          fclose(handle);
325          return NULL;
326      }
327      return handle;
328  }
329  
330  /*
331   * Close the dup-ed file handle, and seek the Python one to the current position
332   */
333  static NPY_INLINE int
334  npy_PyFile_DupClose2(PyObject *file, FILE* handle, npy_off_t orig_pos)
335  {
336      int fd, unbuf;
337      PyObject *ret, *io, *io_raw;
338      npy_off_t position;
339  
340      /* For Python 2 PyFileObject, do nothing */
341  #if !defined(NPY_PY3K)
342      if (PyFile_Check(file)) {
343          return 0;
344      }
345  #endif
346  
347      position = npy_ftell(handle);
348  
349      /* Close the FILE* handle */
350      fclose(handle);
351  
352      /*
353       * Restore original file handle position, in order to not confuse
354       * Python-side data structures
355       */
356      fd = PyObject_AsFileDescriptor(file);
357      if (fd == -1) {
358          return -1;
359      }
360  
361      if (npy_lseek(fd, orig_pos, SEEK_SET) == -1) {
362  
363          /* The io module is needed to determine if buffering is used */
364          io = PyImport_ImportModule("io");
365          if (io == NULL) {
366              return -1;
367          }
368          /* File object instances of RawIOBase are unbuffered */
369          io_raw = PyObject_GetAttrString(io, "RawIOBase");
370          Py_DECREF(io);
371          if (io_raw == NULL) {
372              return -1;
373          }
374          unbuf = PyObject_IsInstance(file, io_raw);
375          Py_DECREF(io_raw);
376          if (unbuf == 1) {
377              /* Succeed if the IO is unbuffered */
378              return 0;
379          }
380          else {
381              PyErr_SetString(PyExc_IOError, "seeking file failed");
382              return -1;
383          }
384      }
385  
386      if (position == -1) {
387          PyErr_SetString(PyExc_IOError, "obtaining file position failed");
388          return -1;
389      }
390  
391      /* Seek Python-side handle to the FILE* handle position */
392      ret = PyObject_CallMethod(file, "seek", NPY_OFF_T_PYFMT "i", position, 0);
393      if (ret == NULL) {
394          return -1;
395      }
396      Py_DECREF(ret);
397      return 0;
398  }
399  
400  static NPY_INLINE int
401  npy_PyFile_Check(PyObject *file)
402  {
403      int fd;
404      /* For Python 2, check if it is a PyFileObject */
405  #if !defined(NPY_PY3K)
406      if (PyFile_Check(file)) {
407          return 1;
408      }
409  #endif
410      fd = PyObject_AsFileDescriptor(file);
411      if (fd == -1) {
412          PyErr_Clear();
413          return 0;
414      }
415      return 1;
416  }
417  
418  static NPY_INLINE PyObject*
419  npy_PyFile_OpenFile(PyObject *filename, const char *mode)
420  {
421      PyObject *open;
422      open = PyDict_GetItemString(PyEval_GetBuiltins(), "open");
423      if (open == NULL) {
424          return NULL;
425      }
426      return PyObject_CallFunction(open, "Os", filename, mode);
427  }
428  
429  static NPY_INLINE int
430  npy_PyFile_CloseFile(PyObject *file)
431  {
432      PyObject *ret;
433  
434      ret = PyObject_CallMethod(file, "close", NULL);
435      if (ret == NULL) {
436          return -1;
437      }
438      Py_DECREF(ret);
439      return 0;
440  }
441  
442  
443  /* This is a copy of _PyErr_ChainExceptions
444   */
445  static NPY_INLINE void
446  npy_PyErr_ChainExceptions(PyObject *exc, PyObject *val, PyObject *tb)
447  {
448      if (exc == NULL)
449          return;
450  
451      if (PyErr_Occurred()) {
452          /* only py3 supports this anyway */
453          #ifdef NPY_PY3K
454              PyObject *exc2, *val2, *tb2;
455              PyErr_Fetch(&exc2, &val2, &tb2);
456              PyErr_NormalizeException(&exc, &val, &tb);
457              if (tb != NULL) {
458                  PyException_SetTraceback(val, tb);
459                  Py_DECREF(tb);
460              }
461              Py_DECREF(exc);
462              PyErr_NormalizeException(&exc2, &val2, &tb2);
463              PyException_SetContext(val2, val);
464              PyErr_Restore(exc2, val2, tb2);
465          #endif
466      }
467      else {
468          PyErr_Restore(exc, val, tb);
469      }
470  }
471  
472  
473  /* This is a copy of _PyErr_ChainExceptions, with:
474   *  - a minimal implementation for python 2
475   *  - __cause__ used instead of __context__
476   */
477  static NPY_INLINE void
478  npy_PyErr_ChainExceptionsCause(PyObject *exc, PyObject *val, PyObject *tb)
479  {
480      if (exc == NULL)
481          return;
482  
483      if (PyErr_Occurred()) {
484          /* only py3 supports this anyway */
485          #ifdef NPY_PY3K
486              PyObject *exc2, *val2, *tb2;
487              PyErr_Fetch(&exc2, &val2, &tb2);
488              PyErr_NormalizeException(&exc, &val, &tb);
489              if (tb != NULL) {
490                  PyException_SetTraceback(val, tb);
491                  Py_DECREF(tb);
492              }
493              Py_DECREF(exc);
494              PyErr_NormalizeException(&exc2, &val2, &tb2);
495              PyException_SetCause(val2, val);
496              PyErr_Restore(exc2, val2, tb2);
497          #endif
498      }
499      else {
500          PyErr_Restore(exc, val, tb);
501      }
502  }
503  
504  /*
505   * PyObject_Cmp
506   */
507  #if defined(NPY_PY3K)
508  static NPY_INLINE int
509  PyObject_Cmp(PyObject *i1, PyObject *i2, int *cmp)
510  {
511      int v;
512      v = PyObject_RichCompareBool(i1, i2, Py_LT);
513      if (v == 1) {
514          *cmp = -1;
515          return 1;
516      }
517      else if (v == -1) {
518          return -1;
519      }
520  
521      v = PyObject_RichCompareBool(i1, i2, Py_GT);
522      if (v == 1) {
523          *cmp = 1;
524          return 1;
525      }
526      else if (v == -1) {
527          return -1;
528      }
529  
530      v = PyObject_RichCompareBool(i1, i2, Py_EQ);
531      if (v == 1) {
532          *cmp = 0;
533          return 1;
534      }
535      else {
536          *cmp = 0;
537          return -1;
538      }
539  }
540  #endif
541  
542  /*
543   * PyCObject functions adapted to PyCapsules.
544   *
545   * The main job here is to get rid of the improved error handling
546   * of PyCapsules. It's a shame...
547   */
548  static NPY_INLINE PyObject *
549  NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *))
550  {
551      PyObject *ret = PyCapsule_New(ptr, NULL, dtor);
552      if (ret == NULL) {
553          PyErr_Clear();
554      }
555      return ret;
556  }
557  
558  static NPY_INLINE PyObject *
559  NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context, void (*dtor)(PyObject *))
560  {
561      PyObject *ret = NpyCapsule_FromVoidPtr(ptr, dtor);
562      if (ret != NULL && PyCapsule_SetContext(ret, context) != 0) {
563          PyErr_Clear();
564          Py_DECREF(ret);
565          ret = NULL;
566      }
567      return ret;
568  }
569  
570  static NPY_INLINE void *
571  NpyCapsule_AsVoidPtr(PyObject *obj)
572  {
573      void *ret = PyCapsule_GetPointer(obj, NULL);
574      if (ret == NULL) {
575          PyErr_Clear();
576      }
577      return ret;
578  }
579  
580  static NPY_INLINE void *
581  NpyCapsule_GetDesc(PyObject *obj)
582  {
583      return PyCapsule_GetContext(obj);
584  }
585  
586  static NPY_INLINE int
587  NpyCapsule_Check(PyObject *ptr)
588  {
589      return PyCapsule_CheckExact(ptr);
590  }
591  
592  #ifdef __cplusplus
593  }
594  #endif
595  
596  
597  #endif  /* NUMPY_CORE_INCLUDE_NUMPY_NPY_3KCOMPAT_H_ */