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_ */