npy_3kcompat.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /*
  2. * This is a convenience header file providing compatibility utilities
  3. * for supporting Python 2 and Python 3 in the same code base.
  4. *
  5. * If you want to use this for your own projects, it's recommended to make a
  6. * copy of it. Although the stuff below is unlikely to change, we don't provide
  7. * strong backwards compatibility guarantees at the moment.
  8. */
  9. #ifndef _NPY_3KCOMPAT_H_
  10. #define _NPY_3KCOMPAT_H_
  11. #include <Python.h>
  12. #include <stdio.h>
  13. #if PY_VERSION_HEX >= 0x03000000
  14. #ifndef NPY_PY3K
  15. #define NPY_PY3K 1
  16. #endif
  17. #endif
  18. #include "numpy/npy_common.h"
  19. #include "numpy/ndarrayobject.h"
  20. #ifdef __cplusplus
  21. extern "C" {
  22. #endif
  23. /*
  24. * PyInt -> PyLong
  25. */
  26. #if defined(NPY_PY3K)
  27. /* Return True only if the long fits in a C long */
  28. static NPY_INLINE int PyInt_Check(PyObject *op) {
  29. int overflow = 0;
  30. if (!PyLong_Check(op)) {
  31. return 0;
  32. }
  33. PyLong_AsLongAndOverflow(op, &overflow);
  34. return (overflow == 0);
  35. }
  36. #define PyInt_FromLong PyLong_FromLong
  37. #define PyInt_AsLong PyLong_AsLong
  38. #define PyInt_AS_LONG PyLong_AsLong
  39. #define PyInt_AsSsize_t PyLong_AsSsize_t
  40. /* NOTE:
  41. *
  42. * Since the PyLong type is very different from the fixed-range PyInt,
  43. * we don't define PyInt_Type -> PyLong_Type.
  44. */
  45. #endif /* NPY_PY3K */
  46. /*
  47. * PyString -> PyBytes
  48. */
  49. #if defined(NPY_PY3K)
  50. #define PyString_Type PyBytes_Type
  51. #define PyString_Check PyBytes_Check
  52. #define PyStringObject PyBytesObject
  53. #define PyString_FromString PyBytes_FromString
  54. #define PyString_FromStringAndSize PyBytes_FromStringAndSize
  55. #define PyString_AS_STRING PyBytes_AS_STRING
  56. #define PyString_AsStringAndSize PyBytes_AsStringAndSize
  57. #define PyString_FromFormat PyBytes_FromFormat
  58. #define PyString_Concat PyBytes_Concat
  59. #define PyString_ConcatAndDel PyBytes_ConcatAndDel
  60. #define PyString_AsString PyBytes_AsString
  61. #define PyString_GET_SIZE PyBytes_GET_SIZE
  62. #define PyString_Size PyBytes_Size
  63. #define PyUString_Type PyUnicode_Type
  64. #define PyUString_Check PyUnicode_Check
  65. #define PyUStringObject PyUnicodeObject
  66. #define PyUString_FromString PyUnicode_FromString
  67. #define PyUString_FromStringAndSize PyUnicode_FromStringAndSize
  68. #define PyUString_FromFormat PyUnicode_FromFormat
  69. #define PyUString_Concat PyUnicode_Concat2
  70. #define PyUString_ConcatAndDel PyUnicode_ConcatAndDel
  71. #define PyUString_GET_SIZE PyUnicode_GET_SIZE
  72. #define PyUString_Size PyUnicode_Size
  73. #define PyUString_InternFromString PyUnicode_InternFromString
  74. #define PyUString_Format PyUnicode_Format
  75. #else
  76. #define PyBytes_Type PyString_Type
  77. #define PyBytes_Check PyString_Check
  78. #define PyBytesObject PyStringObject
  79. #define PyBytes_FromString PyString_FromString
  80. #define PyBytes_FromStringAndSize PyString_FromStringAndSize
  81. #define PyBytes_AS_STRING PyString_AS_STRING
  82. #define PyBytes_AsStringAndSize PyString_AsStringAndSize
  83. #define PyBytes_FromFormat PyString_FromFormat
  84. #define PyBytes_Concat PyString_Concat
  85. #define PyBytes_ConcatAndDel PyString_ConcatAndDel
  86. #define PyBytes_AsString PyString_AsString
  87. #define PyBytes_GET_SIZE PyString_GET_SIZE
  88. #define PyBytes_Size PyString_Size
  89. #define PyUString_Type PyString_Type
  90. #define PyUString_Check PyString_Check
  91. #define PyUStringObject PyStringObject
  92. #define PyUString_FromString PyString_FromString
  93. #define PyUString_FromStringAndSize PyString_FromStringAndSize
  94. #define PyUString_FromFormat PyString_FromFormat
  95. #define PyUString_Concat PyString_Concat
  96. #define PyUString_ConcatAndDel PyString_ConcatAndDel
  97. #define PyUString_GET_SIZE PyString_GET_SIZE
  98. #define PyUString_Size PyString_Size
  99. #define PyUString_InternFromString PyString_InternFromString
  100. #define PyUString_Format PyString_Format
  101. #endif /* NPY_PY3K */
  102. static NPY_INLINE void
  103. PyUnicode_ConcatAndDel(PyObject **left, PyObject *right)
  104. {
  105. PyObject *newobj;
  106. newobj = PyUnicode_Concat(*left, right);
  107. Py_DECREF(*left);
  108. Py_DECREF(right);
  109. *left = newobj;
  110. }
  111. static NPY_INLINE void
  112. PyUnicode_Concat2(PyObject **left, PyObject *right)
  113. {
  114. PyObject *newobj;
  115. newobj = PyUnicode_Concat(*left, right);
  116. Py_DECREF(*left);
  117. *left = newobj;
  118. }
  119. /*
  120. * PyFile_* compatibility
  121. */
  122. #if defined(NPY_PY3K)
  123. /*
  124. * Get a FILE* handle to the file represented by the Python object
  125. */
  126. static NPY_INLINE FILE*
  127. npy_PyFile_Dup2(PyObject *file, char *mode, npy_off_t *orig_pos)
  128. {
  129. int fd, fd2, unbuf;
  130. PyObject *ret, *os, *io, *io_raw;
  131. npy_off_t pos;
  132. FILE *handle;
  133. /* Flush first to ensure things end up in the file in the correct order */
  134. ret = PyObject_CallMethod(file, "flush", "");
  135. if (ret == NULL) {
  136. return NULL;
  137. }
  138. Py_DECREF(ret);
  139. fd = PyObject_AsFileDescriptor(file);
  140. if (fd == -1) {
  141. return NULL;
  142. }
  143. /*
  144. * The handle needs to be dup'd because we have to call fclose
  145. * at the end
  146. */
  147. os = PyImport_ImportModule("os");
  148. if (os == NULL) {
  149. return NULL;
  150. }
  151. ret = PyObject_CallMethod(os, "dup", "i", fd);
  152. Py_DECREF(os);
  153. if (ret == NULL) {
  154. return NULL;
  155. }
  156. fd2 = PyNumber_AsSsize_t(ret, NULL);
  157. Py_DECREF(ret);
  158. /* Convert to FILE* handle */
  159. #ifdef _WIN32
  160. handle = _fdopen(fd2, mode);
  161. #else
  162. handle = fdopen(fd2, mode);
  163. #endif
  164. if (handle == NULL) {
  165. PyErr_SetString(PyExc_IOError,
  166. "Getting a FILE* from a Python file object failed");
  167. }
  168. /* Record the original raw file handle position */
  169. *orig_pos = npy_ftell(handle);
  170. if (*orig_pos == -1) {
  171. /* The io module is needed to determine if buffering is used */
  172. io = PyImport_ImportModule("io");
  173. if (io == NULL) {
  174. fclose(handle);
  175. return NULL;
  176. }
  177. /* File object instances of RawIOBase are unbuffered */
  178. io_raw = PyObject_GetAttrString(io, "RawIOBase");
  179. Py_DECREF(io);
  180. if (io_raw == NULL) {
  181. fclose(handle);
  182. return NULL;
  183. }
  184. unbuf = PyObject_IsInstance(file, io_raw);
  185. Py_DECREF(io_raw);
  186. if (unbuf == 1) {
  187. /* Succeed if the IO is unbuffered */
  188. return handle;
  189. }
  190. else {
  191. PyErr_SetString(PyExc_IOError, "obtaining file position failed");
  192. fclose(handle);
  193. return NULL;
  194. }
  195. }
  196. /* Seek raw handle to the Python-side position */
  197. ret = PyObject_CallMethod(file, "tell", "");
  198. if (ret == NULL) {
  199. fclose(handle);
  200. return NULL;
  201. }
  202. pos = PyLong_AsLongLong(ret);
  203. Py_DECREF(ret);
  204. if (PyErr_Occurred()) {
  205. fclose(handle);
  206. return NULL;
  207. }
  208. if (npy_fseek(handle, pos, SEEK_SET) == -1) {
  209. PyErr_SetString(PyExc_IOError, "seeking file failed");
  210. fclose(handle);
  211. return NULL;
  212. }
  213. return handle;
  214. }
  215. /*
  216. * Close the dup-ed file handle, and seek the Python one to the current position
  217. */
  218. static NPY_INLINE int
  219. npy_PyFile_DupClose2(PyObject *file, FILE* handle, npy_off_t orig_pos)
  220. {
  221. int fd, unbuf;
  222. PyObject *ret, *io, *io_raw;
  223. npy_off_t position;
  224. position = npy_ftell(handle);
  225. /* Close the FILE* handle */
  226. fclose(handle);
  227. /*
  228. * Restore original file handle position, in order to not confuse
  229. * Python-side data structures
  230. */
  231. fd = PyObject_AsFileDescriptor(file);
  232. if (fd == -1) {
  233. return -1;
  234. }
  235. if (npy_lseek(fd, orig_pos, SEEK_SET) == -1) {
  236. /* The io module is needed to determine if buffering is used */
  237. io = PyImport_ImportModule("io");
  238. if (io == NULL) {
  239. return -1;
  240. }
  241. /* File object instances of RawIOBase are unbuffered */
  242. io_raw = PyObject_GetAttrString(io, "RawIOBase");
  243. Py_DECREF(io);
  244. if (io_raw == NULL) {
  245. return -1;
  246. }
  247. unbuf = PyObject_IsInstance(file, io_raw);
  248. Py_DECREF(io_raw);
  249. if (unbuf == 1) {
  250. /* Succeed if the IO is unbuffered */
  251. return 0;
  252. }
  253. else {
  254. PyErr_SetString(PyExc_IOError, "seeking file failed");
  255. return -1;
  256. }
  257. }
  258. if (position == -1) {
  259. PyErr_SetString(PyExc_IOError, "obtaining file position failed");
  260. return -1;
  261. }
  262. /* Seek Python-side handle to the FILE* handle position */
  263. ret = PyObject_CallMethod(file, "seek", NPY_OFF_T_PYFMT "i", position, 0);
  264. if (ret == NULL) {
  265. return -1;
  266. }
  267. Py_DECREF(ret);
  268. return 0;
  269. }
  270. static NPY_INLINE int
  271. npy_PyFile_Check(PyObject *file)
  272. {
  273. int fd;
  274. fd = PyObject_AsFileDescriptor(file);
  275. if (fd == -1) {
  276. PyErr_Clear();
  277. return 0;
  278. }
  279. return 1;
  280. }
  281. #else
  282. static NPY_INLINE FILE *
  283. npy_PyFile_Dup2(PyObject *file,
  284. const char *NPY_UNUSED(mode), npy_off_t *NPY_UNUSED(orig_pos))
  285. {
  286. FILE * fp = PyFile_AsFile(file);
  287. if (fp == NULL) {
  288. PyErr_SetString(PyExc_IOError,
  289. "first argument must be an open file");
  290. return NULL;
  291. }
  292. return fp;
  293. }
  294. static NPY_INLINE int
  295. npy_PyFile_DupClose2(PyObject *NPY_UNUSED(file), FILE* NPY_UNUSED(handle),
  296. npy_off_t NPY_UNUSED(orig_pos))
  297. {
  298. return 0;
  299. }
  300. #define npy_PyFile_Check PyFile_Check
  301. #endif
  302. static NPY_INLINE PyObject*
  303. npy_PyFile_OpenFile(PyObject *filename, const char *mode)
  304. {
  305. PyObject *open;
  306. open = PyDict_GetItemString(PyEval_GetBuiltins(), "open");
  307. if (open == NULL) {
  308. return NULL;
  309. }
  310. return PyObject_CallFunction(open, "Os", filename, mode);
  311. }
  312. static NPY_INLINE int
  313. npy_PyFile_CloseFile(PyObject *file)
  314. {
  315. PyObject *ret;
  316. ret = PyObject_CallMethod(file, "close", NULL);
  317. if (ret == NULL) {
  318. return -1;
  319. }
  320. Py_DECREF(ret);
  321. return 0;
  322. }
  323. /*
  324. * PyObject_Cmp
  325. */
  326. #if defined(NPY_PY3K)
  327. static NPY_INLINE int
  328. PyObject_Cmp(PyObject *i1, PyObject *i2, int *cmp)
  329. {
  330. int v;
  331. v = PyObject_RichCompareBool(i1, i2, Py_LT);
  332. if (v == 1) {
  333. *cmp = -1;
  334. return 1;
  335. }
  336. else if (v == -1) {
  337. return -1;
  338. }
  339. v = PyObject_RichCompareBool(i1, i2, Py_GT);
  340. if (v == 1) {
  341. *cmp = 1;
  342. return 1;
  343. }
  344. else if (v == -1) {
  345. return -1;
  346. }
  347. v = PyObject_RichCompareBool(i1, i2, Py_EQ);
  348. if (v == 1) {
  349. *cmp = 0;
  350. return 1;
  351. }
  352. else {
  353. *cmp = 0;
  354. return -1;
  355. }
  356. }
  357. #endif
  358. /*
  359. * PyCObject functions adapted to PyCapsules.
  360. *
  361. * The main job here is to get rid of the improved error handling
  362. * of PyCapsules. It's a shame...
  363. */
  364. #if PY_VERSION_HEX >= 0x03000000
  365. static NPY_INLINE PyObject *
  366. NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *))
  367. {
  368. PyObject *ret = PyCapsule_New(ptr, NULL, dtor);
  369. if (ret == NULL) {
  370. PyErr_Clear();
  371. }
  372. return ret;
  373. }
  374. static NPY_INLINE PyObject *
  375. NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context, void (*dtor)(PyObject *))
  376. {
  377. PyObject *ret = NpyCapsule_FromVoidPtr(ptr, dtor);
  378. if (ret != NULL && PyCapsule_SetContext(ret, context) != 0) {
  379. PyErr_Clear();
  380. Py_DECREF(ret);
  381. ret = NULL;
  382. }
  383. return ret;
  384. }
  385. static NPY_INLINE void *
  386. NpyCapsule_AsVoidPtr(PyObject *obj)
  387. {
  388. void *ret = PyCapsule_GetPointer(obj, NULL);
  389. if (ret == NULL) {
  390. PyErr_Clear();
  391. }
  392. return ret;
  393. }
  394. static NPY_INLINE void *
  395. NpyCapsule_GetDesc(PyObject *obj)
  396. {
  397. return PyCapsule_GetContext(obj);
  398. }
  399. static NPY_INLINE int
  400. NpyCapsule_Check(PyObject *ptr)
  401. {
  402. return PyCapsule_CheckExact(ptr);
  403. }
  404. #else
  405. static NPY_INLINE PyObject *
  406. NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(void *))
  407. {
  408. return PyCObject_FromVoidPtr(ptr, dtor);
  409. }
  410. static NPY_INLINE PyObject *
  411. NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context,
  412. void (*dtor)(void *, void *))
  413. {
  414. return PyCObject_FromVoidPtrAndDesc(ptr, context, dtor);
  415. }
  416. static NPY_INLINE void *
  417. NpyCapsule_AsVoidPtr(PyObject *ptr)
  418. {
  419. return PyCObject_AsVoidPtr(ptr);
  420. }
  421. static NPY_INLINE void *
  422. NpyCapsule_GetDesc(PyObject *obj)
  423. {
  424. return PyCObject_GetDesc(obj);
  425. }
  426. static NPY_INLINE int
  427. NpyCapsule_Check(PyObject *ptr)
  428. {
  429. return PyCObject_Check(ptr);
  430. }
  431. #endif
  432. #ifdef __cplusplus
  433. }
  434. #endif
  435. #endif /* _NPY_3KCOMPAT_H_ */