numpy
2.0.0
|
00001 /* 00002 * This is a convenience header file providing compatibility utilities 00003 * for supporting Python 2 and Python 3 in the same code base. 00004 * 00005 * If you want to use this for your own projects, it's recommended to make a 00006 * copy of it. Although the stuff below is unlikely to change, we don't provide 00007 * strong backwards compatibility guarantees at the moment. 00008 */ 00009 00010 #ifndef _NPY_3KCOMPAT_H_ 00011 #define _NPY_3KCOMPAT_H_ 00012 00013 #include <Python.h> 00014 #include <stdio.h> 00015 00016 #if PY_VERSION_HEX >= 0x03000000 00017 #ifndef NPY_PY3K 00018 #define NPY_PY3K 1 00019 #endif 00020 #endif 00021 00022 #include "numpy/npy_common.h" 00023 #include "numpy/ndarrayobject.h" 00024 00025 #ifdef __cplusplus 00026 extern "C" { 00027 #endif 00028 00029 /* 00030 * PyInt -> PyLong 00031 */ 00032 00033 #if defined(NPY_PY3K) 00034 /* Return True only if the long fits in a C long */ 00035 static NPY_INLINE int PyInt_Check(PyObject *op) { 00036 int overflow = 0; 00037 if (!PyLong_Check(op)) { 00038 return 0; 00039 } 00040 PyLong_AsLongAndOverflow(op, &overflow); 00041 return (overflow == 0); 00042 } 00043 00044 #define PyInt_FromLong PyLong_FromLong 00045 #define PyInt_AsLong PyLong_AsLong 00046 #define PyInt_AS_LONG PyLong_AsLong 00047 #define PyInt_AsSsize_t PyLong_AsSsize_t 00048 00049 /* NOTE: 00050 * 00051 * Since the PyLong type is very different from the fixed-range PyInt, 00052 * we don't define PyInt_Type -> PyLong_Type. 00053 */ 00054 #endif /* NPY_PY3K */ 00055 00056 /* Py3 changes PySlice_GetIndicesEx' first argument's type to PyObject* */ 00057 #ifdef NPY_PY3K 00058 # define NpySlice_GetIndicesEx PySlice_GetIndicesEx 00059 #else 00060 # define NpySlice_GetIndicesEx(op, nop, start, end, step, slicelength) \ 00061 PySlice_GetIndicesEx((PySliceObject *)op, nop, start, end, step, slicelength) 00062 #endif 00063 00064 /* 00065 * PyString -> PyBytes 00066 */ 00067 00068 #if defined(NPY_PY3K) 00069 00070 #define PyString_Type PyBytes_Type 00071 #define PyString_Check PyBytes_Check 00072 #define PyStringObject PyBytesObject 00073 #define PyString_FromString PyBytes_FromString 00074 #define PyString_FromStringAndSize PyBytes_FromStringAndSize 00075 #define PyString_AS_STRING PyBytes_AS_STRING 00076 #define PyString_AsStringAndSize PyBytes_AsStringAndSize 00077 #define PyString_FromFormat PyBytes_FromFormat 00078 #define PyString_Concat PyBytes_Concat 00079 #define PyString_ConcatAndDel PyBytes_ConcatAndDel 00080 #define PyString_AsString PyBytes_AsString 00081 #define PyString_GET_SIZE PyBytes_GET_SIZE 00082 #define PyString_Size PyBytes_Size 00083 00084 #define PyUString_Type PyUnicode_Type 00085 #define PyUString_Check PyUnicode_Check 00086 #define PyUStringObject PyUnicodeObject 00087 #define PyUString_FromString PyUnicode_FromString 00088 #define PyUString_FromStringAndSize PyUnicode_FromStringAndSize 00089 #define PyUString_FromFormat PyUnicode_FromFormat 00090 #define PyUString_Concat PyUnicode_Concat2 00091 #define PyUString_ConcatAndDel PyUnicode_ConcatAndDel 00092 #define PyUString_GET_SIZE PyUnicode_GET_SIZE 00093 #define PyUString_Size PyUnicode_Size 00094 #define PyUString_InternFromString PyUnicode_InternFromString 00095 #define PyUString_Format PyUnicode_Format 00096 00097 #else 00098 00099 #define PyBytes_Type PyString_Type 00100 #define PyBytes_Check PyString_Check 00101 #define PyBytesObject PyStringObject 00102 #define PyBytes_FromString PyString_FromString 00103 #define PyBytes_FromStringAndSize PyString_FromStringAndSize 00104 #define PyBytes_AS_STRING PyString_AS_STRING 00105 #define PyBytes_AsStringAndSize PyString_AsStringAndSize 00106 #define PyBytes_FromFormat PyString_FromFormat 00107 #define PyBytes_Concat PyString_Concat 00108 #define PyBytes_ConcatAndDel PyString_ConcatAndDel 00109 #define PyBytes_AsString PyString_AsString 00110 #define PyBytes_GET_SIZE PyString_GET_SIZE 00111 #define PyBytes_Size PyString_Size 00112 00113 #define PyUString_Type PyString_Type 00114 #define PyUString_Check PyString_Check 00115 #define PyUStringObject PyStringObject 00116 #define PyUString_FromString PyString_FromString 00117 #define PyUString_FromStringAndSize PyString_FromStringAndSize 00118 #define PyUString_FromFormat PyString_FromFormat 00119 #define PyUString_Concat PyString_Concat 00120 #define PyUString_ConcatAndDel PyString_ConcatAndDel 00121 #define PyUString_GET_SIZE PyString_GET_SIZE 00122 #define PyUString_Size PyString_Size 00123 #define PyUString_InternFromString PyString_InternFromString 00124 #define PyUString_Format PyString_Format 00125 00126 #endif /* NPY_PY3K */ 00127 00128 00129 static NPY_INLINE void 00130 PyUnicode_ConcatAndDel(PyObject **left, PyObject *right) 00131 { 00132 PyObject *newobj; 00133 newobj = PyUnicode_Concat(*left, right); 00134 Py_DECREF(*left); 00135 Py_DECREF(right); 00136 *left = newobj; 00137 } 00138 00139 static NPY_INLINE void 00140 PyUnicode_Concat2(PyObject **left, PyObject *right) 00141 { 00142 PyObject *newobj; 00143 newobj = PyUnicode_Concat(*left, right); 00144 Py_DECREF(*left); 00145 *left = newobj; 00146 } 00147 00148 /* 00149 * PyFile_* compatibility 00150 */ 00151 #if defined(NPY_PY3K) 00152 /* 00153 * Get a FILE* handle to the file represented by the Python object 00154 */ 00155 static NPY_INLINE FILE* 00156 npy_PyFile_Dup2(PyObject *file, char *mode, npy_off_t *orig_pos) 00157 { 00158 int fd, fd2, unbuf; 00159 PyObject *ret, *os, *io, *io_raw; 00160 npy_off_t pos; 00161 FILE *handle; 00162 00163 /* Flush first to ensure things end up in the file in the correct order */ 00164 ret = PyObject_CallMethod(file, "flush", ""); 00165 if (ret == NULL) { 00166 return NULL; 00167 } 00168 Py_DECREF(ret); 00169 fd = PyObject_AsFileDescriptor(file); 00170 if (fd == -1) { 00171 return NULL; 00172 } 00173 00174 /* 00175 * The handle needs to be dup'd because we have to call fclose 00176 * at the end 00177 */ 00178 os = PyImport_ImportModule("os"); 00179 if (os == NULL) { 00180 return NULL; 00181 } 00182 ret = PyObject_CallMethod(os, "dup", "i", fd); 00183 Py_DECREF(os); 00184 if (ret == NULL) { 00185 return NULL; 00186 } 00187 fd2 = PyNumber_AsSsize_t(ret, NULL); 00188 Py_DECREF(ret); 00189 00190 /* Convert to FILE* handle */ 00191 #ifdef _WIN32 00192 handle = _fdopen(fd2, mode); 00193 #else 00194 handle = fdopen(fd2, mode); 00195 #endif 00196 if (handle == NULL) { 00197 PyErr_SetString(PyExc_IOError, 00198 "Getting a FILE* from a Python file object failed"); 00199 } 00200 00201 /* Record the original raw file handle position */ 00202 *orig_pos = npy_ftell(handle); 00203 if (*orig_pos == -1) { 00204 /* The io module is needed to determine if buffering is used */ 00205 io = PyImport_ImportModule("io"); 00206 if (io == NULL) { 00207 fclose(handle); 00208 return NULL; 00209 } 00210 /* File object instances of RawIOBase are unbuffered */ 00211 io_raw = PyObject_GetAttrString(io, "RawIOBase"); 00212 Py_DECREF(io); 00213 if (io_raw == NULL) { 00214 fclose(handle); 00215 return NULL; 00216 } 00217 unbuf = PyObject_IsInstance(file, io_raw); 00218 Py_DECREF(io_raw); 00219 if (unbuf == 1) { 00220 /* Succeed if the IO is unbuffered */ 00221 return handle; 00222 } 00223 else { 00224 PyErr_SetString(PyExc_IOError, "obtaining file position failed"); 00225 fclose(handle); 00226 return NULL; 00227 } 00228 } 00229 00230 /* Seek raw handle to the Python-side position */ 00231 ret = PyObject_CallMethod(file, "tell", ""); 00232 if (ret == NULL) { 00233 fclose(handle); 00234 return NULL; 00235 } 00236 pos = PyLong_AsLongLong(ret); 00237 Py_DECREF(ret); 00238 if (PyErr_Occurred()) { 00239 fclose(handle); 00240 return NULL; 00241 } 00242 if (npy_fseek(handle, pos, SEEK_SET) == -1) { 00243 PyErr_SetString(PyExc_IOError, "seeking file failed"); 00244 fclose(handle); 00245 return NULL; 00246 } 00247 return handle; 00248 } 00249 00250 /* 00251 * Close the dup-ed file handle, and seek the Python one to the current position 00252 */ 00253 static NPY_INLINE int 00254 npy_PyFile_DupClose2(PyObject *file, FILE* handle, npy_off_t orig_pos) 00255 { 00256 int fd, unbuf; 00257 PyObject *ret, *io, *io_raw; 00258 npy_off_t position; 00259 00260 position = npy_ftell(handle); 00261 00262 /* Close the FILE* handle */ 00263 fclose(handle); 00264 00265 /* 00266 * Restore original file handle position, in order to not confuse 00267 * Python-side data structures 00268 */ 00269 fd = PyObject_AsFileDescriptor(file); 00270 if (fd == -1) { 00271 return -1; 00272 } 00273 00274 if (npy_lseek(fd, orig_pos, SEEK_SET) == -1) { 00275 00276 /* The io module is needed to determine if buffering is used */ 00277 io = PyImport_ImportModule("io"); 00278 if (io == NULL) { 00279 return -1; 00280 } 00281 /* File object instances of RawIOBase are unbuffered */ 00282 io_raw = PyObject_GetAttrString(io, "RawIOBase"); 00283 Py_DECREF(io); 00284 if (io_raw == NULL) { 00285 return -1; 00286 } 00287 unbuf = PyObject_IsInstance(file, io_raw); 00288 Py_DECREF(io_raw); 00289 if (unbuf == 1) { 00290 /* Succeed if the IO is unbuffered */ 00291 return 0; 00292 } 00293 else { 00294 PyErr_SetString(PyExc_IOError, "seeking file failed"); 00295 return -1; 00296 } 00297 } 00298 00299 if (position == -1) { 00300 PyErr_SetString(PyExc_IOError, "obtaining file position failed"); 00301 return -1; 00302 } 00303 00304 /* Seek Python-side handle to the FILE* handle position */ 00305 ret = PyObject_CallMethod(file, "seek", NPY_OFF_T_PYFMT "i", position, 0); 00306 if (ret == NULL) { 00307 return -1; 00308 } 00309 Py_DECREF(ret); 00310 return 0; 00311 } 00312 00313 static NPY_INLINE int 00314 npy_PyFile_Check(PyObject *file) 00315 { 00316 int fd; 00317 fd = PyObject_AsFileDescriptor(file); 00318 if (fd == -1) { 00319 PyErr_Clear(); 00320 return 0; 00321 } 00322 return 1; 00323 } 00324 00325 #else 00326 00327 static NPY_INLINE FILE * 00328 npy_PyFile_Dup2(PyObject *file, 00329 const char *NPY_UNUSED(mode), npy_off_t *NPY_UNUSED(orig_pos)) 00330 { 00331 FILE * fp = PyFile_AsFile(file); 00332 if (fp == NULL) { 00333 PyErr_SetString(PyExc_IOError, 00334 "first argument must be an open file"); 00335 return NULL; 00336 } 00337 return fp; 00338 } 00339 00340 static NPY_INLINE int 00341 npy_PyFile_DupClose2(PyObject *NPY_UNUSED(file), FILE* NPY_UNUSED(handle), 00342 npy_off_t NPY_UNUSED(orig_pos)) 00343 { 00344 return 0; 00345 } 00346 00347 #define npy_PyFile_Check PyFile_Check 00348 00349 #endif 00350 00351 static NPY_INLINE PyObject* 00352 npy_PyFile_OpenFile(PyObject *filename, const char *mode) 00353 { 00354 PyObject *open; 00355 open = PyDict_GetItemString(PyEval_GetBuiltins(), "open"); 00356 if (open == NULL) { 00357 return NULL; 00358 } 00359 return PyObject_CallFunction(open, "Os", filename, mode); 00360 } 00361 00362 static NPY_INLINE int 00363 npy_PyFile_CloseFile(PyObject *file) 00364 { 00365 PyObject *ret; 00366 00367 ret = PyObject_CallMethod(file, "close", NULL); 00368 if (ret == NULL) { 00369 return -1; 00370 } 00371 Py_DECREF(ret); 00372 return 0; 00373 } 00374 00375 /* 00376 * PyObject_Cmp 00377 */ 00378 #if defined(NPY_PY3K) 00379 static NPY_INLINE int 00380 PyObject_Cmp(PyObject *i1, PyObject *i2, int *cmp) 00381 { 00382 int v; 00383 v = PyObject_RichCompareBool(i1, i2, Py_LT); 00384 if (v == 1) { 00385 *cmp = -1; 00386 return 1; 00387 } 00388 else if (v == -1) { 00389 return -1; 00390 } 00391 00392 v = PyObject_RichCompareBool(i1, i2, Py_GT); 00393 if (v == 1) { 00394 *cmp = 1; 00395 return 1; 00396 } 00397 else if (v == -1) { 00398 return -1; 00399 } 00400 00401 v = PyObject_RichCompareBool(i1, i2, Py_EQ); 00402 if (v == 1) { 00403 *cmp = 0; 00404 return 1; 00405 } 00406 else { 00407 *cmp = 0; 00408 return -1; 00409 } 00410 } 00411 #endif 00412 00413 /* 00414 * PyCObject functions adapted to PyCapsules. 00415 * 00416 * The main job here is to get rid of the improved error handling 00417 * of PyCapsules. It's a shame... 00418 */ 00419 #if PY_VERSION_HEX >= 0x03000000 00420 00421 static NPY_INLINE PyObject * 00422 NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *)) 00423 { 00424 PyObject *ret = PyCapsule_New(ptr, NULL, dtor); 00425 if (ret == NULL) { 00426 PyErr_Clear(); 00427 } 00428 return ret; 00429 } 00430 00431 static NPY_INLINE PyObject * 00432 NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context, void (*dtor)(PyObject *)) 00433 { 00434 PyObject *ret = NpyCapsule_FromVoidPtr(ptr, dtor); 00435 if (ret != NULL && PyCapsule_SetContext(ret, context) != 0) { 00436 PyErr_Clear(); 00437 Py_DECREF(ret); 00438 ret = NULL; 00439 } 00440 return ret; 00441 } 00442 00443 static NPY_INLINE void * 00444 NpyCapsule_AsVoidPtr(PyObject *obj) 00445 { 00446 void *ret = PyCapsule_GetPointer(obj, NULL); 00447 if (ret == NULL) { 00448 PyErr_Clear(); 00449 } 00450 return ret; 00451 } 00452 00453 static NPY_INLINE void * 00454 NpyCapsule_GetDesc(PyObject *obj) 00455 { 00456 return PyCapsule_GetContext(obj); 00457 } 00458 00459 static NPY_INLINE int 00460 NpyCapsule_Check(PyObject *ptr) 00461 { 00462 return PyCapsule_CheckExact(ptr); 00463 } 00464 00465 #else 00466 00467 static NPY_INLINE PyObject * 00468 NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(void *)) 00469 { 00470 return PyCObject_FromVoidPtr(ptr, dtor); 00471 } 00472 00473 static NPY_INLINE PyObject * 00474 NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context, 00475 void (*dtor)(void *, void *)) 00476 { 00477 return PyCObject_FromVoidPtrAndDesc(ptr, context, dtor); 00478 } 00479 00480 static NPY_INLINE void * 00481 NpyCapsule_AsVoidPtr(PyObject *ptr) 00482 { 00483 return PyCObject_AsVoidPtr(ptr); 00484 } 00485 00486 static NPY_INLINE void * 00487 NpyCapsule_GetDesc(PyObject *obj) 00488 { 00489 return PyCObject_GetDesc(obj); 00490 } 00491 00492 static NPY_INLINE int 00493 NpyCapsule_Check(PyObject *ptr) 00494 { 00495 return PyCObject_Check(ptr); 00496 } 00497 00498 #endif 00499 00500 #ifdef __cplusplus 00501 } 00502 #endif 00503 00504 #endif /* _NPY_3KCOMPAT_H_ */