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
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 /*
00142  * Accessing items of ob_base
00143  */
00144 
00145 #if (PY_VERSION_HEX < 0x02060000)
00146 #define Py_TYPE(o)    (((PyObject*)(o))->ob_type)
00147 #define Py_REFCNT(o)  (((PyObject*)(o))->ob_refcnt)
00148 #define Py_SIZE(o)    (((PyVarObject*)(o))->ob_size)
00149 #endif
00150 
00151 /*
00152  * PyFile_* compatibility
00153  */
00154 #if defined(NPY_PY3K)
00155 
00156 /*
00157  * Get a FILE* handle to the file represented by the Python object
00158  */
00159 static NPY_INLINE FILE*
00160 npy_PyFile_Dup(PyObject *file, char *mode)
00161 {
00162     int fd, fd2;
00163     PyObject *ret, *os;
00164     Py_ssize_t pos;
00165     FILE *handle;
00166     /* Flush first to ensure things end up in the file in the correct order */
00167     ret = PyObject_CallMethod(file, "flush", "");
00168     if (ret == NULL) {
00169         return NULL;
00170     }
00171     Py_DECREF(ret);
00172     fd = PyObject_AsFileDescriptor(file);
00173     if (fd == -1) {
00174         return NULL;
00175     }
00176     os = PyImport_ImportModule("os");
00177     if (os == NULL) {
00178         return NULL;
00179     }
00180     ret = PyObject_CallMethod(os, "dup", "i", fd);
00181     Py_DECREF(os);
00182     if (ret == NULL) {
00183         return NULL;
00184     }
00185     fd2 = PyNumber_AsSsize_t(ret, NULL);
00186     Py_DECREF(ret);
00187 #ifdef _WIN32
00188     handle = _fdopen(fd2, mode);
00189 #else
00190     handle = fdopen(fd2, mode);
00191 #endif
00192     if (handle == NULL) {
00193         PyErr_SetString(PyExc_IOError,
00194                         "Getting a FILE* from a Python file object failed");
00195     }
00196     ret = PyObject_CallMethod(file, "tell", "");
00197     if (ret == NULL) {
00198         fclose(handle);
00199         return NULL;
00200     }
00201     pos = PyNumber_AsSsize_t(ret, PyExc_OverflowError);
00202     Py_DECREF(ret);
00203     if (PyErr_Occurred()) {
00204         fclose(handle);
00205         return NULL;
00206     }
00207     fseek(handle, pos, SEEK_SET);
00208     return handle;
00209 }
00210 
00211 /*
00212  * Close the dup-ed file handle, and seek the Python one to the current position
00213  */
00214 static NPY_INLINE int
00215 npy_PyFile_DupClose(PyObject *file, FILE* handle)
00216 {
00217     PyObject *ret;
00218     long position;
00219     position = ftell(handle);
00220     fclose(handle);
00221 
00222     ret = PyObject_CallMethod(file, "seek", "li", position, 0);
00223     if (ret == NULL) {
00224         return -1;
00225     }
00226     Py_DECREF(ret);
00227     return 0;
00228 }
00229 
00230 static NPY_INLINE int
00231 npy_PyFile_Check(PyObject *file)
00232 {
00233     int fd;
00234     fd = PyObject_AsFileDescriptor(file);
00235     if (fd == -1) {
00236         PyErr_Clear();
00237         return 0;
00238     }
00239     return 1;
00240 }
00241 
00242 #else
00243 
00244 #define npy_PyFile_Dup(file, mode) PyFile_AsFile(file)
00245 #define npy_PyFile_DupClose(file, handle) (0)
00246 #define npy_PyFile_Check PyFile_Check
00247 
00248 #endif
00249 
00250 static NPY_INLINE PyObject*
00251 npy_PyFile_OpenFile(PyObject *filename, char *mode)
00252 {
00253     PyObject *open;
00254     open = PyDict_GetItemString(PyEval_GetBuiltins(), "open");
00255     if (open == NULL) {
00256         return NULL;
00257     }
00258     return PyObject_CallFunction(open, "Os", filename, mode);
00259 }
00260 
00261 /*
00262  * PyObject_Cmp
00263  */
00264 #if defined(NPY_PY3K)
00265 static NPY_INLINE int
00266 PyObject_Cmp(PyObject *i1, PyObject *i2, int *cmp)
00267 {
00268     int v;
00269     v = PyObject_RichCompareBool(i1, i2, Py_LT);
00270     if (v == 0) {
00271         *cmp = -1;
00272         return 1;
00273     }
00274     else if (v == -1) {
00275         return -1;
00276     }
00277 
00278     v = PyObject_RichCompareBool(i1, i2, Py_GT);
00279     if (v == 0) {
00280         *cmp = 1;
00281         return 1;
00282     }
00283     else if (v == -1) {
00284         return -1;
00285     }
00286 
00287     v = PyObject_RichCompareBool(i1, i2, Py_EQ);
00288     if (v == 0) {
00289         *cmp = 0;
00290         return 1;
00291     }
00292     else {
00293         *cmp = 0;
00294         return -1;
00295     }
00296 }
00297 #endif
00298 
00299 /*
00300  * PyCObject functions adapted to PyCapsules.
00301  *
00302  * The main job here is to get rid of the improved error handling
00303  * of PyCapsules. It's a shame...
00304  */
00305 #if PY_VERSION_HEX >= 0x03000000
00306 
00307 static NPY_INLINE PyObject *
00308 NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *))
00309 {
00310     PyObject *ret = PyCapsule_New(ptr, NULL, dtor);
00311     if (ret == NULL) {
00312         PyErr_Clear();
00313     }
00314     return ret;
00315 }
00316 
00317 static NPY_INLINE PyObject *
00318 NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context, void (*dtor)(PyObject *))
00319 {
00320     PyObject *ret = NpyCapsule_FromVoidPtr(ptr, dtor);
00321     if (ret != NULL && PyCapsule_SetContext(ret, context) != 0) {
00322         PyErr_Clear();
00323         Py_DECREF(ret);
00324         ret = NULL;
00325     }
00326     return ret;
00327 }
00328 
00329 static NPY_INLINE void *
00330 NpyCapsule_AsVoidPtr(PyObject *obj)
00331 {
00332     void *ret = PyCapsule_GetPointer(obj, NULL);
00333     if (ret == NULL) {
00334         PyErr_Clear();
00335     }
00336     return ret;
00337 }
00338 
00339 static NPY_INLINE void *
00340 NpyCapsule_GetDesc(PyObject *obj)
00341 {
00342     return PyCapsule_GetContext(obj);
00343 }
00344 
00345 static NPY_INLINE int
00346 NpyCapsule_Check(PyObject *ptr)
00347 {
00348     return PyCapsule_CheckExact(ptr);
00349 }
00350 
00351 static void
00352 simple_capsule_dtor(PyObject *cap)
00353 {
00354     PyArray_free(PyCapsule_GetPointer(cap, NULL));
00355 }
00356 
00357 #else
00358 
00359 static NPY_INLINE PyObject *
00360 NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(void *))
00361 {
00362     return PyCObject_FromVoidPtr(ptr, dtor);
00363 }
00364 
00365 static NPY_INLINE PyObject *
00366 NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context,
00367         void (*dtor)(void *, void *))
00368 {
00369     return PyCObject_FromVoidPtrAndDesc(ptr, context, dtor);
00370 }
00371 
00372 static NPY_INLINE void *
00373 NpyCapsule_AsVoidPtr(PyObject *ptr)
00374 {
00375     return PyCObject_AsVoidPtr(ptr);
00376 }
00377 
00378 static NPY_INLINE void *
00379 NpyCapsule_GetDesc(PyObject *obj)
00380 {
00381     return PyCObject_GetDesc(obj);
00382 }
00383 
00384 static NPY_INLINE int
00385 NpyCapsule_Check(PyObject *ptr)
00386 {
00387     return PyCObject_Check(ptr);
00388 }
00389 
00390 static void
00391 simple_capsule_dtor(void *ptr)
00392 {
00393     PyArray_free(ptr);
00394 }
00395 
00396 #endif
00397 
00398 #ifdef __cplusplus
00399 }
00400 #endif
00401 
00402 #endif /* _NPY_3KCOMPAT_H_ */