numpy  2.0.0
include/numpy/npy_3kcompat.h
Go to the documentation of this file.
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 /*
00057  * PyString -> PyBytes
00058  */
00059 
00060 #if defined(NPY_PY3K)
00061 
00062 #define PyString_Type PyBytes_Type
00063 #define PyString_Check PyBytes_Check
00064 #define PyStringObject PyBytesObject
00065 #define PyString_FromString PyBytes_FromString
00066 #define PyString_FromStringAndSize PyBytes_FromStringAndSize
00067 #define PyString_AS_STRING PyBytes_AS_STRING
00068 #define PyString_AsStringAndSize PyBytes_AsStringAndSize
00069 #define PyString_FromFormat PyBytes_FromFormat
00070 #define PyString_Concat PyBytes_Concat
00071 #define PyString_ConcatAndDel PyBytes_ConcatAndDel
00072 #define PyString_AsString PyBytes_AsString
00073 #define PyString_GET_SIZE PyBytes_GET_SIZE
00074 #define PyString_Size PyBytes_Size
00075 
00076 #define PyUString_Type PyUnicode_Type
00077 #define PyUString_Check PyUnicode_Check
00078 #define PyUStringObject PyUnicodeObject
00079 #define PyUString_FromString PyUnicode_FromString
00080 #define PyUString_FromStringAndSize PyUnicode_FromStringAndSize
00081 #define PyUString_FromFormat PyUnicode_FromFormat
00082 #define PyUString_Concat PyUnicode_Concat2
00083 #define PyUString_ConcatAndDel PyUnicode_ConcatAndDel
00084 #define PyUString_GET_SIZE PyUnicode_GET_SIZE
00085 #define PyUString_Size PyUnicode_Size
00086 #define PyUString_InternFromString PyUnicode_InternFromString
00087 #define PyUString_Format PyUnicode_Format
00088 
00089 #else
00090 
00091 #define PyBytes_Type PyString_Type
00092 #define PyBytes_Check PyString_Check
00093 #define PyBytesObject PyStringObject
00094 #define PyBytes_FromString PyString_FromString
00095 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
00096 #define PyBytes_AS_STRING PyString_AS_STRING
00097 #define PyBytes_AsStringAndSize PyString_AsStringAndSize
00098 #define PyBytes_FromFormat PyString_FromFormat
00099 #define PyBytes_Concat PyString_Concat
00100 #define PyBytes_ConcatAndDel PyString_ConcatAndDel
00101 #define PyBytes_AsString PyString_AsString
00102 #define PyBytes_GET_SIZE PyString_GET_SIZE
00103 #define PyBytes_Size PyString_Size
00104 
00105 #define PyUString_Type PyString_Type
00106 #define PyUString_Check PyString_Check
00107 #define PyUStringObject PyStringObject
00108 #define PyUString_FromString PyString_FromString
00109 #define PyUString_FromStringAndSize PyString_FromStringAndSize
00110 #define PyUString_FromFormat PyString_FromFormat
00111 #define PyUString_Concat PyString_Concat
00112 #define PyUString_ConcatAndDel PyString_ConcatAndDel
00113 #define PyUString_GET_SIZE PyString_GET_SIZE
00114 #define PyUString_Size PyString_Size
00115 #define PyUString_InternFromString PyString_InternFromString
00116 #define PyUString_Format PyString_Format
00117 
00118 #endif /* NPY_PY3K */
00119 
00120 
00121 static NPY_INLINE void
00122 PyUnicode_ConcatAndDel(PyObject **left, PyObject *right)
00123 {
00124     PyObject *newobj;
00125     newobj = PyUnicode_Concat(*left, right);
00126     Py_DECREF(*left);
00127     Py_DECREF(right);
00128     *left = newobj;
00129 }
00130 
00131 static NPY_INLINE void
00132 PyUnicode_Concat2(PyObject **left, PyObject *right)
00133 {
00134     PyObject *newobj;
00135     newobj = PyUnicode_Concat(*left, right);
00136     Py_DECREF(*left);
00137     *left = newobj;
00138 }
00139 
00140 /*
00141  * PyFile_* compatibility
00142  */
00143 #if defined(NPY_PY3K)
00144 
00145 /*
00146  * Get a FILE* handle to the file represented by the Python object
00147  */
00148 static NPY_INLINE FILE*
00149 npy_PyFile_Dup(PyObject *file, char *mode)
00150 {
00151     int fd, fd2;
00152     PyObject *ret, *os;
00153     Py_ssize_t pos;
00154     FILE *handle;
00155     /* Flush first to ensure things end up in the file in the correct order */
00156     ret = PyObject_CallMethod(file, "flush", "");
00157     if (ret == NULL) {
00158         return NULL;
00159     }
00160     Py_DECREF(ret);
00161     fd = PyObject_AsFileDescriptor(file);
00162     if (fd == -1) {
00163         return NULL;
00164     }
00165     os = PyImport_ImportModule("os");
00166     if (os == NULL) {
00167         return NULL;
00168     }
00169     ret = PyObject_CallMethod(os, "dup", "i", fd);
00170     Py_DECREF(os);
00171     if (ret == NULL) {
00172         return NULL;
00173     }
00174     fd2 = PyNumber_AsSsize_t(ret, NULL);
00175     Py_DECREF(ret);
00176 #ifdef _WIN32
00177     handle = _fdopen(fd2, mode);
00178 #else
00179     handle = fdopen(fd2, mode);
00180 #endif
00181     if (handle == NULL) {
00182         PyErr_SetString(PyExc_IOError,
00183                         "Getting a FILE* from a Python file object failed");
00184     }
00185     ret = PyObject_CallMethod(file, "tell", "");
00186     if (ret == NULL) {
00187         fclose(handle);
00188         return NULL;
00189     }
00190     pos = PyNumber_AsSsize_t(ret, PyExc_OverflowError);
00191     Py_DECREF(ret);
00192     if (PyErr_Occurred()) {
00193         fclose(handle);
00194         return NULL;
00195     }
00196     npy_fseek(handle, pos, SEEK_SET);
00197     return handle;
00198 }
00199 
00200 /*
00201  * Close the dup-ed file handle, and seek the Python one to the current position
00202  */
00203 static NPY_INLINE int
00204 npy_PyFile_DupClose(PyObject *file, FILE* handle)
00205 {
00206     PyObject *ret;
00207     Py_ssize_t position;
00208     position = npy_ftell(handle);
00209     fclose(handle);
00210 
00211     ret = PyObject_CallMethod(file, "seek", NPY_SSIZE_T_PYFMT "i", position, 0);
00212     if (ret == NULL) {
00213         return -1;
00214     }
00215     Py_DECREF(ret);
00216     return 0;
00217 }
00218 
00219 static NPY_INLINE int
00220 npy_PyFile_Check(PyObject *file)
00221 {
00222     int fd;
00223     fd = PyObject_AsFileDescriptor(file);
00224     if (fd == -1) {
00225         PyErr_Clear();
00226         return 0;
00227     }
00228     return 1;
00229 }
00230 
00231 #else
00232 
00233 #define npy_PyFile_Dup(file, mode) PyFile_AsFile(file)
00234 #define npy_PyFile_DupClose(file, handle) (0)
00235 #define npy_PyFile_Check PyFile_Check
00236 
00237 #endif
00238 
00239 static NPY_INLINE PyObject*
00240 npy_PyFile_OpenFile(PyObject *filename, const char *mode)
00241 {
00242     PyObject *open;
00243     open = PyDict_GetItemString(PyEval_GetBuiltins(), "open");
00244     if (open == NULL) {
00245         return NULL;
00246     }
00247     return PyObject_CallFunction(open, "Os", filename, mode);
00248 }
00249 
00250 static NPY_INLINE int
00251 npy_PyFile_CloseFile(PyObject *file)
00252 {
00253     PyObject *ret;
00254 
00255     ret = PyObject_CallMethod(file, "close", NULL);
00256     if (ret == NULL) {
00257         return -1;
00258     }
00259     Py_DECREF(ret);
00260     return 0;
00261 }
00262 
00263 /*
00264  * PyObject_Cmp
00265  */
00266 #if defined(NPY_PY3K)
00267 static NPY_INLINE int
00268 PyObject_Cmp(PyObject *i1, PyObject *i2, int *cmp)
00269 {
00270     int v;
00271     v = PyObject_RichCompareBool(i1, i2, Py_LT);
00272     if (v == 0) {
00273         *cmp = -1;
00274         return 1;
00275     }
00276     else if (v == -1) {
00277         return -1;
00278     }
00279 
00280     v = PyObject_RichCompareBool(i1, i2, Py_GT);
00281     if (v == 0) {
00282         *cmp = 1;
00283         return 1;
00284     }
00285     else if (v == -1) {
00286         return -1;
00287     }
00288 
00289     v = PyObject_RichCompareBool(i1, i2, Py_EQ);
00290     if (v == 0) {
00291         *cmp = 0;
00292         return 1;
00293     }
00294     else {
00295         *cmp = 0;
00296         return -1;
00297     }
00298 }
00299 #endif
00300 
00301 /*
00302  * PyCObject functions adapted to PyCapsules.
00303  *
00304  * The main job here is to get rid of the improved error handling
00305  * of PyCapsules. It's a shame...
00306  */
00307 #if PY_VERSION_HEX >= 0x03000000
00308 
00309 static NPY_INLINE PyObject *
00310 NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *))
00311 {
00312     PyObject *ret = PyCapsule_New(ptr, NULL, dtor);
00313     if (ret == NULL) {
00314         PyErr_Clear();
00315     }
00316     return ret;
00317 }
00318 
00319 static NPY_INLINE PyObject *
00320 NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context, void (*dtor)(PyObject *))
00321 {
00322     PyObject *ret = NpyCapsule_FromVoidPtr(ptr, dtor);
00323     if (ret != NULL && PyCapsule_SetContext(ret, context) != 0) {
00324         PyErr_Clear();
00325         Py_DECREF(ret);
00326         ret = NULL;
00327     }
00328     return ret;
00329 }
00330 
00331 static NPY_INLINE void *
00332 NpyCapsule_AsVoidPtr(PyObject *obj)
00333 {
00334     void *ret = PyCapsule_GetPointer(obj, NULL);
00335     if (ret == NULL) {
00336         PyErr_Clear();
00337     }
00338     return ret;
00339 }
00340 
00341 static NPY_INLINE void *
00342 NpyCapsule_GetDesc(PyObject *obj)
00343 {
00344     return PyCapsule_GetContext(obj);
00345 }
00346 
00347 static NPY_INLINE int
00348 NpyCapsule_Check(PyObject *ptr)
00349 {
00350     return PyCapsule_CheckExact(ptr);
00351 }
00352 
00353 static NPY_INLINE void
00354 simple_capsule_dtor(PyObject *cap)
00355 {
00356     PyArray_free(PyCapsule_GetPointer(cap, NULL));
00357 }
00358 
00359 #else
00360 
00361 static NPY_INLINE PyObject *
00362 NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(void *))
00363 {
00364     return PyCObject_FromVoidPtr(ptr, dtor);
00365 }
00366 
00367 static NPY_INLINE PyObject *
00368 NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context,
00369         void (*dtor)(void *, void *))
00370 {
00371     return PyCObject_FromVoidPtrAndDesc(ptr, context, dtor);
00372 }
00373 
00374 static NPY_INLINE void *
00375 NpyCapsule_AsVoidPtr(PyObject *ptr)
00376 {
00377     return PyCObject_AsVoidPtr(ptr);
00378 }
00379 
00380 static NPY_INLINE void *
00381 NpyCapsule_GetDesc(PyObject *obj)
00382 {
00383     return PyCObject_GetDesc(obj);
00384 }
00385 
00386 static NPY_INLINE int
00387 NpyCapsule_Check(PyObject *ptr)
00388 {
00389     return PyCObject_Check(ptr);
00390 }
00391 
00392 static NPY_INLINE void
00393 simple_capsule_dtor(void *ptr)
00394 {
00395     PyArray_free(ptr);
00396 }
00397 
00398 #endif
00399 
00400 #ifdef __cplusplus
00401 }
00402 #endif
00403 
00404 #endif /* _NPY_3KCOMPAT_H_ */