| File: | numpy/core/src/multiarray/descriptor.c |
| Warning: | line 527, column 14 Calling function 'PyDict_GetItemWithError' with a PyObject argument whose ownership has been released (with stolen reference) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* Array Descr Object */ | |||
| 2 | ||||
| 3 | #define PY_SSIZE_T_CLEAN | |||
| 4 | #include <Python.h> | |||
| 5 | #include "structmember.h" | |||
| 6 | ||||
| 7 | #define NPY_NO_DEPRECATED_API0x0000000E NPY_API_VERSION0x0000000E | |||
| 8 | #define _MULTIARRAYMODULE | |||
| 9 | #include "numpy/arrayobject.h" | |||
| 10 | ||||
| 11 | #include "npy_config.h" | |||
| 12 | #include "npy_pycompat.h" | |||
| 13 | #include "npy_import.h" | |||
| 14 | ||||
| 15 | #include "common.h" | |||
| 16 | #include "conversion_utils.h" | |||
| 17 | #include "ctors.h" | |||
| 18 | #include "scalartypes.h" | |||
| 19 | #include "descriptor.h" | |||
| 20 | #include "getset.h" | |||
| 21 | #include "arrayobject.h" | |||
| 22 | #include "mem_overlap.h" | |||
| 23 | #include "alloc.h" | |||
| 24 | #include "npy_buffer.h" | |||
| 25 | ||||
| 26 | /******************* array attribute get and set routines ******************/ | |||
| 27 | ||||
| 28 | static PyObject * | |||
| 29 | array_ndim_get(PyArrayObject *self) | |||
| 30 | { | |||
| 31 | return PyLong_FromLong(PyArray_NDIM(self)); | |||
| 32 | } | |||
| 33 | ||||
| 34 | static PyObject * | |||
| 35 | array_flags_get(PyArrayObject *self) | |||
| 36 | { | |||
| 37 | return PyArray_NewFlagsObject((PyObject *)self); | |||
| 38 | } | |||
| 39 | ||||
| 40 | static PyObject * | |||
| 41 | array_shape_get(PyArrayObject *self) | |||
| 42 | { | |||
| 43 | return PyArray_IntTupleFromIntp(PyArray_NDIM(self), PyArray_DIMS(self)); | |||
| 44 | } | |||
| 45 | ||||
| 46 | ||||
| 47 | static int | |||
| 48 | array_shape_set(PyArrayObject *self, PyObject *val) | |||
| 49 | { | |||
| 50 | int nd; | |||
| 51 | PyArrayObject *ret; | |||
| 52 | ||||
| 53 | if (val == NULL((void*)0)) { | |||
| 54 | PyErr_SetString(PyExc_AttributeError, | |||
| 55 | "Cannot delete array shape"); | |||
| 56 | return -1; | |||
| 57 | } | |||
| 58 | /* Assumes C-order */ | |||
| 59 | ret = (PyArrayObject *)PyArray_Reshape(self, val); | |||
| 60 | if (ret == NULL((void*)0)) { | |||
| 61 | return -1; | |||
| 62 | } | |||
| 63 | if (PyArray_DATA(ret) != PyArray_DATA(self)) { | |||
| 64 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 65 | PyErr_SetString(PyExc_AttributeError, | |||
| 66 | "Incompatible shape for in-place modification. Use " | |||
| 67 | "`.reshape()` to make a copy with the desired shape."); | |||
| 68 | return -1; | |||
| 69 | } | |||
| 70 | ||||
| 71 | nd = PyArray_NDIM(ret); | |||
| 72 | if (nd > 0) { | |||
| 73 | /* create new dimensions and strides */ | |||
| 74 | npy_intp *_dimensions = npy_alloc_cache_dim(2 * nd); | |||
| 75 | if (_dimensions == NULL((void*)0)) { | |||
| 76 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 77 | PyErr_NoMemory(); | |||
| 78 | return -1; | |||
| 79 | } | |||
| 80 | /* Free old dimensions and strides */ | |||
| 81 | npy_free_cache_dim_array(self); | |||
| 82 | ((PyArrayObject_fields *)self)->nd = nd; | |||
| 83 | ((PyArrayObject_fields *)self)->dimensions = _dimensions; | |||
| 84 | ((PyArrayObject_fields *)self)->strides = _dimensions + nd; | |||
| 85 | ||||
| 86 | if (nd) { | |||
| 87 | memcpy(PyArray_DIMS(self), PyArray_DIMS(ret), nd*sizeof(npy_intp)); | |||
| 88 | memcpy(PyArray_STRIDES(self), PyArray_STRIDES(ret), nd*sizeof(npy_intp)); | |||
| 89 | } | |||
| 90 | } | |||
| 91 | else { | |||
| 92 | /* Free old dimensions and strides */ | |||
| 93 | npy_free_cache_dim_array(self); | |||
| 94 | ((PyArrayObject_fields *)self)->nd = 0; | |||
| 95 | ((PyArrayObject_fields *)self)->dimensions = NULL((void*)0); | |||
| 96 | ((PyArrayObject_fields *)self)->strides = NULL((void*)0); | |||
| 97 | } | |||
| 98 | ||||
| 99 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 100 | PyArray_UpdateFlags(self, NPY_ARRAY_C_CONTIGUOUS0x0001 | NPY_ARRAY_F_CONTIGUOUS0x0002); | |||
| 101 | return 0; | |||
| 102 | } | |||
| 103 | ||||
| 104 | ||||
| 105 | static PyObject * | |||
| 106 | array_strides_get(PyArrayObject *self) | |||
| 107 | { | |||
| 108 | return PyArray_IntTupleFromIntp(PyArray_NDIM(self), PyArray_STRIDES(self)); | |||
| 109 | } | |||
| 110 | ||||
| 111 | static int | |||
| 112 | array_strides_set(PyArrayObject *self, PyObject *obj) | |||
| 113 | { | |||
| 114 | PyArray_Dims newstrides = {NULL((void*)0), -1}; | |||
| 115 | PyArrayObject *new; | |||
| 116 | npy_intp numbytes = 0; | |||
| 117 | npy_intp offset = 0; | |||
| 118 | npy_intp lower_offset = 0; | |||
| 119 | npy_intp upper_offset = 0; | |||
| 120 | Py_buffer view; | |||
| 121 | ||||
| 122 | if (obj == NULL((void*)0)) { | |||
| 123 | PyErr_SetString(PyExc_AttributeError, | |||
| 124 | "Cannot delete array strides"); | |||
| 125 | return -1; | |||
| 126 | } | |||
| 127 | if (!PyArray_OptionalIntpConverter(obj, &newstrides) || | |||
| 128 | newstrides.len == -1) { | |||
| 129 | PyErr_SetString(PyExc_TypeError, "invalid strides"); | |||
| 130 | return -1; | |||
| 131 | } | |||
| 132 | if (newstrides.len != PyArray_NDIM(self)) { | |||
| 133 | PyErr_Format(PyExc_ValueError, "strides must be " \ | |||
| 134 | " same length as shape (%d)", PyArray_NDIM(self)); | |||
| 135 | goto fail; | |||
| 136 | } | |||
| 137 | new = self; | |||
| 138 | while(PyArray_BASE(new) && PyArray_Check(PyArray_BASE(new))((((PyObject*)(PyArray_BASE(new)))->ob_type) == (&PyArray_Type ) || PyType_IsSubtype((((PyObject*)(PyArray_BASE(new)))->ob_type ), (&PyArray_Type)))) { | |||
| 139 | new = (PyArrayObject *)(PyArray_BASE(new)); | |||
| 140 | } | |||
| 141 | /* | |||
| 142 | * Get the available memory through the buffer interface on | |||
| 143 | * PyArray_BASE(new) or if that fails from the current new | |||
| 144 | */ | |||
| 145 | if (PyArray_BASE(new) && | |||
| 146 | PyObject_GetBuffer(PyArray_BASE(new), &view, PyBUF_SIMPLE0) >= 0) { | |||
| 147 | offset = PyArray_BYTES(self) - (char *)view.buf; | |||
| 148 | numbytes = view.len + offset; | |||
| 149 | PyBuffer_Release(&view); | |||
| 150 | } | |||
| 151 | else { | |||
| 152 | PyErr_Clear(); | |||
| 153 | offset_bounds_from_strides(PyArray_ITEMSIZE(new), PyArray_NDIM(new), | |||
| 154 | PyArray_DIMS(new), PyArray_STRIDES(new), | |||
| 155 | &lower_offset, &upper_offset); | |||
| 156 | ||||
| 157 | offset = PyArray_BYTES(self) - (PyArray_BYTES(new) + lower_offset); | |||
| 158 | numbytes = upper_offset - lower_offset; | |||
| 159 | } | |||
| 160 | ||||
| 161 | /* numbytes == 0 is special here, but the 0-size array case always works */ | |||
| 162 | if (!PyArray_CheckStrides(PyArray_ITEMSIZE(self), PyArray_NDIM(self), | |||
| 163 | numbytes, offset, | |||
| 164 | PyArray_DIMS(self), newstrides.ptr)) { | |||
| 165 | PyErr_SetString(PyExc_ValueError, "strides is not "\ | |||
| 166 | "compatible with available memory"); | |||
| 167 | goto fail; | |||
| 168 | } | |||
| 169 | if (newstrides.len) { | |||
| 170 | memcpy(PyArray_STRIDES(self), newstrides.ptr, sizeof(npy_intp)*newstrides.len); | |||
| 171 | } | |||
| 172 | PyArray_UpdateFlags(self, NPY_ARRAY_C_CONTIGUOUS0x0001 | NPY_ARRAY_F_CONTIGUOUS0x0002 | | |||
| 173 | NPY_ARRAY_ALIGNED0x0100); | |||
| 174 | npy_free_cache_dim_obj(newstrides); | |||
| 175 | return 0; | |||
| 176 | ||||
| 177 | fail: | |||
| 178 | npy_free_cache_dim_obj(newstrides); | |||
| 179 | return -1; | |||
| 180 | } | |||
| 181 | ||||
| 182 | ||||
| 183 | ||||
| 184 | static PyObject * | |||
| 185 | array_priority_get(PyArrayObject *NPY_UNUSED(self)(__NPY_UNUSED_TAGGEDself) __attribute__ ((__unused__))) | |||
| 186 | { | |||
| 187 | return PyFloat_FromDouble(NPY_PRIORITY0.0); | |||
| 188 | } | |||
| 189 | ||||
| 190 | static PyObject * | |||
| 191 | array_typestr_get(PyArrayObject *self) | |||
| 192 | { | |||
| 193 | return arraydescr_protocol_typestr_get(PyArray_DESCR(self)); | |||
| 194 | } | |||
| 195 | ||||
| 196 | static PyObject * | |||
| 197 | array_descr_get(PyArrayObject *self) | |||
| 198 | { | |||
| 199 | Py_INCREF(PyArray_DESCR(self))_Py_INCREF(((PyObject*)(PyArray_DESCR(self)))); | |||
| 200 | return (PyObject *)PyArray_DESCR(self); | |||
| 201 | } | |||
| 202 | ||||
| 203 | static PyObject * | |||
| 204 | array_protocol_descr_get(PyArrayObject *self) | |||
| 205 | { | |||
| 206 | PyObject *res; | |||
| 207 | PyObject *dobj; | |||
| 208 | ||||
| 209 | res = arraydescr_protocol_descr_get(PyArray_DESCR(self)); | |||
| 210 | if (res) { | |||
| 211 | return res; | |||
| 212 | } | |||
| 213 | PyErr_Clear(); | |||
| 214 | ||||
| 215 | /* get default */ | |||
| 216 | dobj = PyTuple_New(2); | |||
| 217 | if (dobj == NULL((void*)0)) { | |||
| 218 | return NULL((void*)0); | |||
| 219 | } | |||
| 220 | PyTuple_SET_ITEM(dobj, 0, PyUnicode_FromString(""))PyTuple_SetItem(dobj, 0, PyUnicode_FromString("")); | |||
| 221 | PyTuple_SET_ITEM(dobj, 1, array_typestr_get(self))PyTuple_SetItem(dobj, 1, array_typestr_get(self)); | |||
| 222 | res = PyList_New(1); | |||
| 223 | if (res == NULL((void*)0)) { | |||
| 224 | Py_DECREF(dobj)_Py_DECREF(((PyObject*)(dobj))); | |||
| 225 | return NULL((void*)0); | |||
| 226 | } | |||
| 227 | PyList_SET_ITEM(res, 0, dobj)PyList_SetItem(res, 0, dobj); | |||
| 228 | return res; | |||
| 229 | } | |||
| 230 | ||||
| 231 | static PyObject * | |||
| 232 | array_protocol_strides_get(PyArrayObject *self) | |||
| 233 | { | |||
| 234 | if (PyArray_ISCONTIGUOUS(self)PyArray_CHKFLAGS((self), 0x0001)) { | |||
| 235 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 236 | } | |||
| 237 | return PyArray_IntTupleFromIntp(PyArray_NDIM(self), PyArray_STRIDES(self)); | |||
| 238 | } | |||
| 239 | ||||
| 240 | ||||
| 241 | ||||
| 242 | static PyObject * | |||
| 243 | array_dataptr_get(PyArrayObject *self) | |||
| 244 | { | |||
| 245 | return Py_BuildValue_Py_BuildValue_SizeT("NO", | |||
| 246 | PyLong_FromVoidPtr(PyArray_DATA(self)), | |||
| 247 | ((PyArray_FLAGS(self) & NPY_ARRAY_WRITEABLE0x0400) && | |||
| 248 | !(PyArray_FLAGS(self) & NPY_ARRAY_WARN_ON_WRITE)) ? | |||
| 249 | Py_False((PyObject *) &_Py_FalseStruct) : Py_True((PyObject *) &_Py_TrueStruct)); | |||
| 250 | } | |||
| 251 | ||||
| 252 | static PyObject * | |||
| 253 | array_ctypes_get(PyArrayObject *self) | |||
| 254 | { | |||
| 255 | PyObject *_numpy_internal; | |||
| 256 | PyObject *ret; | |||
| 257 | _numpy_internal = PyImport_ImportModule("numpy.core._internal"); | |||
| 258 | if (_numpy_internal == NULL((void*)0)) { | |||
| 259 | return NULL((void*)0); | |||
| 260 | } | |||
| 261 | ret = PyObject_CallMethod_PyObject_CallMethod_SizeT(_numpy_internal, "_ctypes", "ON", self, | |||
| 262 | PyLong_FromVoidPtr(PyArray_DATA(self))); | |||
| 263 | Py_DECREF(_numpy_internal)_Py_DECREF(((PyObject*)(_numpy_internal))); | |||
| 264 | return ret; | |||
| 265 | } | |||
| 266 | ||||
| 267 | static PyObject * | |||
| 268 | array_interface_get(PyArrayObject *self) | |||
| 269 | { | |||
| 270 | PyObject *dict; | |||
| 271 | PyObject *obj; | |||
| 272 | ||||
| 273 | dict = PyDict_New(); | |||
| 274 | if (dict == NULL((void*)0)) { | |||
| 275 | return NULL((void*)0); | |||
| 276 | } | |||
| 277 | ||||
| 278 | int ret; | |||
| 279 | ||||
| 280 | /* dataptr */ | |||
| 281 | obj = array_dataptr_get(self); | |||
| 282 | ret = PyDict_SetItemString(dict, "data", obj); | |||
| 283 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | |||
| 284 | if (ret < 0) { | |||
| 285 | Py_DECREF(dict)_Py_DECREF(((PyObject*)(dict))); | |||
| 286 | return NULL((void*)0); | |||
| 287 | } | |||
| 288 | ||||
| 289 | obj = array_protocol_strides_get(self); | |||
| 290 | ret = PyDict_SetItemString(dict, "strides", obj); | |||
| 291 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | |||
| 292 | if (ret < 0) { | |||
| 293 | Py_DECREF(dict)_Py_DECREF(((PyObject*)(dict))); | |||
| 294 | return NULL((void*)0); | |||
| 295 | } | |||
| 296 | ||||
| 297 | obj = array_protocol_descr_get(self); | |||
| 298 | ret = PyDict_SetItemString(dict, "descr", obj); | |||
| 299 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | |||
| 300 | if (ret < 0) { | |||
| 301 | Py_DECREF(dict)_Py_DECREF(((PyObject*)(dict))); | |||
| 302 | return NULL((void*)0); | |||
| 303 | } | |||
| 304 | ||||
| 305 | obj = arraydescr_protocol_typestr_get(PyArray_DESCR(self)); | |||
| 306 | ret = PyDict_SetItemString(dict, "typestr", obj); | |||
| 307 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | |||
| 308 | if (ret < 0) { | |||
| 309 | Py_DECREF(dict)_Py_DECREF(((PyObject*)(dict))); | |||
| 310 | return NULL((void*)0); | |||
| 311 | } | |||
| 312 | ||||
| 313 | obj = array_shape_get(self); | |||
| 314 | ret = PyDict_SetItemString(dict, "shape", obj); | |||
| 315 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | |||
| 316 | if (ret < 0) { | |||
| 317 | Py_DECREF(dict)_Py_DECREF(((PyObject*)(dict))); | |||
| 318 | return NULL((void*)0); | |||
| 319 | } | |||
| 320 | ||||
| 321 | obj = PyLong_FromLong(3); | |||
| 322 | ret = PyDict_SetItemString(dict, "version", obj); | |||
| 323 | Py_DECREF(obj)_Py_DECREF(((PyObject*)(obj))); | |||
| 324 | if (ret < 0) { | |||
| 325 | Py_DECREF(dict)_Py_DECREF(((PyObject*)(dict))); | |||
| 326 | return NULL((void*)0); | |||
| 327 | } | |||
| 328 | ||||
| 329 | return dict; | |||
| 330 | } | |||
| 331 | ||||
| 332 | static PyObject * | |||
| 333 | array_data_get(PyArrayObject *self) | |||
| 334 | { | |||
| 335 | return PyMemoryView_FromObject((PyObject *)self); | |||
| 336 | } | |||
| 337 | ||||
| 338 | static int | |||
| 339 | array_data_set(PyArrayObject *self, PyObject *op) | |||
| 340 | { | |||
| 341 | void *buf; | |||
| 342 | Py_ssize_t buf_len; | |||
| 343 | int writeable=1; | |||
| 344 | Py_buffer view; | |||
| 345 | ||||
| 346 | /* 2016-19-02, 1.12 */ | |||
| 347 | int ret = DEPRECATE("Assigning the 'data' attribute is an "PyErr_WarnEx(PyExc_DeprecationWarning,"Assigning the 'data' attribute is an " "inherently unsafe operation and will " "be removed in the future." ,1) | |||
| 348 | "inherently unsafe operation and will "PyErr_WarnEx(PyExc_DeprecationWarning,"Assigning the 'data' attribute is an " "inherently unsafe operation and will " "be removed in the future." ,1) | |||
| 349 | "be removed in the future.")PyErr_WarnEx(PyExc_DeprecationWarning,"Assigning the 'data' attribute is an " "inherently unsafe operation and will " "be removed in the future." ,1); | |||
| 350 | if (ret < 0) { | |||
| 351 | return -1; | |||
| 352 | } | |||
| 353 | ||||
| 354 | if (op == NULL((void*)0)) { | |||
| 355 | PyErr_SetString(PyExc_AttributeError, | |||
| 356 | "Cannot delete array data"); | |||
| 357 | return -1; | |||
| 358 | } | |||
| 359 | if (PyObject_GetBuffer(op, &view, PyBUF_WRITABLE0x0001|PyBUF_SIMPLE0) < 0) { | |||
| 360 | writeable = 0; | |||
| 361 | PyErr_Clear(); | |||
| 362 | if (PyObject_GetBuffer(op, &view, PyBUF_SIMPLE0) < 0) { | |||
| 363 | return -1; | |||
| 364 | } | |||
| 365 | } | |||
| 366 | buf = view.buf; | |||
| 367 | buf_len = view.len; | |||
| 368 | /* | |||
| 369 | * In Python 3 both of the deprecated functions PyObject_AsWriteBuffer and | |||
| 370 | * PyObject_AsReadBuffer that this code replaces release the buffer. It is | |||
| 371 | * up to the object that supplies the buffer to guarantee that the buffer | |||
| 372 | * sticks around after the release. | |||
| 373 | */ | |||
| 374 | PyBuffer_Release(&view); | |||
| 375 | ||||
| 376 | if (!PyArray_ISONESEGMENT(self)(PyArray_CHKFLAGS(self, 0x0001) || PyArray_CHKFLAGS(self, 0x0002 ))) { | |||
| 377 | PyErr_SetString(PyExc_AttributeError, | |||
| 378 | "cannot set single-segment buffer for discontiguous array"); | |||
| 379 | return -1; | |||
| 380 | } | |||
| 381 | if (PyArray_NBYTES(self)(PyArray_ITEMSIZE(self) * PyArray_MultiplyList(PyArray_DIMS(self ), PyArray_NDIM(self))) > buf_len) { | |||
| 382 | PyErr_SetString(PyExc_AttributeError, "not enough data for array"); | |||
| 383 | return -1; | |||
| 384 | } | |||
| 385 | if (PyArray_FLAGS(self) & NPY_ARRAY_OWNDATA0x0004) { | |||
| 386 | PyArray_XDECREF(self); | |||
| 387 | PyDataMem_FREE(PyArray_DATA(self)); | |||
| 388 | } | |||
| 389 | if (PyArray_BASE(self)) { | |||
| 390 | if ((PyArray_FLAGS(self) & NPY_ARRAY_WRITEBACKIFCOPY0x2000) || | |||
| 391 | (PyArray_FLAGS(self) & NPY_ARRAY_UPDATEIFCOPY0x1000)) { | |||
| 392 | PyArray_ENABLEFLAGS((PyArrayObject *)PyArray_BASE(self), | |||
| 393 | NPY_ARRAY_WRITEABLE0x0400); | |||
| 394 | PyArray_CLEARFLAGS(self, NPY_ARRAY_WRITEBACKIFCOPY0x2000); | |||
| 395 | PyArray_CLEARFLAGS(self, NPY_ARRAY_UPDATEIFCOPY0x1000); | |||
| 396 | } | |||
| 397 | Py_DECREF(PyArray_BASE(self))_Py_DECREF(((PyObject*)(PyArray_BASE(self)))); | |||
| 398 | ((PyArrayObject_fields *)self)->base = NULL((void*)0); | |||
| 399 | } | |||
| 400 | Py_INCREF(op)_Py_INCREF(((PyObject*)(op))); | |||
| 401 | if (PyArray_SetBaseObject(self, op) < 0) { | |||
| 402 | return -1; | |||
| 403 | } | |||
| 404 | ((PyArrayObject_fields *)self)->data = buf; | |||
| 405 | ((PyArrayObject_fields *)self)->flags = NPY_ARRAY_CARRAY(0x0001 | (0x0100 | 0x0400)); | |||
| 406 | if (!writeable) { | |||
| 407 | PyArray_CLEARFLAGS(self, ~NPY_ARRAY_WRITEABLE0x0400); | |||
| 408 | } | |||
| 409 | return 0; | |||
| 410 | } | |||
| 411 | ||||
| 412 | ||||
| 413 | static PyObject * | |||
| 414 | array_itemsize_get(PyArrayObject *self) | |||
| 415 | { | |||
| 416 | return PyLong_FromLong((long) PyArray_DESCR(self)->elsize); | |||
| 417 | } | |||
| 418 | ||||
| 419 | static PyObject * | |||
| 420 | array_size_get(PyArrayObject *self) | |||
| 421 | { | |||
| 422 | npy_intp size=PyArray_SIZE(self)PyArray_MultiplyList(PyArray_DIMS(self), PyArray_NDIM(self)); | |||
| 423 | #if NPY_SIZEOF_INTP8 <= NPY_SIZEOF_LONG8 | |||
| 424 | return PyLong_FromLong((long) size); | |||
| 425 | #else | |||
| 426 | if (size > NPY_MAX_LONG9223372036854775807L || size < NPY_MIN_LONG(-9223372036854775807L -1L)) { | |||
| 427 | return PyLong_FromLongLong(size); | |||
| 428 | } | |||
| 429 | else { | |||
| 430 | return PyLong_FromLong((long) size); | |||
| 431 | } | |||
| 432 | #endif | |||
| 433 | } | |||
| 434 | ||||
| 435 | static PyObject * | |||
| 436 | array_nbytes_get(PyArrayObject *self) | |||
| 437 | { | |||
| 438 | npy_intp nbytes = PyArray_NBYTES(self)(PyArray_ITEMSIZE(self) * PyArray_MultiplyList(PyArray_DIMS(self ), PyArray_NDIM(self))); | |||
| 439 | #if NPY_SIZEOF_INTP8 <= NPY_SIZEOF_LONG8 | |||
| 440 | return PyLong_FromLong((long) nbytes); | |||
| 441 | #else | |||
| 442 | if (nbytes > NPY_MAX_LONG9223372036854775807L || nbytes < NPY_MIN_LONG(-9223372036854775807L -1L)) { | |||
| 443 | return PyLong_FromLongLong(nbytes); | |||
| 444 | } | |||
| 445 | else { | |||
| 446 | return PyLong_FromLong((long) nbytes); | |||
| 447 | } | |||
| 448 | #endif | |||
| 449 | } | |||
| 450 | ||||
| 451 | ||||
| 452 | /* | |||
| 453 | * If the type is changed. | |||
| 454 | * Also needing change: strides, itemsize | |||
| 455 | * | |||
| 456 | * Either itemsize is exactly the same or the array is single-segment | |||
| 457 | * (contiguous or fortran) with compatible dimensions The shape and strides | |||
| 458 | * will be adjusted in that case as well. | |||
| 459 | */ | |||
| 460 | static int | |||
| 461 | array_descr_set(PyArrayObject *self, PyObject *arg) | |||
| 462 | { | |||
| 463 | PyArray_Descr *newtype = NULL((void*)0); | |||
| 464 | ||||
| 465 | if (arg == NULL((void*)0)) { | |||
| ||||
| 466 | PyErr_SetString(PyExc_AttributeError, | |||
| 467 | "Cannot delete array dtype"); | |||
| 468 | return -1; | |||
| 469 | } | |||
| 470 | ||||
| 471 | if (!(PyArray_DescrConverter(arg, &newtype)) || | |||
| 472 | newtype == NULL((void*)0)) { | |||
| 473 | PyErr_SetString(PyExc_TypeError, | |||
| 474 | "invalid data-type for array"); | |||
| 475 | return -1; | |||
| 476 | } | |||
| 477 | ||||
| 478 | /* check that we are not reinterpreting memory containing Objects. */ | |||
| 479 | if (_may_have_objects(PyArray_DESCR(self)) || _may_have_objects(newtype)) { | |||
| 480 | static PyObject *checkfunc = NULL((void*)0); | |||
| 481 | PyObject *safe; | |||
| 482 | ||||
| 483 | npy_cache_import("numpy.core._internal", "_view_is_safe", &checkfunc); | |||
| 484 | if (checkfunc == NULL((void*)0)) { | |||
| 485 | goto fail; | |||
| 486 | } | |||
| 487 | ||||
| 488 | safe = PyObject_CallFunction_PyObject_CallFunction_SizeT(checkfunc, "OO", | |||
| 489 | PyArray_DESCR(self), newtype); | |||
| 490 | if (safe == NULL((void*)0)) { | |||
| 491 | goto fail; | |||
| 492 | } | |||
| 493 | Py_DECREF(safe)_Py_DECREF(((PyObject*)(safe))); | |||
| 494 | } | |||
| 495 | ||||
| 496 | /* | |||
| 497 | * Viewing as an unsized void implies a void dtype matching the size of the | |||
| 498 | * current dtype. | |||
| 499 | */ | |||
| 500 | if (newtype->type_num == NPY_VOID && | |||
| 501 | PyDataType_ISUNSIZED(newtype)((newtype)->elsize == 0 && !(((PyArray_Descr *)(newtype ))->names != ((void*)0))) && | |||
| 502 | newtype->elsize != PyArray_DESCR(self)->elsize) { | |||
| 503 | PyArray_DESCR_REPLACE(newtype)do { PyArray_Descr *_new_; _new_ = PyArray_DescrNew(newtype); _Py_XDECREF(((PyObject*)(newtype))); newtype = _new_; } while (0); | |||
| 504 | if (newtype == NULL((void*)0)) { | |||
| 505 | return -1; | |||
| 506 | } | |||
| 507 | newtype->elsize = PyArray_DESCR(self)->elsize; | |||
| 508 | } | |||
| 509 | ||||
| 510 | /* Changing the size of the dtype results in a shape change */ | |||
| 511 | if (newtype->elsize != PyArray_DESCR(self)->elsize) { | |||
| 512 | int axis; | |||
| 513 | npy_intp newdim; | |||
| 514 | ||||
| 515 | /* forbidden cases */ | |||
| 516 | if (PyArray_NDIM(self) == 0) { | |||
| 517 | PyErr_SetString(PyExc_ValueError, | |||
| 518 | "Changing the dtype of a 0d array is only supported " | |||
| 519 | "if the itemsize is unchanged"); | |||
| 520 | goto fail; | |||
| 521 | } | |||
| 522 | else if (PyDataType_HASSUBARRAY(newtype)((newtype)->subarray != ((void*)0))) { | |||
| 523 | PyErr_SetString(PyExc_ValueError, | |||
| 524 | "Changing the dtype to a subarray type is only supported " | |||
| 525 | "if the total itemsize is unchanged"); | |||
| 526 | goto fail; | |||
| 527 | } | |||
| 528 | ||||
| 529 | /* determine which axis to resize */ | |||
| 530 | if (PyArray_IS_C_CONTIGUOUS(self)PyArray_CHKFLAGS((self), 0x0001)) { | |||
| 531 | axis = PyArray_NDIM(self) - 1; | |||
| 532 | } | |||
| 533 | else if (PyArray_IS_F_CONTIGUOUS(self)PyArray_CHKFLAGS((self), 0x0002)) { | |||
| 534 | /* 2015-11-27 1.11.0, gh-6747 */ | |||
| 535 | if (DEPRECATE(PyErr_WarnEx(PyExc_DeprecationWarning,"Changing the shape of an F-contiguous array by " "descriptor assignment is deprecated. To maintain the " "Fortran contiguity of a multidimensional Fortran " "array, use 'a.T.view(...).T' instead",1) | |||
| 536 | "Changing the shape of an F-contiguous array by "PyErr_WarnEx(PyExc_DeprecationWarning,"Changing the shape of an F-contiguous array by " "descriptor assignment is deprecated. To maintain the " "Fortran contiguity of a multidimensional Fortran " "array, use 'a.T.view(...).T' instead",1) | |||
| 537 | "descriptor assignment is deprecated. To maintain the "PyErr_WarnEx(PyExc_DeprecationWarning,"Changing the shape of an F-contiguous array by " "descriptor assignment is deprecated. To maintain the " "Fortran contiguity of a multidimensional Fortran " "array, use 'a.T.view(...).T' instead",1) | |||
| 538 | "Fortran contiguity of a multidimensional Fortran "PyErr_WarnEx(PyExc_DeprecationWarning,"Changing the shape of an F-contiguous array by " "descriptor assignment is deprecated. To maintain the " "Fortran contiguity of a multidimensional Fortran " "array, use 'a.T.view(...).T' instead",1) | |||
| 539 | "array, use 'a.T.view(...).T' instead")PyErr_WarnEx(PyExc_DeprecationWarning,"Changing the shape of an F-contiguous array by " "descriptor assignment is deprecated. To maintain the " "Fortran contiguity of a multidimensional Fortran " "array, use 'a.T.view(...).T' instead",1) < 0) { | |||
| 540 | goto fail; | |||
| 541 | } | |||
| 542 | axis = 0; | |||
| 543 | } | |||
| 544 | else { | |||
| 545 | /* Don't mention the deprecated F-contiguous support */ | |||
| 546 | PyErr_SetString(PyExc_ValueError, | |||
| 547 | "To change to a dtype of a different size, the array must " | |||
| 548 | "be C-contiguous"); | |||
| 549 | goto fail; | |||
| 550 | } | |||
| 551 | ||||
| 552 | if (newtype->elsize < PyArray_DESCR(self)->elsize) { | |||
| 553 | /* if it is compatible, increase the size of the relevant axis */ | |||
| 554 | if (newtype->elsize == 0 || | |||
| 555 | PyArray_DESCR(self)->elsize % newtype->elsize != 0) { | |||
| 556 | PyErr_SetString(PyExc_ValueError, | |||
| 557 | "When changing to a smaller dtype, its size must be a " | |||
| 558 | "divisor of the size of original dtype"); | |||
| 559 | goto fail; | |||
| 560 | } | |||
| 561 | newdim = PyArray_DESCR(self)->elsize / newtype->elsize; | |||
| 562 | PyArray_DIMS(self)[axis] *= newdim; | |||
| 563 | PyArray_STRIDES(self)[axis] = newtype->elsize; | |||
| 564 | } | |||
| 565 | else if (newtype->elsize > PyArray_DESCR(self)->elsize) { | |||
| 566 | /* if it is compatible, decrease the size of the relevant axis */ | |||
| 567 | newdim = PyArray_DIMS(self)[axis] * PyArray_DESCR(self)->elsize; | |||
| 568 | if ((newdim % newtype->elsize) != 0) { | |||
| 569 | PyErr_SetString(PyExc_ValueError, | |||
| 570 | "When changing to a larger dtype, its size must be a " | |||
| 571 | "divisor of the total size in bytes of the last axis " | |||
| 572 | "of the array."); | |||
| 573 | goto fail; | |||
| 574 | } | |||
| 575 | PyArray_DIMS(self)[axis] = newdim / newtype->elsize; | |||
| 576 | PyArray_STRIDES(self)[axis] = newtype->elsize; | |||
| 577 | } | |||
| 578 | } | |||
| 579 | ||||
| 580 | /* Viewing as a subarray increases the number of dimensions */ | |||
| 581 | if (PyDataType_HASSUBARRAY(newtype)((newtype)->subarray != ((void*)0))) { | |||
| 582 | /* | |||
| 583 | * create new array object from data and update | |||
| 584 | * dimensions, strides and descr from it | |||
| 585 | */ | |||
| 586 | PyArrayObject *temp; | |||
| 587 | /* | |||
| 588 | * We would decref newtype here. | |||
| 589 | * temp will steal a reference to it | |||
| 590 | */ | |||
| 591 | temp = (PyArrayObject *) | |||
| 592 | PyArray_NewFromDescr(&PyArray_Type, newtype, PyArray_NDIM(self), | |||
| 593 | PyArray_DIMS(self), PyArray_STRIDES(self), | |||
| 594 | PyArray_DATA(self), PyArray_FLAGS(self), NULL((void*)0)); | |||
| 595 | if (temp == NULL((void*)0)) { | |||
| 596 | return -1; | |||
| 597 | } | |||
| 598 | npy_free_cache_dim_array(self); | |||
| 599 | ((PyArrayObject_fields *)self)->dimensions = PyArray_DIMS(temp); | |||
| 600 | ((PyArrayObject_fields *)self)->nd = PyArray_NDIM(temp); | |||
| 601 | ((PyArrayObject_fields *)self)->strides = PyArray_STRIDES(temp); | |||
| 602 | newtype = PyArray_DESCR(temp); | |||
| 603 | Py_INCREF(PyArray_DESCR(temp))_Py_INCREF(((PyObject*)(PyArray_DESCR(temp)))); | |||
| 604 | /* Fool deallocator not to delete these*/ | |||
| 605 | ((PyArrayObject_fields *)temp)->nd = 0; | |||
| 606 | ((PyArrayObject_fields *)temp)->dimensions = NULL((void*)0); | |||
| 607 | Py_DECREF(temp)_Py_DECREF(((PyObject*)(temp))); | |||
| 608 | } | |||
| 609 | ||||
| 610 | Py_DECREF(PyArray_DESCR(self))_Py_DECREF(((PyObject*)(PyArray_DESCR(self)))); | |||
| 611 | ((PyArrayObject_fields *)self)->descr = newtype; | |||
| 612 | PyArray_UpdateFlags(self, NPY_ARRAY_UPDATE_ALL(0x0001 | 0x0002 | 0x0100)); | |||
| 613 | return 0; | |||
| 614 | ||||
| 615 | fail: | |||
| 616 | Py_DECREF(newtype)_Py_DECREF(((PyObject*)(newtype))); | |||
| 617 | return -1; | |||
| 618 | } | |||
| 619 | ||||
| 620 | static PyObject * | |||
| 621 | array_struct_get(PyArrayObject *self) | |||
| 622 | { | |||
| 623 | PyArrayInterface *inter; | |||
| 624 | ||||
| 625 | inter = (PyArrayInterface *)PyArray_mallocPyMem_RawMalloc(sizeof(PyArrayInterface)); | |||
| 626 | if (inter==NULL((void*)0)) { | |||
| 627 | return PyErr_NoMemory(); | |||
| 628 | } | |||
| 629 | inter->two = 2; | |||
| 630 | inter->nd = PyArray_NDIM(self); | |||
| 631 | inter->typekind = PyArray_DESCR(self)->kind; | |||
| 632 | inter->itemsize = PyArray_DESCR(self)->elsize; | |||
| 633 | inter->flags = PyArray_FLAGS(self); | |||
| 634 | if (inter->flags & NPY_ARRAY_WARN_ON_WRITE) { | |||
| 635 | /* Export a warn-on-write array as read-only */ | |||
| 636 | inter->flags = inter->flags & ~NPY_ARRAY_WARN_ON_WRITE; | |||
| 637 | inter->flags = inter->flags & ~NPY_ARRAY_WRITEABLE0x0400; | |||
| 638 | } | |||
| 639 | /* reset unused flags */ | |||
| 640 | inter->flags &= ~(NPY_ARRAY_WRITEBACKIFCOPY0x2000 | NPY_ARRAY_UPDATEIFCOPY0x1000 |NPY_ARRAY_OWNDATA0x0004); | |||
| 641 | if (PyArray_ISNOTSWAPPED(self)((PyArray_DESCR(self)->byteorder) != '>')) inter->flags |= NPY_ARRAY_NOTSWAPPED0x0200; | |||
| 642 | /* | |||
| 643 | * Copy shape and strides over since these can be reset | |||
| 644 | *when the array is "reshaped". | |||
| 645 | */ | |||
| 646 | if (PyArray_NDIM(self) > 0) { | |||
| 647 | inter->shape = (npy_intp *)PyArray_mallocPyMem_RawMalloc(2*sizeof(npy_intp)*PyArray_NDIM(self)); | |||
| 648 | if (inter->shape == NULL((void*)0)) { | |||
| 649 | PyArray_freePyMem_RawFree(inter); | |||
| 650 | return PyErr_NoMemory(); | |||
| 651 | } | |||
| 652 | inter->strides = inter->shape + PyArray_NDIM(self); | |||
| 653 | if (PyArray_NDIM(self)) { | |||
| 654 | memcpy(inter->shape, PyArray_DIMS(self), sizeof(npy_intp)*PyArray_NDIM(self)); | |||
| 655 | memcpy(inter->strides, PyArray_STRIDES(self), sizeof(npy_intp)*PyArray_NDIM(self)); | |||
| 656 | } | |||
| 657 | } | |||
| 658 | else { | |||
| 659 | inter->shape = NULL((void*)0); | |||
| 660 | inter->strides = NULL((void*)0); | |||
| 661 | } | |||
| 662 | inter->data = PyArray_DATA(self); | |||
| 663 | if (PyDataType_HASFIELDS(PyArray_DESCR(self))(((PyArray_Descr *)(PyArray_DESCR(self)))->names != ((void *)0))) { | |||
| 664 | inter->descr = arraydescr_protocol_descr_get(PyArray_DESCR(self)); | |||
| 665 | if (inter->descr == NULL((void*)0)) { | |||
| 666 | PyErr_Clear(); | |||
| 667 | } | |||
| 668 | else { | |||
| 669 | inter->flags &= NPY_ARR_HAS_DESCR0x0800; | |||
| 670 | } | |||
| 671 | } | |||
| 672 | else { | |||
| 673 | inter->descr = NULL((void*)0); | |||
| 674 | } | |||
| 675 | PyObject *ret = PyCapsule_New(inter, NULL((void*)0), gentype_struct_free); | |||
| 676 | if (ret == NULL((void*)0)) { | |||
| 677 | return NULL((void*)0); | |||
| 678 | } | |||
| 679 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
| 680 | if (PyCapsule_SetContext(ret, self) < 0) { | |||
| 681 | return NULL((void*)0); | |||
| 682 | } | |||
| 683 | return ret; | |||
| 684 | } | |||
| 685 | ||||
| 686 | static PyObject * | |||
| 687 | array_base_get(PyArrayObject *self) | |||
| 688 | { | |||
| 689 | if (PyArray_BASE(self) == NULL((void*)0)) { | |||
| 690 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 691 | } | |||
| 692 | else { | |||
| 693 | Py_INCREF(PyArray_BASE(self))_Py_INCREF(((PyObject*)(PyArray_BASE(self)))); | |||
| 694 | return PyArray_BASE(self); | |||
| 695 | } | |||
| 696 | } | |||
| 697 | ||||
| 698 | /* | |||
| 699 | * Create a view of a complex array with an equivalent data-type | |||
| 700 | * except it is real instead of complex. | |||
| 701 | */ | |||
| 702 | static PyArrayObject * | |||
| 703 | _get_part(PyArrayObject *self, int imag) | |||
| 704 | { | |||
| 705 | int float_type_num; | |||
| 706 | PyArray_Descr *type; | |||
| 707 | PyArrayObject *ret; | |||
| 708 | int offset; | |||
| 709 | ||||
| 710 | switch (PyArray_DESCR(self)->type_num) { | |||
| 711 | case NPY_CFLOAT: | |||
| 712 | float_type_num = NPY_FLOAT; | |||
| 713 | break; | |||
| 714 | case NPY_CDOUBLE: | |||
| 715 | float_type_num = NPY_DOUBLE; | |||
| 716 | break; | |||
| 717 | case NPY_CLONGDOUBLE: | |||
| 718 | float_type_num = NPY_LONGDOUBLE; | |||
| 719 | break; | |||
| 720 | default: | |||
| 721 | PyErr_Format(PyExc_ValueError, | |||
| 722 | "Cannot convert complex type number %d to float", | |||
| 723 | PyArray_DESCR(self)->type_num); | |||
| 724 | return NULL((void*)0); | |||
| 725 | ||||
| 726 | } | |||
| 727 | type = PyArray_DescrFromType(float_type_num); | |||
| 728 | ||||
| 729 | offset = (imag ? type->elsize : 0); | |||
| 730 | ||||
| 731 | if (!PyArray_ISNBO(PyArray_DESCR(self)->byteorder)((PyArray_DESCR(self)->byteorder) != '>')) { | |||
| 732 | PyArray_Descr *new; | |||
| 733 | new = PyArray_DescrNew(type); | |||
| 734 | new->byteorder = PyArray_DESCR(self)->byteorder; | |||
| 735 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | |||
| 736 | type = new; | |||
| 737 | } | |||
| 738 | ret = (PyArrayObject *)PyArray_NewFromDescrAndBase( | |||
| 739 | Py_TYPE(self)(((PyObject*)(self))->ob_type), | |||
| 740 | type, | |||
| 741 | PyArray_NDIM(self), | |||
| 742 | PyArray_DIMS(self), | |||
| 743 | PyArray_STRIDES(self), | |||
| 744 | PyArray_BYTES(self) + offset, | |||
| 745 | PyArray_FLAGS(self), (PyObject *)self, (PyObject *)self); | |||
| 746 | if (ret == NULL((void*)0)) { | |||
| 747 | return NULL((void*)0); | |||
| 748 | } | |||
| 749 | return ret; | |||
| 750 | } | |||
| 751 | ||||
| 752 | /* For Object arrays, we need to get and set the | |||
| 753 | real part of each element. | |||
| 754 | */ | |||
| 755 | ||||
| 756 | static PyObject * | |||
| 757 | array_real_get(PyArrayObject *self) | |||
| 758 | { | |||
| 759 | PyArrayObject *ret; | |||
| 760 | ||||
| 761 | if (PyArray_ISCOMPLEX(self)(((PyArray_TYPE(self)) >= NPY_CFLOAT) && ((PyArray_TYPE (self)) <= NPY_CLONGDOUBLE))) { | |||
| 762 | ret = _get_part(self, 0); | |||
| 763 | return (PyObject *)ret; | |||
| 764 | } | |||
| 765 | else { | |||
| 766 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
| 767 | return (PyObject *)self; | |||
| 768 | } | |||
| 769 | } | |||
| 770 | ||||
| 771 | ||||
| 772 | static int | |||
| 773 | array_real_set(PyArrayObject *self, PyObject *val) | |||
| 774 | { | |||
| 775 | PyArrayObject *ret; | |||
| 776 | PyArrayObject *new; | |||
| 777 | int retcode; | |||
| 778 | ||||
| 779 | if (val == NULL((void*)0)) { | |||
| 780 | PyErr_SetString(PyExc_AttributeError, | |||
| 781 | "Cannot delete array real part"); | |||
| 782 | return -1; | |||
| 783 | } | |||
| 784 | if (PyArray_ISCOMPLEX(self)(((PyArray_TYPE(self)) >= NPY_CFLOAT) && ((PyArray_TYPE (self)) <= NPY_CLONGDOUBLE))) { | |||
| 785 | ret = _get_part(self, 0); | |||
| 786 | if (ret == NULL((void*)0)) { | |||
| 787 | return -1; | |||
| 788 | } | |||
| 789 | } | |||
| 790 | else { | |||
| 791 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
| 792 | ret = self; | |||
| 793 | } | |||
| 794 | new = (PyArrayObject *)PyArray_FROM_O(val)PyArray_FromAny(val, ((void*)0), 0, 0, 0, ((void*)0)); | |||
| 795 | if (new == NULL((void*)0)) { | |||
| 796 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 797 | return -1; | |||
| 798 | } | |||
| 799 | retcode = PyArray_MoveInto(ret, new); | |||
| 800 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 801 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 802 | return retcode; | |||
| 803 | } | |||
| 804 | ||||
| 805 | /* For Object arrays we need to get | |||
| 806 | and set the imaginary part of | |||
| 807 | each element | |||
| 808 | */ | |||
| 809 | ||||
| 810 | static PyObject * | |||
| 811 | array_imag_get(PyArrayObject *self) | |||
| 812 | { | |||
| 813 | PyArrayObject *ret; | |||
| 814 | ||||
| 815 | if (PyArray_ISCOMPLEX(self)(((PyArray_TYPE(self)) >= NPY_CFLOAT) && ((PyArray_TYPE (self)) <= NPY_CLONGDOUBLE))) { | |||
| 816 | ret = _get_part(self, 1); | |||
| 817 | } | |||
| 818 | else { | |||
| 819 | Py_INCREF(PyArray_DESCR(self))_Py_INCREF(((PyObject*)(PyArray_DESCR(self)))); | |||
| 820 | ret = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(self)(((PyObject*)(self))->ob_type), | |||
| 821 | PyArray_DESCR(self), | |||
| 822 | PyArray_NDIM(self), | |||
| 823 | PyArray_DIMS(self), | |||
| 824 | NULL((void*)0), NULL((void*)0), | |||
| 825 | PyArray_ISFORTRAN(self)(PyArray_CHKFLAGS(self, 0x0002) && (!PyArray_CHKFLAGS (self, 0x0001))), | |||
| 826 | (PyObject *)self); | |||
| 827 | if (ret == NULL((void*)0)) { | |||
| 828 | return NULL((void*)0); | |||
| 829 | } | |||
| 830 | if (_zerofill(ret) < 0) { | |||
| 831 | return NULL((void*)0); | |||
| 832 | } | |||
| 833 | PyArray_CLEARFLAGS(ret, NPY_ARRAY_WRITEABLE0x0400); | |||
| 834 | } | |||
| 835 | return (PyObject *) ret; | |||
| 836 | } | |||
| 837 | ||||
| 838 | static int | |||
| 839 | array_imag_set(PyArrayObject *self, PyObject *val) | |||
| 840 | { | |||
| 841 | if (val == NULL((void*)0)) { | |||
| 842 | PyErr_SetString(PyExc_AttributeError, | |||
| 843 | "Cannot delete array imaginary part"); | |||
| 844 | return -1; | |||
| 845 | } | |||
| 846 | if (PyArray_ISCOMPLEX(self)(((PyArray_TYPE(self)) >= NPY_CFLOAT) && ((PyArray_TYPE (self)) <= NPY_CLONGDOUBLE))) { | |||
| 847 | PyArrayObject *ret; | |||
| 848 | PyArrayObject *new; | |||
| 849 | int retcode; | |||
| 850 | ||||
| 851 | ret = _get_part(self, 1); | |||
| 852 | if (ret == NULL((void*)0)) { | |||
| 853 | return -1; | |||
| 854 | } | |||
| 855 | new = (PyArrayObject *)PyArray_FROM_O(val)PyArray_FromAny(val, ((void*)0), 0, 0, 0, ((void*)0)); | |||
| 856 | if (new == NULL((void*)0)) { | |||
| 857 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 858 | return -1; | |||
| 859 | } | |||
| 860 | retcode = PyArray_MoveInto(ret, new); | |||
| 861 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 862 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 863 | return retcode; | |||
| 864 | } | |||
| 865 | else { | |||
| 866 | PyErr_SetString(PyExc_TypeError, | |||
| 867 | "array does not have imaginary part to set"); | |||
| 868 | return -1; | |||
| 869 | } | |||
| 870 | } | |||
| 871 | ||||
| 872 | static PyObject * | |||
| 873 | array_flat_get(PyArrayObject *self) | |||
| 874 | { | |||
| 875 | return PyArray_IterNew((PyObject *)self); | |||
| 876 | } | |||
| 877 | ||||
| 878 | static int | |||
| 879 | array_flat_set(PyArrayObject *self, PyObject *val) | |||
| 880 | { | |||
| 881 | PyArrayObject *arr = NULL((void*)0); | |||
| 882 | int retval = -1; | |||
| 883 | PyArrayIterObject *selfit = NULL((void*)0), *arrit = NULL((void*)0); | |||
| 884 | PyArray_Descr *typecode; | |||
| 885 | int swap; | |||
| 886 | PyArray_CopySwapFunc *copyswap; | |||
| 887 | ||||
| 888 | if (val == NULL((void*)0)) { | |||
| 889 | PyErr_SetString(PyExc_AttributeError, | |||
| 890 | "Cannot delete array flat iterator"); | |||
| 891 | return -1; | |||
| 892 | } | |||
| 893 | if (PyArray_FailUnlessWriteable(self, "array") < 0) return -1; | |||
| 894 | typecode = PyArray_DESCR(self); | |||
| 895 | Py_INCREF(typecode)_Py_INCREF(((PyObject*)(typecode))); | |||
| 896 | arr = (PyArrayObject *)PyArray_FromAny(val, typecode, | |||
| 897 | 0, 0, NPY_ARRAY_FORCECAST0x0010 | PyArray_FORTRAN_IF(self)((PyArray_CHKFLAGS(self, 0x0002) ? 0x0002 : 0)), NULL((void*)0)); | |||
| 898 | if (arr == NULL((void*)0)) { | |||
| 899 | return -1; | |||
| 900 | } | |||
| 901 | arrit = (PyArrayIterObject *)PyArray_IterNew((PyObject *)arr); | |||
| 902 | if (arrit == NULL((void*)0)) { | |||
| 903 | goto exit; | |||
| 904 | } | |||
| 905 | selfit = (PyArrayIterObject *)PyArray_IterNew((PyObject *)self); | |||
| 906 | if (selfit == NULL((void*)0)) { | |||
| 907 | goto exit; | |||
| 908 | } | |||
| 909 | if (arrit->size == 0) { | |||
| 910 | retval = 0; | |||
| 911 | goto exit; | |||
| 912 | } | |||
| 913 | swap = PyArray_ISNOTSWAPPED(self)((PyArray_DESCR(self)->byteorder) != '>') != PyArray_ISNOTSWAPPED(arr)((PyArray_DESCR(arr)->byteorder) != '>'); | |||
| 914 | copyswap = PyArray_DESCR(self)->f->copyswap; | |||
| 915 | if (PyDataType_REFCHK(PyArray_DESCR(self))(((PyArray_DESCR(self))->flags & (0x01)) == (0x01))) { | |||
| 916 | while (selfit->index < selfit->size) { | |||
| 917 | PyArray_Item_XDECREF(selfit->dataptr, PyArray_DESCR(self)); | |||
| 918 | PyArray_Item_INCREF(arrit->dataptr, PyArray_DESCR(arr)); | |||
| 919 | memmove(selfit->dataptr, arrit->dataptr, sizeof(PyObject **)); | |||
| 920 | if (swap) { | |||
| 921 | copyswap(selfit->dataptr, NULL((void*)0), swap, self); | |||
| 922 | } | |||
| 923 | PyArray_ITER_NEXT(selfit)do { ((PyArrayIterObject *)(selfit))->index++; if (((PyArrayIterObject *)(selfit))->nd_m1 == 0) { do { (((PyArrayIterObject *)(selfit )))->dataptr += ((PyArrayIterObject *)(((PyArrayIterObject *)(selfit))))->strides[0]; (((PyArrayIterObject *)(selfit )))->coordinates[0]++; } while (0); } else if (((PyArrayIterObject *)(selfit))->contiguous) ((PyArrayIterObject *)(selfit))-> dataptr += PyArray_DESCR(((PyArrayIterObject *)(selfit))-> ao)->elsize; else if (((PyArrayIterObject *)(selfit))-> nd_m1 == 1) { do { if ((((PyArrayIterObject *)(selfit)))-> coordinates[1] < (((PyArrayIterObject *)(selfit)))->dims_m1 [1]) { (((PyArrayIterObject *)(selfit)))->coordinates[1]++ ; (((PyArrayIterObject *)(selfit)))->dataptr += (((PyArrayIterObject *)(selfit)))->strides[1]; } else { (((PyArrayIterObject * )(selfit)))->coordinates[1] = 0; (((PyArrayIterObject *)(selfit )))->coordinates[0]++; (((PyArrayIterObject *)(selfit)))-> dataptr += (((PyArrayIterObject *)(selfit)))->strides[0] - (((PyArrayIterObject *)(selfit)))->backstrides[1]; } } while (0); } else { int __npy_i; for (__npy_i=((PyArrayIterObject * )(selfit))->nd_m1; __npy_i >= 0; __npy_i--) { if (((PyArrayIterObject *)(selfit))->coordinates[__npy_i] < ((PyArrayIterObject *)(selfit))->dims_m1[__npy_i]) { ((PyArrayIterObject *)(selfit ))->coordinates[__npy_i]++; ((PyArrayIterObject *)(selfit) )->dataptr += ((PyArrayIterObject *)(selfit))->strides[ __npy_i]; break; } else { ((PyArrayIterObject *)(selfit))-> coordinates[__npy_i] = 0; ((PyArrayIterObject *)(selfit))-> dataptr -= ((PyArrayIterObject *)(selfit))->backstrides[__npy_i ]; } } } } while (0); | |||
| 924 | PyArray_ITER_NEXT(arrit)do { ((PyArrayIterObject *)(arrit))->index++; if (((PyArrayIterObject *)(arrit))->nd_m1 == 0) { do { (((PyArrayIterObject *)(arrit )))->dataptr += ((PyArrayIterObject *)(((PyArrayIterObject *)(arrit))))->strides[0]; (((PyArrayIterObject *)(arrit)) )->coordinates[0]++; } while (0); } else if (((PyArrayIterObject *)(arrit))->contiguous) ((PyArrayIterObject *)(arrit))-> dataptr += PyArray_DESCR(((PyArrayIterObject *)(arrit))->ao )->elsize; else if (((PyArrayIterObject *)(arrit))->nd_m1 == 1) { do { if ((((PyArrayIterObject *)(arrit)))->coordinates [1] < (((PyArrayIterObject *)(arrit)))->dims_m1[1]) { ( ((PyArrayIterObject *)(arrit)))->coordinates[1]++; (((PyArrayIterObject *)(arrit)))->dataptr += (((PyArrayIterObject *)(arrit)))-> strides[1]; } else { (((PyArrayIterObject *)(arrit)))->coordinates [1] = 0; (((PyArrayIterObject *)(arrit)))->coordinates[0]++ ; (((PyArrayIterObject *)(arrit)))->dataptr += (((PyArrayIterObject *)(arrit)))->strides[0] - (((PyArrayIterObject *)(arrit)) )->backstrides[1]; } } while (0); } else { int __npy_i; for (__npy_i=((PyArrayIterObject *)(arrit))->nd_m1; __npy_i >= 0; __npy_i--) { if (((PyArrayIterObject *)(arrit))->coordinates [__npy_i] < ((PyArrayIterObject *)(arrit))->dims_m1[__npy_i ]) { ((PyArrayIterObject *)(arrit))->coordinates[__npy_i]++ ; ((PyArrayIterObject *)(arrit))->dataptr += ((PyArrayIterObject *)(arrit))->strides[__npy_i]; break; } else { ((PyArrayIterObject *)(arrit))->coordinates[__npy_i] = 0; ((PyArrayIterObject *)(arrit))->dataptr -= ((PyArrayIterObject *)(arrit))-> backstrides[__npy_i]; } } } } while (0); | |||
| 925 | if (arrit->index == arrit->size) { | |||
| 926 | PyArray_ITER_RESET(arrit)do { ((PyArrayIterObject *)(arrit))->index = 0; ((PyArrayIterObject *)(arrit))->dataptr = PyArray_BYTES(((PyArrayIterObject * )(arrit))->ao); memset(((PyArrayIterObject *)(arrit))-> coordinates, 0, (((PyArrayIterObject *)(arrit))->nd_m1+1)* sizeof(npy_intp)); } while (0); | |||
| 927 | } | |||
| 928 | } | |||
| 929 | retval = 0; | |||
| 930 | goto exit; | |||
| 931 | } | |||
| 932 | ||||
| 933 | while(selfit->index < selfit->size) { | |||
| 934 | copyswap(selfit->dataptr, arrit->dataptr, swap, self); | |||
| 935 | PyArray_ITER_NEXT(selfit)do { ((PyArrayIterObject *)(selfit))->index++; if (((PyArrayIterObject *)(selfit))->nd_m1 == 0) { do { (((PyArrayIterObject *)(selfit )))->dataptr += ((PyArrayIterObject *)(((PyArrayIterObject *)(selfit))))->strides[0]; (((PyArrayIterObject *)(selfit )))->coordinates[0]++; } while (0); } else if (((PyArrayIterObject *)(selfit))->contiguous) ((PyArrayIterObject *)(selfit))-> dataptr += PyArray_DESCR(((PyArrayIterObject *)(selfit))-> ao)->elsize; else if (((PyArrayIterObject *)(selfit))-> nd_m1 == 1) { do { if ((((PyArrayIterObject *)(selfit)))-> coordinates[1] < (((PyArrayIterObject *)(selfit)))->dims_m1 [1]) { (((PyArrayIterObject *)(selfit)))->coordinates[1]++ ; (((PyArrayIterObject *)(selfit)))->dataptr += (((PyArrayIterObject *)(selfit)))->strides[1]; } else { (((PyArrayIterObject * )(selfit)))->coordinates[1] = 0; (((PyArrayIterObject *)(selfit )))->coordinates[0]++; (((PyArrayIterObject *)(selfit)))-> dataptr += (((PyArrayIterObject *)(selfit)))->strides[0] - (((PyArrayIterObject *)(selfit)))->backstrides[1]; } } while (0); } else { int __npy_i; for (__npy_i=((PyArrayIterObject * )(selfit))->nd_m1; __npy_i >= 0; __npy_i--) { if (((PyArrayIterObject *)(selfit))->coordinates[__npy_i] < ((PyArrayIterObject *)(selfit))->dims_m1[__npy_i]) { ((PyArrayIterObject *)(selfit ))->coordinates[__npy_i]++; ((PyArrayIterObject *)(selfit) )->dataptr += ((PyArrayIterObject *)(selfit))->strides[ __npy_i]; break; } else { ((PyArrayIterObject *)(selfit))-> coordinates[__npy_i] = 0; ((PyArrayIterObject *)(selfit))-> dataptr -= ((PyArrayIterObject *)(selfit))->backstrides[__npy_i ]; } } } } while (0); | |||
| 936 | PyArray_ITER_NEXT(arrit)do { ((PyArrayIterObject *)(arrit))->index++; if (((PyArrayIterObject *)(arrit))->nd_m1 == 0) { do { (((PyArrayIterObject *)(arrit )))->dataptr += ((PyArrayIterObject *)(((PyArrayIterObject *)(arrit))))->strides[0]; (((PyArrayIterObject *)(arrit)) )->coordinates[0]++; } while (0); } else if (((PyArrayIterObject *)(arrit))->contiguous) ((PyArrayIterObject *)(arrit))-> dataptr += PyArray_DESCR(((PyArrayIterObject *)(arrit))->ao )->elsize; else if (((PyArrayIterObject *)(arrit))->nd_m1 == 1) { do { if ((((PyArrayIterObject *)(arrit)))->coordinates [1] < (((PyArrayIterObject *)(arrit)))->dims_m1[1]) { ( ((PyArrayIterObject *)(arrit)))->coordinates[1]++; (((PyArrayIterObject *)(arrit)))->dataptr += (((PyArrayIterObject *)(arrit)))-> strides[1]; } else { (((PyArrayIterObject *)(arrit)))->coordinates [1] = 0; (((PyArrayIterObject *)(arrit)))->coordinates[0]++ ; (((PyArrayIterObject *)(arrit)))->dataptr += (((PyArrayIterObject *)(arrit)))->strides[0] - (((PyArrayIterObject *)(arrit)) )->backstrides[1]; } } while (0); } else { int __npy_i; for (__npy_i=((PyArrayIterObject *)(arrit))->nd_m1; __npy_i >= 0; __npy_i--) { if (((PyArrayIterObject *)(arrit))->coordinates [__npy_i] < ((PyArrayIterObject *)(arrit))->dims_m1[__npy_i ]) { ((PyArrayIterObject *)(arrit))->coordinates[__npy_i]++ ; ((PyArrayIterObject *)(arrit))->dataptr += ((PyArrayIterObject *)(arrit))->strides[__npy_i]; break; } else { ((PyArrayIterObject *)(arrit))->coordinates[__npy_i] = 0; ((PyArrayIterObject *)(arrit))->dataptr -= ((PyArrayIterObject *)(arrit))-> backstrides[__npy_i]; } } } } while (0); | |||
| 937 | if (arrit->index == arrit->size) { | |||
| 938 | PyArray_ITER_RESET(arrit)do { ((PyArrayIterObject *)(arrit))->index = 0; ((PyArrayIterObject *)(arrit))->dataptr = PyArray_BYTES(((PyArrayIterObject * )(arrit))->ao); memset(((PyArrayIterObject *)(arrit))-> coordinates, 0, (((PyArrayIterObject *)(arrit))->nd_m1+1)* sizeof(npy_intp)); } while (0); | |||
| 939 | } | |||
| 940 | } | |||
| 941 | retval = 0; | |||
| 942 | ||||
| 943 | exit: | |||
| 944 | Py_XDECREF(selfit)_Py_XDECREF(((PyObject*)(selfit))); | |||
| 945 | Py_XDECREF(arrit)_Py_XDECREF(((PyObject*)(arrit))); | |||
| 946 | Py_XDECREF(arr)_Py_XDECREF(((PyObject*)(arr))); | |||
| 947 | return retval; | |||
| 948 | } | |||
| 949 | ||||
| 950 | static PyObject * | |||
| 951 | array_transpose_get(PyArrayObject *self) | |||
| 952 | { | |||
| 953 | return PyArray_Transpose(self, NULL((void*)0)); | |||
| 954 | } | |||
| 955 | ||||
| 956 | /* If this is None, no function call is made | |||
| 957 | --- default sub-class behavior | |||
| 958 | */ | |||
| 959 | static PyObject * | |||
| 960 | array_finalize_get(PyArrayObject *NPY_UNUSED(self)(__NPY_UNUSED_TAGGEDself) __attribute__ ((__unused__))) | |||
| 961 | { | |||
| 962 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 963 | } | |||
| 964 | ||||
| 965 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyGetSetDef array_getsetlist[] = { | |||
| 966 | {"ndim", | |||
| 967 | (getter)array_ndim_get, | |||
| 968 | NULL((void*)0), | |||
| 969 | NULL((void*)0), NULL((void*)0)}, | |||
| 970 | {"flags", | |||
| 971 | (getter)array_flags_get, | |||
| 972 | NULL((void*)0), | |||
| 973 | NULL((void*)0), NULL((void*)0)}, | |||
| 974 | {"shape", | |||
| 975 | (getter)array_shape_get, | |||
| 976 | (setter)array_shape_set, | |||
| 977 | NULL((void*)0), NULL((void*)0)}, | |||
| 978 | {"strides", | |||
| 979 | (getter)array_strides_get, | |||
| 980 | (setter)array_strides_set, | |||
| 981 | NULL((void*)0), NULL((void*)0)}, | |||
| 982 | {"data", | |||
| 983 | (getter)array_data_get, | |||
| 984 | (setter)array_data_set, | |||
| 985 | NULL((void*)0), NULL((void*)0)}, | |||
| 986 | {"itemsize", | |||
| 987 | (getter)array_itemsize_get, | |||
| 988 | NULL((void*)0), | |||
| 989 | NULL((void*)0), NULL((void*)0)}, | |||
| 990 | {"size", | |||
| 991 | (getter)array_size_get, | |||
| 992 | NULL((void*)0), | |||
| 993 | NULL((void*)0), NULL((void*)0)}, | |||
| 994 | {"nbytes", | |||
| 995 | (getter)array_nbytes_get, | |||
| 996 | NULL((void*)0), | |||
| 997 | NULL((void*)0), NULL((void*)0)}, | |||
| 998 | {"base", | |||
| 999 | (getter)array_base_get, | |||
| 1000 | NULL((void*)0), | |||
| 1001 | NULL((void*)0), NULL((void*)0)}, | |||
| 1002 | {"dtype", | |||
| 1003 | (getter)array_descr_get, | |||
| 1004 | (setter)array_descr_set, | |||
| 1005 | NULL((void*)0), NULL((void*)0)}, | |||
| 1006 | {"real", | |||
| 1007 | (getter)array_real_get, | |||
| 1008 | (setter)array_real_set, | |||
| 1009 | NULL((void*)0), NULL((void*)0)}, | |||
| 1010 | {"imag", | |||
| 1011 | (getter)array_imag_get, | |||
| 1012 | (setter)array_imag_set, | |||
| 1013 | NULL((void*)0), NULL((void*)0)}, | |||
| 1014 | {"flat", | |||
| 1015 | (getter)array_flat_get, | |||
| 1016 | (setter)array_flat_set, | |||
| 1017 | NULL((void*)0), NULL((void*)0)}, | |||
| 1018 | {"ctypes", | |||
| 1019 | (getter)array_ctypes_get, | |||
| 1020 | NULL((void*)0), | |||
| 1021 | NULL((void*)0), NULL((void*)0)}, | |||
| 1022 | {"T", | |||
| 1023 | (getter)array_transpose_get, | |||
| 1024 | NULL((void*)0), | |||
| 1025 | NULL((void*)0), NULL((void*)0)}, | |||
| 1026 | {"__array_interface__", | |||
| 1027 | (getter)array_interface_get, | |||
| 1028 | NULL((void*)0), | |||
| 1029 | NULL((void*)0), NULL((void*)0)}, | |||
| 1030 | {"__array_struct__", | |||
| 1031 | (getter)array_struct_get, | |||
| 1032 | NULL((void*)0), | |||
| 1033 | NULL((void*)0), NULL((void*)0)}, | |||
| 1034 | {"__array_priority__", | |||
| 1035 | (getter)array_priority_get, | |||
| 1036 | NULL((void*)0), | |||
| 1037 | NULL((void*)0), NULL((void*)0)}, | |||
| 1038 | {"__array_finalize__", | |||
| 1039 | (getter)array_finalize_get, | |||
| 1040 | NULL((void*)0), | |||
| 1041 | NULL((void*)0), NULL((void*)0)}, | |||
| 1042 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)}, /* Sentinel */ | |||
| 1043 | }; | |||
| 1044 | ||||
| 1045 | /****************** end of attribute get and set routines *******************/ |
| 1 | /* Array Descr Object */ | |||
| 2 | ||||
| 3 | #define PY_SSIZE_T_CLEAN | |||
| 4 | #include <Python.h> | |||
| 5 | #include "structmember.h" | |||
| 6 | ||||
| 7 | #define NPY_NO_DEPRECATED_API0x0000000E NPY_API_VERSION0x0000000E | |||
| 8 | #define _MULTIARRAYMODULE | |||
| 9 | #include "numpy/arrayobject.h" | |||
| 10 | #include "numpy/arrayscalars.h" | |||
| 11 | ||||
| 12 | #include "npy_config.h" | |||
| 13 | #include "npy_ctypes.h" | |||
| 14 | #include "npy_pycompat.h" | |||
| 15 | ||||
| 16 | #include "_datetime.h" | |||
| 17 | #include "common.h" | |||
| 18 | #include "templ_common.h" /* for npy_mul_with_overflow_intp */ | |||
| 19 | #include "descriptor.h" | |||
| 20 | #include "alloc.h" | |||
| 21 | #include "assert.h" | |||
| 22 | #include "npy_buffer.h" | |||
| 23 | ||||
| 24 | /* | |||
| 25 | * offset: A starting offset. | |||
| 26 | * alignment: A power-of-two alignment. | |||
| 27 | * | |||
| 28 | * This macro returns the smallest value >= 'offset' | |||
| 29 | * that is divisible by 'alignment'. Because 'alignment' | |||
| 30 | * is a power of two and integers are twos-complement, | |||
| 31 | * it is possible to use some simple bit-fiddling to do this. | |||
| 32 | */ | |||
| 33 | #define NPY_NEXT_ALIGNED_OFFSET(offset, alignment) \ | |||
| 34 | (((offset) + (alignment) - 1) & (-(alignment))) | |||
| 35 | ||||
| 36 | #ifndef PyDictProxy_Check | |||
| 37 | #define PyDictProxy_Check(obj) (Py_TYPE(obj)(((PyObject*)(obj))->ob_type) == &PyDictProxy_Type) | |||
| 38 | #endif | |||
| 39 | ||||
| 40 | static PyObject *typeDict = NULL((void*)0); /* Must be explicitly loaded */ | |||
| 41 | ||||
| 42 | static PyArray_Descr * | |||
| 43 | _try_convert_from_inherit_tuple(PyArray_Descr *type, PyObject *newobj); | |||
| 44 | ||||
| 45 | static PyArray_Descr * | |||
| 46 | _convert_from_any(PyObject *obj, int align); | |||
| 47 | ||||
| 48 | /* | |||
| 49 | * This function creates a dtype object when the object is a ctypes subclass. | |||
| 50 | * | |||
| 51 | * Returns `Py_NotImplemented` if the type is not a ctypes subclass. | |||
| 52 | */ | |||
| 53 | static PyArray_Descr * | |||
| 54 | _try_convert_from_ctypes_type(PyTypeObject *type) | |||
| 55 | { | |||
| 56 | PyObject *_numpy_dtype_ctypes; | |||
| 57 | PyObject *res; | |||
| 58 | ||||
| 59 | if (!npy_ctypes_check(type)) { | |||
| 60 | Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct)))); | |||
| 61 | return (PyArray_Descr *)Py_NotImplemented(&_Py_NotImplementedStruct); | |||
| 62 | } | |||
| 63 | ||||
| 64 | /* Call the python function of the same name. */ | |||
| 65 | _numpy_dtype_ctypes = PyImport_ImportModule("numpy.core._dtype_ctypes"); | |||
| 66 | if (_numpy_dtype_ctypes == NULL((void*)0)) { | |||
| 67 | return NULL((void*)0); | |||
| 68 | } | |||
| 69 | res = PyObject_CallMethod_PyObject_CallMethod_SizeT(_numpy_dtype_ctypes, "dtype_from_ctypes_type", "O", (PyObject *)type); | |||
| 70 | Py_DECREF(_numpy_dtype_ctypes)_Py_DECREF(((PyObject*)(_numpy_dtype_ctypes))); | |||
| 71 | if (res == NULL((void*)0)) { | |||
| 72 | return NULL((void*)0); | |||
| 73 | } | |||
| 74 | ||||
| 75 | /* | |||
| 76 | * sanity check that dtype_from_ctypes_type returned the right type, | |||
| 77 | * since getting it wrong would give segfaults. | |||
| 78 | */ | |||
| 79 | if (!PyObject_TypeCheck(res, &PyArrayDescr_Type)((((PyObject*)(res))->ob_type) == (&(*(PyTypeObject *) (&PyArrayDescr_TypeFull))) || PyType_IsSubtype((((PyObject *)(res))->ob_type), (&(*(PyTypeObject *)(&PyArrayDescr_TypeFull )))))) { | |||
| 80 | Py_DECREF(res)_Py_DECREF(((PyObject*)(res))); | |||
| 81 | PyErr_BadInternalCall()_PyErr_BadInternalCall("/tmp/pyrefcon/numpy/numpy/core/src/multiarray/descriptor.c" , 81); | |||
| 82 | return NULL((void*)0); | |||
| 83 | } | |||
| 84 | ||||
| 85 | return (PyArray_Descr *)res; | |||
| 86 | } | |||
| 87 | ||||
| 88 | static PyArray_Descr * | |||
| 89 | _convert_from_any(PyObject *obj, int align); | |||
| 90 | ||||
| 91 | /* | |||
| 92 | * This function creates a dtype object when the object has a "dtype" attribute, | |||
| 93 | * and it can be converted to a dtype object. | |||
| 94 | * | |||
| 95 | * Returns `Py_NotImplemented` if this is not possible. | |||
| 96 | * Currently the only failure mode for a NULL return is a RecursionError. | |||
| 97 | */ | |||
| 98 | static PyArray_Descr * | |||
| 99 | _try_convert_from_dtype_attr(PyObject *obj) | |||
| 100 | { | |||
| 101 | /* For arbitrary objects that have a "dtype" attribute */ | |||
| 102 | PyObject *dtypedescr = PyObject_GetAttrString(obj, "dtype"); | |||
| 103 | if (dtypedescr == NULL((void*)0)) { | |||
| 104 | /* | |||
| 105 | * This can be reached due to recursion limit being hit while fetching | |||
| 106 | * the attribute (tested for py3.7). This removes the custom message. | |||
| 107 | */ | |||
| 108 | goto fail; | |||
| 109 | } | |||
| 110 | ||||
| 111 | if (PyArray_DescrCheck(dtypedescr)((((PyObject*)(dtypedescr))->ob_type) == (&(*(PyTypeObject *)(&PyArrayDescr_TypeFull))) || PyType_IsSubtype((((PyObject *)(dtypedescr))->ob_type), (&(*(PyTypeObject *)(&PyArrayDescr_TypeFull )))))) { | |||
| 112 | /* The dtype attribute is already a valid descriptor */ | |||
| 113 | return (PyArray_Descr *)dtypedescr; | |||
| 114 | } | |||
| 115 | ||||
| 116 | if (Py_EnterRecursiveCall(((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from its " "`.dtype` attribute.")) | |||
| 117 | " while trying to convert the given data type from its "((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from its " "`.dtype` attribute.")) | |||
| 118 | "`.dtype` attribute.")((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from its " "`.dtype` attribute.")) != 0) { | |||
| 119 | Py_DECREF(dtypedescr)_Py_DECREF(((PyObject*)(dtypedescr))); | |||
| 120 | return NULL((void*)0); | |||
| 121 | } | |||
| 122 | ||||
| 123 | PyArray_Descr *newdescr = _convert_from_any(dtypedescr, 0); | |||
| 124 | Py_DECREF(dtypedescr)_Py_DECREF(((PyObject*)(dtypedescr))); | |||
| 125 | Py_LeaveRecursiveCall()do{ if((--(PyThreadState_Get()->recursion_depth) < (((_Py_CheckRecursionLimit ) > 200) ? ((_Py_CheckRecursionLimit) - 50) : (3 * ((_Py_CheckRecursionLimit ) >> 2))))) PyThreadState_Get()->overflowed = 0; } while (0); | |||
| 126 | if (newdescr == NULL((void*)0)) { | |||
| 127 | goto fail; | |||
| 128 | } | |||
| 129 | ||||
| 130 | /* Deprecated 2021-01-05, NumPy 1.21 */ | |||
| 131 | if (DEPRECATE("in the future the `.dtype` attribute of a given data"PyErr_WarnEx(PyExc_DeprecationWarning,"in the future the `.dtype` attribute of a given data" "type object must be a valid dtype instance. " "`data_type.dtype` may need to be coerced using " "`np.dtype(data_type.dtype)`. (Deprecated NumPy 1.20)",1) | |||
| 132 | "type object must be a valid dtype instance. "PyErr_WarnEx(PyExc_DeprecationWarning,"in the future the `.dtype` attribute of a given data" "type object must be a valid dtype instance. " "`data_type.dtype` may need to be coerced using " "`np.dtype(data_type.dtype)`. (Deprecated NumPy 1.20)",1) | |||
| 133 | "`data_type.dtype` may need to be coerced using "PyErr_WarnEx(PyExc_DeprecationWarning,"in the future the `.dtype` attribute of a given data" "type object must be a valid dtype instance. " "`data_type.dtype` may need to be coerced using " "`np.dtype(data_type.dtype)`. (Deprecated NumPy 1.20)",1) | |||
| 134 | "`np.dtype(data_type.dtype)`. (Deprecated NumPy 1.20)")PyErr_WarnEx(PyExc_DeprecationWarning,"in the future the `.dtype` attribute of a given data" "type object must be a valid dtype instance. " "`data_type.dtype` may need to be coerced using " "`np.dtype(data_type.dtype)`. (Deprecated NumPy 1.20)",1) < 0) { | |||
| 135 | Py_DECREF(newdescr)_Py_DECREF(((PyObject*)(newdescr))); | |||
| 136 | return NULL((void*)0); | |||
| 137 | } | |||
| 138 | ||||
| 139 | return newdescr; | |||
| 140 | ||||
| 141 | fail: | |||
| 142 | /* Ignore all but recursion errors, to give ctypes a full try. */ | |||
| 143 | if (!PyErr_ExceptionMatches(PyExc_RecursionError)) { | |||
| 144 | PyErr_Clear(); | |||
| 145 | Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct)))); | |||
| 146 | return (PyArray_Descr *)Py_NotImplemented(&_Py_NotImplementedStruct); | |||
| 147 | } | |||
| 148 | return NULL((void*)0); | |||
| 149 | } | |||
| 150 | ||||
| 151 | /* Expose to another file with a prefixed name */ | |||
| 152 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr * | |||
| 153 | _arraydescr_try_convert_from_dtype_attr(PyObject *obj) | |||
| 154 | { | |||
| 155 | return _try_convert_from_dtype_attr(obj); | |||
| 156 | } | |||
| 157 | ||||
| 158 | /* | |||
| 159 | * Sets the global typeDict object, which is a dictionary mapping | |||
| 160 | * dtype names to numpy scalar types. | |||
| 161 | */ | |||
| 162 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | |||
| 163 | array_set_typeDict(PyObject *NPY_UNUSED(ignored)(__NPY_UNUSED_TAGGEDignored) __attribute__ ((__unused__)), PyObject *args) | |||
| 164 | { | |||
| 165 | PyObject *dict; | |||
| 166 | ||||
| 167 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "O:set_typeDict", &dict)) { | |||
| 168 | return NULL((void*)0); | |||
| 169 | } | |||
| 170 | /* Decrement old reference (if any)*/ | |||
| 171 | Py_XDECREF(typeDict)_Py_XDECREF(((PyObject*)(typeDict))); | |||
| 172 | typeDict = dict; | |||
| 173 | /* Create an internal reference to it */ | |||
| 174 | Py_INCREF(dict)_Py_INCREF(((PyObject*)(dict))); | |||
| 175 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 176 | } | |||
| 177 | ||||
| 178 | #define _chk_byteorder(arg) (arg == '>' || arg == '<' || \ | |||
| 179 | arg == '|' || arg == '=') | |||
| 180 | ||||
| 181 | static int | |||
| 182 | _check_for_commastring(const char *type, Py_ssize_t len) | |||
| 183 | { | |||
| 184 | Py_ssize_t i; | |||
| 185 | int sqbracket; | |||
| 186 | ||||
| 187 | /* Check for ints at start of string */ | |||
| 188 | if ((type[0] >= '0' | |||
| 189 | && type[0] <= '9') | |||
| 190 | || ((len > 1) | |||
| 191 | && _chk_byteorder(type[0]) | |||
| 192 | && (type[1] >= '0' | |||
| 193 | && type[1] <= '9'))) { | |||
| 194 | return 1; | |||
| 195 | } | |||
| 196 | /* Check for empty tuple */ | |||
| 197 | if (((len > 1) | |||
| 198 | && (type[0] == '(' | |||
| 199 | && type[1] == ')')) | |||
| 200 | || ((len > 3) | |||
| 201 | && _chk_byteorder(type[0]) | |||
| 202 | && (type[1] == '(' | |||
| 203 | && type[2] == ')'))) { | |||
| 204 | return 1; | |||
| 205 | } | |||
| 206 | /* | |||
| 207 | * Check for presence of commas outside square [] brackets. This | |||
| 208 | * allows commas inside of [], for parameterized dtypes to use. | |||
| 209 | */ | |||
| 210 | sqbracket = 0; | |||
| 211 | for (i = 0; i < len; i++) { | |||
| 212 | switch (type[i]) { | |||
| 213 | case ',': | |||
| 214 | if (sqbracket == 0) { | |||
| 215 | return 1; | |||
| 216 | } | |||
| 217 | break; | |||
| 218 | case '[': | |||
| 219 | ++sqbracket; | |||
| 220 | break; | |||
| 221 | case ']': | |||
| 222 | --sqbracket; | |||
| 223 | break; | |||
| 224 | } | |||
| 225 | } | |||
| 226 | return 0; | |||
| 227 | } | |||
| 228 | ||||
| 229 | #undef _chk_byteorder | |||
| 230 | ||||
| 231 | static int | |||
| 232 | is_datetime_typestr(char const *type, Py_ssize_t len) | |||
| 233 | { | |||
| 234 | if (len < 2) { | |||
| 235 | return 0; | |||
| 236 | } | |||
| 237 | if (type[1] == '8' && (type[0] == 'M' || type[0] == 'm')) { | |||
| 238 | return 1; | |||
| 239 | } | |||
| 240 | if (len < 10) { | |||
| 241 | return 0; | |||
| 242 | } | |||
| 243 | if (strncmp(type, "datetime64", 10) == 0) { | |||
| 244 | return 1; | |||
| 245 | } | |||
| 246 | if (len < 11) { | |||
| 247 | return 0; | |||
| 248 | } | |||
| 249 | if (strncmp(type, "timedelta64", 11) == 0) { | |||
| 250 | return 1; | |||
| 251 | } | |||
| 252 | return 0; | |||
| 253 | } | |||
| 254 | ||||
| 255 | static PyArray_Descr * | |||
| 256 | _convert_from_tuple(PyObject *obj, int align) | |||
| 257 | { | |||
| 258 | if (PyTuple_GET_SIZE(obj)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(obj))))-> ob_size) != 2) { | |||
| 259 | PyErr_Format(PyExc_TypeError, | |||
| 260 | "Tuple must have size 2, but has size %zd", | |||
| 261 | PyTuple_GET_SIZE(obj)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(obj))))-> ob_size)); | |||
| 262 | return NULL((void*)0); | |||
| 263 | } | |||
| 264 | PyArray_Descr *type = _convert_from_any(PyTuple_GET_ITEM(obj, 0)((((void) (0)), (PyTupleObject *)(obj))->ob_item[0]), align); | |||
| 265 | if (type == NULL((void*)0)) { | |||
| 266 | return NULL((void*)0); | |||
| 267 | } | |||
| 268 | PyObject *val = PyTuple_GET_ITEM(obj,1)((((void) (0)), (PyTupleObject *)(obj))->ob_item[1]); | |||
| 269 | /* try to interpret next item as a type */ | |||
| 270 | PyArray_Descr *res = _try_convert_from_inherit_tuple(type, val); | |||
| 271 | if ((PyObject *)res != Py_NotImplemented(&_Py_NotImplementedStruct)) { | |||
| 272 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | |||
| 273 | return res; | |||
| 274 | } | |||
| 275 | Py_DECREF(res)_Py_DECREF(((PyObject*)(res))); | |||
| 276 | /* | |||
| 277 | * We get here if _try_convert_from_inherit_tuple failed without crashing | |||
| 278 | */ | |||
| 279 | if (PyDataType_ISUNSIZED(type)((type)->elsize == 0 && !(((PyArray_Descr *)(type) )->names != ((void*)0)))) { | |||
| 280 | /* interpret next item as a typesize */ | |||
| 281 | int itemsize = PyArray_PyIntAsInt(PyTuple_GET_ITEM(obj,1)((((void) (0)), (PyTupleObject *)(obj))->ob_item[1])); | |||
| 282 | ||||
| 283 | if (error_converting(itemsize)(((itemsize) == -1) && PyErr_Occurred())) { | |||
| 284 | PyErr_SetString(PyExc_ValueError, | |||
| 285 | "invalid itemsize in generic type tuple"); | |||
| 286 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | |||
| 287 | return NULL((void*)0); | |||
| 288 | } | |||
| 289 | PyArray_DESCR_REPLACE(type)do { PyArray_Descr *_new_; _new_ = PyArray_DescrNew(type); _Py_XDECREF (((PyObject*)(type))); type = _new_; } while(0); | |||
| 290 | if (type == NULL((void*)0)) { | |||
| 291 | return NULL((void*)0); | |||
| 292 | } | |||
| 293 | if (type->type_num == NPY_UNICODE) { | |||
| 294 | type->elsize = itemsize << 2; | |||
| 295 | } | |||
| 296 | else { | |||
| 297 | type->elsize = itemsize; | |||
| 298 | } | |||
| 299 | return type; | |||
| 300 | } | |||
| 301 | else if (type->metadata && (PyDict_Check(val)((((((PyObject*)(val))->ob_type))->tp_flags & ((1UL << 29))) != 0) || PyDictProxy_Check(val))) { | |||
| 302 | /* Assume it's a metadata dictionary */ | |||
| 303 | if (PyDict_Merge(type->metadata, val, 0) == -1) { | |||
| 304 | Py_DECREF(type)_Py_DECREF(((PyObject*)(type))); | |||
| 305 | return NULL((void*)0); | |||
| 306 | } | |||
| 307 | return type; | |||
| 308 | } | |||
| 309 | else { | |||
| 310 | /* | |||
| 311 | * interpret next item as shape (if it's a tuple) | |||
| 312 | * and reset the type to NPY_VOID with | |||
| 313 | * a new fields attribute. | |||
| 314 | */ | |||
| 315 | PyArray_Dims shape = {NULL((void*)0), -1}; | |||
| 316 | if (!(PyArray_IntpConverter(val, &shape)) || (shape.len > NPY_MAXDIMS32)) { | |||
| 317 | PyErr_SetString(PyExc_ValueError, | |||
| 318 | "invalid shape in fixed-type tuple."); | |||
| 319 | goto fail; | |||
| 320 | } | |||
| 321 | /* if (type, ()) was given it is equivalent to type... */ | |||
| 322 | if (shape.len == 0 && PyTuple_Check(val)((((((PyObject*)(val))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | |||
| 323 | npy_free_cache_dim_obj(shape); | |||
| 324 | return type; | |||
| 325 | } | |||
| 326 | /* (type, 1) use to be equivalent to type, but is deprecated */ | |||
| 327 | if (shape.len == 1 | |||
| 328 | && shape.ptr[0] == 1 | |||
| 329 | && PyNumber_Check(val)) { | |||
| 330 | /* 2019-05-20, 1.17 */ | |||
| 331 | if (DEPRECATE_FUTUREWARNING(PyErr_WarnEx(PyExc_FutureWarning,"Passing (type, 1) or '1type' as a synonym of type is " "deprecated; in a future version of numpy, it will be " "understood as (type, (1,)) / '(1,)type'." ,1) | |||
| 332 | "Passing (type, 1) or '1type' as a synonym of type is "PyErr_WarnEx(PyExc_FutureWarning,"Passing (type, 1) or '1type' as a synonym of type is " "deprecated; in a future version of numpy, it will be " "understood as (type, (1,)) / '(1,)type'." ,1) | |||
| 333 | "deprecated; in a future version of numpy, it will be "PyErr_WarnEx(PyExc_FutureWarning,"Passing (type, 1) or '1type' as a synonym of type is " "deprecated; in a future version of numpy, it will be " "understood as (type, (1,)) / '(1,)type'." ,1) | |||
| 334 | "understood as (type, (1,)) / '(1,)type'.")PyErr_WarnEx(PyExc_FutureWarning,"Passing (type, 1) or '1type' as a synonym of type is " "deprecated; in a future version of numpy, it will be " "understood as (type, (1,)) / '(1,)type'." ,1) < 0) { | |||
| 335 | goto fail; | |||
| 336 | } | |||
| 337 | npy_free_cache_dim_obj(shape); | |||
| 338 | return type; | |||
| 339 | } | |||
| 340 | ||||
| 341 | /* validate and set shape */ | |||
| 342 | for (int i=0; i < shape.len; i++) { | |||
| 343 | if (shape.ptr[i] < 0) { | |||
| 344 | PyErr_SetString(PyExc_ValueError, | |||
| 345 | "invalid shape in fixed-type tuple: " | |||
| 346 | "dimension smaller then zero."); | |||
| 347 | goto fail; | |||
| 348 | } | |||
| 349 | if (shape.ptr[i] > NPY_MAX_INT2147483647) { | |||
| 350 | PyErr_SetString(PyExc_ValueError, | |||
| 351 | "invalid shape in fixed-type tuple: " | |||
| 352 | "dimension does not fit into a C int."); | |||
| 353 | goto fail; | |||
| 354 | } | |||
| 355 | } | |||
| 356 | npy_intp items = PyArray_OverflowMultiplyList(shape.ptr, shape.len); | |||
| 357 | int overflowed; | |||
| 358 | int nbytes; | |||
| 359 | if (items < 0 || items > NPY_MAX_INT2147483647) { | |||
| 360 | overflowed = 1; | |||
| 361 | } | |||
| 362 | else { | |||
| 363 | overflowed = npy_mul_with_overflow_int( | |||
| 364 | &nbytes, type->elsize, (int) items); | |||
| 365 | } | |||
| 366 | if (overflowed) { | |||
| 367 | PyErr_SetString(PyExc_ValueError, | |||
| 368 | "invalid shape in fixed-type tuple: dtype size in " | |||
| 369 | "bytes must fit into a C int."); | |||
| 370 | goto fail; | |||
| 371 | } | |||
| 372 | PyArray_Descr *newdescr = PyArray_DescrNewFromType(NPY_VOID); | |||
| 373 | if (newdescr == NULL((void*)0)) { | |||
| 374 | goto fail; | |||
| 375 | } | |||
| 376 | newdescr->elsize = nbytes; | |||
| 377 | newdescr->subarray = PyArray_mallocPyMem_RawMalloc(sizeof(PyArray_ArrayDescr)); | |||
| 378 | if (newdescr->subarray == NULL((void*)0)) { | |||
| 379 | Py_DECREF(newdescr)_Py_DECREF(((PyObject*)(newdescr))); | |||
| 380 | PyErr_NoMemory(); | |||
| 381 | goto fail; | |||
| 382 | } | |||
| 383 | newdescr->flags = type->flags; | |||
| 384 | newdescr->alignment = type->alignment; | |||
| 385 | newdescr->subarray->base = type; | |||
| 386 | type = NULL((void*)0); | |||
| 387 | Py_XDECREF(newdescr->fields)_Py_XDECREF(((PyObject*)(newdescr->fields))); | |||
| 388 | Py_XDECREF(newdescr->names)_Py_XDECREF(((PyObject*)(newdescr->names))); | |||
| 389 | newdescr->fields = NULL((void*)0); | |||
| 390 | newdescr->names = NULL((void*)0); | |||
| 391 | ||||
| 392 | /* | |||
| 393 | * Create a new subarray->shape tuple (it can be an arbitrary | |||
| 394 | * sequence of integer like objects, neither of which is safe. | |||
| 395 | */ | |||
| 396 | newdescr->subarray->shape = PyTuple_New(shape.len); | |||
| 397 | if (newdescr->subarray->shape == NULL((void*)0)) { | |||
| 398 | Py_DECREF(newdescr)_Py_DECREF(((PyObject*)(newdescr))); | |||
| 399 | goto fail; | |||
| 400 | } | |||
| 401 | for (int i=0; i < shape.len; i++) { | |||
| 402 | PyTuple_SET_ITEM(newdescr->subarray->shape, i,PyTuple_SetItem(newdescr->subarray->shape, i, PyLong_FromLong ((long)shape.ptr[i])) | |||
| 403 | PyLong_FromLong((long)shape.ptr[i]))PyTuple_SetItem(newdescr->subarray->shape, i, PyLong_FromLong ((long)shape.ptr[i])); | |||
| 404 | ||||
| 405 | if (PyTuple_GET_ITEM(newdescr->subarray->shape, i)((((void) (0)), (PyTupleObject *)(newdescr->subarray->shape ))->ob_item[i]) == NULL((void*)0)) { | |||
| 406 | Py_DECREF(newdescr)_Py_DECREF(((PyObject*)(newdescr))); | |||
| 407 | goto fail; | |||
| 408 | } | |||
| 409 | } | |||
| 410 | ||||
| 411 | npy_free_cache_dim_obj(shape); | |||
| 412 | return newdescr; | |||
| 413 | ||||
| 414 | fail: | |||
| 415 | Py_XDECREF(type)_Py_XDECREF(((PyObject*)(type))); | |||
| 416 | npy_free_cache_dim_obj(shape); | |||
| 417 | return NULL((void*)0); | |||
| 418 | } | |||
| 419 | } | |||
| 420 | ||||
| 421 | /* | |||
| 422 | * obj is a list. Each item is a tuple with | |||
| 423 | * | |||
| 424 | * (field-name, data-type (either a list or a string), and an optional | |||
| 425 | * shape parameter). | |||
| 426 | * | |||
| 427 | * field-name can be a string or a 2-tuple | |||
| 428 | * data-type can now be a list, string, or 2-tuple | |||
| 429 | * (string, metadata dictionary) | |||
| 430 | */ | |||
| 431 | static PyArray_Descr * | |||
| 432 | _convert_from_array_descr(PyObject *obj, int align) | |||
| 433 | { | |||
| 434 | int n = PyList_GET_SIZE(obj)(((void) (0)), (((PyVarObject*)(obj))->ob_size)); | |||
| 435 | PyObject *nameslist = PyTuple_New(n); | |||
| 436 | if (!nameslist) { | |||
| 437 | return NULL((void*)0); | |||
| 438 | } | |||
| 439 | ||||
| 440 | /* Types with fields need the Python C API for field access */ | |||
| 441 | char dtypeflags = NPY_NEEDS_PYAPI0x10; | |||
| 442 | int maxalign = 0; | |||
| 443 | int totalsize = 0; | |||
| 444 | PyObject *fields = PyDict_New(); | |||
| 445 | if (!fields) { | |||
| 446 | return NULL((void*)0); | |||
| 447 | } | |||
| 448 | for (int i = 0; i < n; i++) { | |||
| 449 | PyObject *item = PyList_GET_ITEM(obj, i)(((PyListObject *)(obj))->ob_item[i]); | |||
| 450 | if (!PyTuple_Check(item)((((((PyObject*)(item))->ob_type))->tp_flags & ((1UL << 26))) != 0) || (PyTuple_GET_SIZE(item)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(item))))-> ob_size) < 2)) { | |||
| 451 | PyErr_Format(PyExc_TypeError, | |||
| 452 | "Field elements must be 2- or 3-tuples, got '%R'", | |||
| 453 | item); | |||
| 454 | goto fail; | |||
| 455 | } | |||
| 456 | PyObject *name = PyTuple_GET_ITEM(item, 0)((((void) (0)), (PyTupleObject *)(item))->ob_item[0]); | |||
| 457 | PyObject *title; | |||
| 458 | if (PyUnicode_Check(name)((((((PyObject*)(name))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 459 | title = NULL((void*)0); | |||
| 460 | } | |||
| 461 | else if (PyTuple_Check(name)((((((PyObject*)(name))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | |||
| 462 | if (PyTuple_GET_SIZE(name)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(name))))-> ob_size) != 2) { | |||
| 463 | PyErr_Format(PyExc_TypeError, | |||
| 464 | "If a tuple, the first element of a field tuple must have " | |||
| 465 | "two elements, not %zd", | |||
| 466 | PyTuple_GET_SIZE(name)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(name))))-> ob_size)); | |||
| 467 | goto fail; | |||
| 468 | } | |||
| 469 | title = PyTuple_GET_ITEM(name, 0)((((void) (0)), (PyTupleObject *)(name))->ob_item[0]); | |||
| 470 | name = PyTuple_GET_ITEM(name, 1)((((void) (0)), (PyTupleObject *)(name))->ob_item[1]); | |||
| 471 | if (!PyUnicode_Check(name)((((((PyObject*)(name))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 472 | PyErr_SetString(PyExc_TypeError, "Field name must be a str"); | |||
| 473 | goto fail; | |||
| 474 | } | |||
| 475 | } | |||
| 476 | else { | |||
| 477 | PyErr_SetString(PyExc_TypeError, | |||
| 478 | "First element of field tuple is " | |||
| 479 | "neither a tuple nor str"); | |||
| 480 | goto fail; | |||
| 481 | } | |||
| 482 | ||||
| 483 | /* Insert name into nameslist */ | |||
| 484 | Py_INCREF(name)_Py_INCREF(((PyObject*)(name))); | |||
| 485 | ||||
| 486 | if (PyUnicode_GetLength(name) == 0) { | |||
| 487 | Py_DECREF(name)_Py_DECREF(((PyObject*)(name))); | |||
| 488 | if (title == NULL((void*)0)) { | |||
| 489 | name = PyUnicode_FromFormat("f%d", i); | |||
| 490 | if (name == NULL((void*)0)) { | |||
| 491 | goto fail; | |||
| 492 | } | |||
| 493 | } | |||
| 494 | /* On Py3, allow only non-empty Unicode strings as field names */ | |||
| 495 | else if (PyUnicode_Check(title)((((((PyObject*)(title))->ob_type))->tp_flags & ((1UL << 28))) != 0) && PyUnicode_GetLength(title) > 0) { | |||
| 496 | name = title; | |||
| 497 | Py_INCREF(name)_Py_INCREF(((PyObject*)(name))); | |||
| 498 | } | |||
| 499 | else { | |||
| 500 | PyErr_SetString(PyExc_TypeError, "Field titles must be non-empty strings"); | |||
| 501 | goto fail; | |||
| 502 | } | |||
| 503 | } | |||
| 504 | PyTuple_SET_ITEM(nameslist, i, name)PyTuple_SetItem(nameslist, i, name); | |||
| 505 | ||||
| 506 | /* Process rest */ | |||
| 507 | PyArray_Descr *conv; | |||
| 508 | if (PyTuple_GET_SIZE(item)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(item))))-> ob_size) == 2) { | |||
| 509 | conv = _convert_from_any(PyTuple_GET_ITEM(item, 1)((((void) (0)), (PyTupleObject *)(item))->ob_item[1]), align); | |||
| 510 | if (conv == NULL((void*)0)) { | |||
| 511 | goto fail; | |||
| 512 | } | |||
| 513 | } | |||
| 514 | else if (PyTuple_GET_SIZE(item)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(item))))-> ob_size) == 3) { | |||
| 515 | PyObject *newobj = PyTuple_GetSlice(item, 1, 3); | |||
| 516 | conv = _convert_from_any(newobj, align); | |||
| 517 | Py_DECREF(newobj)_Py_DECREF(((PyObject*)(newobj))); | |||
| 518 | if (conv == NULL((void*)0)) { | |||
| 519 | goto fail; | |||
| 520 | } | |||
| 521 | } | |||
| 522 | else { | |||
| 523 | PyErr_Format(PyExc_TypeError, | |||
| 524 | "Field elements must be tuples with at most 3 elements, got '%R'", item); | |||
| 525 | goto fail; | |||
| 526 | } | |||
| 527 | if ((PyDict_GetItemWithError(fields, name) != NULL((void*)0)) | |||
| ||||
| 528 | || (title | |||
| 529 | && PyUnicode_Check(title)((((((PyObject*)(title))->ob_type))->tp_flags & ((1UL << 28))) != 0) | |||
| 530 | && (PyDict_GetItemWithError(fields, title) != NULL((void*)0)))) { | |||
| 531 | PyErr_Format(PyExc_ValueError, | |||
| 532 | "field %R occurs more than once", name); | |||
| 533 | Py_DECREF(conv)_Py_DECREF(((PyObject*)(conv))); | |||
| 534 | goto fail; | |||
| 535 | } | |||
| 536 | else if (PyErr_Occurred()) { | |||
| 537 | /* Dict lookup crashed */ | |||
| 538 | Py_DECREF(conv)_Py_DECREF(((PyObject*)(conv))); | |||
| 539 | goto fail; | |||
| 540 | } | |||
| 541 | dtypeflags |= (conv->flags & NPY_FROM_FIELDS(0x08 | 0x02 | 0x01 | 0x10)); | |||
| 542 | if (align) { | |||
| 543 | int _align = conv->alignment; | |||
| 544 | if (_align > 1) { | |||
| 545 | totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, _align); | |||
| 546 | } | |||
| 547 | maxalign = PyArray_MAX(maxalign, _align)(((maxalign)>(_align))?(maxalign):(_align)); | |||
| 548 | } | |||
| 549 | PyObject *tup = PyTuple_New((title == NULL((void*)0) ? 2 : 3)); | |||
| 550 | if (tup == NULL((void*)0)) { | |||
| 551 | goto fail; | |||
| 552 | } | |||
| 553 | PyTuple_SET_ITEM(tup, 0, (PyObject *)conv)PyTuple_SetItem(tup, 0, (PyObject *)conv); | |||
| 554 | PyTuple_SET_ITEM(tup, 1, PyLong_FromLong((long) totalsize))PyTuple_SetItem(tup, 1, PyLong_FromLong((long) totalsize)); | |||
| 555 | ||||
| 556 | /* | |||
| 557 | * Title can be "meta-data". Only insert it | |||
| 558 | * into the fields dictionary if it is a string | |||
| 559 | * and if it is not the same as the name. | |||
| 560 | */ | |||
| 561 | if (title != NULL((void*)0)) { | |||
| 562 | Py_INCREF(title)_Py_INCREF(((PyObject*)(title))); | |||
| 563 | PyTuple_SET_ITEM(tup, 2, title)PyTuple_SetItem(tup, 2, title); | |||
| 564 | if (PyDict_SetItem(fields, name, tup) < 0) { | |||
| 565 | goto fail; | |||
| 566 | } | |||
| 567 | if (PyUnicode_Check(title)((((((PyObject*)(title))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 568 | PyObject *existing = PyDict_GetItemWithError(fields, title); | |||
| 569 | if (existing == NULL((void*)0) && PyErr_Occurred()) { | |||
| 570 | goto fail; | |||
| 571 | } | |||
| 572 | if (existing != NULL((void*)0)) { | |||
| 573 | PyErr_SetString(PyExc_ValueError, | |||
| 574 | "title already used as a name or title."); | |||
| 575 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 576 | goto fail; | |||
| 577 | } | |||
| 578 | if (PyDict_SetItem(fields, title, tup) < 0) { | |||
| 579 | goto fail; | |||
| 580 | } | |||
| 581 | } | |||
| 582 | } | |||
| 583 | else { | |||
| 584 | if (PyDict_SetItem(fields, name, tup) < 0) { | |||
| 585 | goto fail; | |||
| 586 | } | |||
| 587 | } | |||
| 588 | ||||
| 589 | totalsize += conv->elsize; | |||
| 590 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 591 | } | |||
| 592 | ||||
| 593 | if (maxalign > 1) { | |||
| 594 | totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, maxalign); | |||
| 595 | } | |||
| 596 | ||||
| 597 | PyArray_Descr *new = PyArray_DescrNewFromType(NPY_VOID); | |||
| 598 | if (new == NULL((void*)0)) { | |||
| 599 | Py_XDECREF(fields)_Py_XDECREF(((PyObject*)(fields))); | |||
| 600 | Py_XDECREF(nameslist)_Py_XDECREF(((PyObject*)(nameslist))); | |||
| 601 | return NULL((void*)0); | |||
| 602 | } | |||
| 603 | new->fields = fields; | |||
| 604 | new->names = nameslist; | |||
| 605 | new->elsize = totalsize; | |||
| 606 | new->flags = dtypeflags; | |||
| 607 | ||||
| 608 | /* Structured arrays get a sticky aligned bit */ | |||
| 609 | if (align) { | |||
| 610 | new->flags |= NPY_ALIGNED_STRUCT0x80; | |||
| 611 | new->alignment = maxalign; | |||
| 612 | } | |||
| 613 | return new; | |||
| 614 | ||||
| 615 | fail: | |||
| 616 | Py_DECREF(fields)_Py_DECREF(((PyObject*)(fields))); | |||
| 617 | Py_DECREF(nameslist)_Py_DECREF(((PyObject*)(nameslist))); | |||
| 618 | return NULL((void*)0); | |||
| 619 | ||||
| 620 | } | |||
| 621 | ||||
| 622 | /* | |||
| 623 | * a list specifying a data-type can just be | |||
| 624 | * a list of formats. The names for the fields | |||
| 625 | * will default to f0, f1, f2, and so forth. | |||
| 626 | */ | |||
| 627 | static PyArray_Descr * | |||
| 628 | _convert_from_list(PyObject *obj, int align) | |||
| 629 | { | |||
| 630 | int n = PyList_GET_SIZE(obj)(((void) (0)), (((PyVarObject*)(obj))->ob_size)); | |||
| 631 | /* | |||
| 632 | * Ignore any empty string at end which _internal._commastring | |||
| 633 | * can produce | |||
| 634 | */ | |||
| 635 | PyObject *last_item = PyList_GET_ITEM(obj, n-1)(((PyListObject *)(obj))->ob_item[n-1]); | |||
| 636 | if (PyUnicode_Check(last_item)((((((PyObject*)(last_item))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 637 | Py_ssize_t s = PySequence_Size(last_item); | |||
| 638 | if (s < 0) { | |||
| 639 | return NULL((void*)0); | |||
| 640 | } | |||
| 641 | if (s == 0) { | |||
| 642 | n = n - 1; | |||
| 643 | } | |||
| 644 | } | |||
| 645 | if (n == 0) { | |||
| 646 | PyErr_SetString(PyExc_ValueError, "Expected at least one field name"); | |||
| 647 | return NULL((void*)0); | |||
| 648 | } | |||
| 649 | PyObject *nameslist = PyTuple_New(n); | |||
| 650 | if (!nameslist) { | |||
| 651 | return NULL((void*)0); | |||
| 652 | } | |||
| 653 | PyObject *fields = PyDict_New(); | |||
| 654 | if (!fields) { | |||
| 655 | Py_DECREF(nameslist)_Py_DECREF(((PyObject*)(nameslist))); | |||
| 656 | return NULL((void*)0); | |||
| 657 | } | |||
| 658 | ||||
| 659 | /* Types with fields need the Python C API for field access */ | |||
| 660 | char dtypeflags = NPY_NEEDS_PYAPI0x10; | |||
| 661 | int maxalign = 0; | |||
| 662 | int totalsize = 0; | |||
| 663 | for (int i = 0; i < n; i++) { | |||
| 664 | PyArray_Descr *conv = _convert_from_any( | |||
| 665 | PyList_GET_ITEM(obj, i)(((PyListObject *)(obj))->ob_item[i]), align); | |||
| 666 | if (conv == NULL((void*)0)) { | |||
| 667 | goto fail; | |||
| 668 | } | |||
| 669 | dtypeflags |= (conv->flags & NPY_FROM_FIELDS(0x08 | 0x02 | 0x01 | 0x10)); | |||
| 670 | if (align) { | |||
| 671 | int _align = conv->alignment; | |||
| 672 | if (_align > 1) { | |||
| 673 | totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, _align); | |||
| 674 | } | |||
| 675 | maxalign = PyArray_MAX(maxalign, _align)(((maxalign)>(_align))?(maxalign):(_align)); | |||
| 676 | } | |||
| 677 | PyObject *size_obj = PyLong_FromLong((long) totalsize); | |||
| 678 | if (!size_obj) { | |||
| 679 | Py_DECREF(conv)_Py_DECREF(((PyObject*)(conv))); | |||
| 680 | goto fail; | |||
| 681 | } | |||
| 682 | PyObject *tup = PyTuple_New(2); | |||
| 683 | if (!tup) { | |||
| 684 | Py_DECREF(size_obj)_Py_DECREF(((PyObject*)(size_obj))); | |||
| 685 | Py_DECREF(conv)_Py_DECREF(((PyObject*)(conv))); | |||
| 686 | goto fail; | |||
| 687 | } | |||
| 688 | PyTuple_SET_ITEM(tup, 0, (PyObject *)conv)PyTuple_SetItem(tup, 0, (PyObject *)conv); | |||
| 689 | PyTuple_SET_ITEM(tup, 1, size_obj)PyTuple_SetItem(tup, 1, size_obj); | |||
| 690 | PyObject *key = PyUnicode_FromFormat("f%d", i); | |||
| 691 | if (!key) { | |||
| 692 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 693 | goto fail; | |||
| 694 | } | |||
| 695 | /* steals a reference to key */ | |||
| 696 | PyTuple_SET_ITEM(nameslist, i, key)PyTuple_SetItem(nameslist, i, key); | |||
| 697 | int ret = PyDict_SetItem(fields, key, tup); | |||
| 698 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 699 | if (ret < 0) { | |||
| 700 | goto fail; | |||
| 701 | } | |||
| 702 | totalsize += conv->elsize; | |||
| 703 | } | |||
| 704 | PyArray_Descr *new = PyArray_DescrNewFromType(NPY_VOID); | |||
| 705 | new->fields = fields; | |||
| 706 | new->names = nameslist; | |||
| 707 | new->flags = dtypeflags; | |||
| 708 | if (maxalign > 1) { | |||
| 709 | totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, maxalign); | |||
| 710 | } | |||
| 711 | /* Structured arrays get a sticky aligned bit */ | |||
| 712 | if (align) { | |||
| 713 | new->flags |= NPY_ALIGNED_STRUCT0x80; | |||
| 714 | new->alignment = maxalign; | |||
| 715 | } | |||
| 716 | new->elsize = totalsize; | |||
| 717 | return new; | |||
| 718 | ||||
| 719 | fail: | |||
| 720 | Py_DECREF(nameslist)_Py_DECREF(((PyObject*)(nameslist))); | |||
| 721 | Py_DECREF(fields)_Py_DECREF(((PyObject*)(fields))); | |||
| 722 | return NULL((void*)0); | |||
| 723 | } | |||
| 724 | ||||
| 725 | ||||
| 726 | /* | |||
| 727 | * comma-separated string | |||
| 728 | * this is the format developed by the numarray records module and implemented | |||
| 729 | * by the format parser in that module this is an alternative implementation | |||
| 730 | * found in the _internal.py file patterned after that one -- the approach is | |||
| 731 | * to try to convert to a list (with tuples if any repeat information is | |||
| 732 | * present) and then call the _convert_from_list) | |||
| 733 | * | |||
| 734 | * TODO: Calling Python from C like this in critical-path code is not | |||
| 735 | * a good idea. This should all be converted to C code. | |||
| 736 | */ | |||
| 737 | static PyArray_Descr * | |||
| 738 | _convert_from_commastring(PyObject *obj, int align) | |||
| 739 | { | |||
| 740 | PyObject *listobj; | |||
| 741 | PyArray_Descr *res; | |||
| 742 | PyObject *_numpy_internal; | |||
| 743 | assert(PyUnicode_Check(obj))((void) (0)); | |||
| 744 | _numpy_internal = PyImport_ImportModule("numpy.core._internal"); | |||
| 745 | if (_numpy_internal == NULL((void*)0)) { | |||
| 746 | return NULL((void*)0); | |||
| 747 | } | |||
| 748 | listobj = PyObject_CallMethod_PyObject_CallMethod_SizeT(_numpy_internal, "_commastring", "O", obj); | |||
| 749 | Py_DECREF(_numpy_internal)_Py_DECREF(((PyObject*)(_numpy_internal))); | |||
| 750 | if (listobj == NULL((void*)0)) { | |||
| 751 | return NULL((void*)0); | |||
| 752 | } | |||
| 753 | if (!PyList_Check(listobj)((((((PyObject*)(listobj))->ob_type))->tp_flags & ( (1UL << 25))) != 0) || PyList_GET_SIZE(listobj)(((void) (0)), (((PyVarObject*)(listobj))->ob_size)) < 1) { | |||
| 754 | PyErr_SetString(PyExc_RuntimeError, | |||
| 755 | "_commastring is not returning a list with len >= 1"); | |||
| 756 | Py_DECREF(listobj)_Py_DECREF(((PyObject*)(listobj))); | |||
| 757 | return NULL((void*)0); | |||
| 758 | } | |||
| 759 | if (PyList_GET_SIZE(listobj)(((void) (0)), (((PyVarObject*)(listobj))->ob_size)) == 1) { | |||
| 760 | res = _convert_from_any(PyList_GET_ITEM(listobj, 0)(((PyListObject *)(listobj))->ob_item[0]), align); | |||
| 761 | } | |||
| 762 | else { | |||
| 763 | res = _convert_from_list(listobj, align); | |||
| 764 | } | |||
| 765 | Py_DECREF(listobj)_Py_DECREF(((PyObject*)(listobj))); | |||
| 766 | return res; | |||
| 767 | } | |||
| 768 | ||||
| 769 | static int | |||
| 770 | _is_tuple_of_integers(PyObject *obj) | |||
| 771 | { | |||
| 772 | int i; | |||
| 773 | ||||
| 774 | if (!PyTuple_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | |||
| 775 | return 0; | |||
| 776 | } | |||
| 777 | for (i = 0; i < PyTuple_GET_SIZE(obj)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(obj))))-> ob_size); i++) { | |||
| 778 | if (!PyArray_IsIntegerScalar(PyTuple_GET_ITEM(obj, i))(((((((PyObject*)(((((void) (0)), (PyTupleObject *)(obj))-> ob_item[i])))->ob_type))->tp_flags & ((1UL << 24))) != 0) || (((((PyObject*)((((((void) (0)), (PyTupleObject *)(obj))->ob_item[i]))))->ob_type) == (&PyIntegerArrType_Type ) || PyType_IsSubtype((((PyObject*)((((((void) (0)), (PyTupleObject *)(obj))->ob_item[i]))))->ob_type), (&PyIntegerArrType_Type )))))) { | |||
| 779 | return 0; | |||
| 780 | } | |||
| 781 | } | |||
| 782 | return 1; | |||
| 783 | } | |||
| 784 | ||||
| 785 | /* | |||
| 786 | * helper function for _try_convert_from_inherit_tuple to disallow dtypes of the form | |||
| 787 | * (old_dtype, new_dtype) where either of the dtypes contains python | |||
| 788 | * objects - these dtypes are not useful and can be a source of segfaults, | |||
| 789 | * when an attempt is made to interpret a python object as a different dtype | |||
| 790 | * or vice versa | |||
| 791 | * an exception is made for dtypes of the form ('O', [('name', 'O')]), which | |||
| 792 | * people have been using to add a field to an object array without fields | |||
| 793 | */ | |||
| 794 | static int | |||
| 795 | _validate_union_object_dtype(PyArray_Descr *new, PyArray_Descr *conv) | |||
| 796 | { | |||
| 797 | PyObject *name, *tup; | |||
| 798 | PyArray_Descr *dtype; | |||
| 799 | ||||
| 800 | if (!PyDataType_REFCHK(new)(((new)->flags & (0x01)) == (0x01)) && !PyDataType_REFCHK(conv)(((conv)->flags & (0x01)) == (0x01))) { | |||
| 801 | return 0; | |||
| 802 | } | |||
| 803 | if (PyDataType_HASFIELDS(new)(((PyArray_Descr *)(new))->names != ((void*)0)) || new->kind != 'O') { | |||
| 804 | goto fail; | |||
| 805 | } | |||
| 806 | if (!PyDataType_HASFIELDS(conv)(((PyArray_Descr *)(conv))->names != ((void*)0)) || PyTuple_GET_SIZE(conv->names)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(conv->names ))))->ob_size) != 1) { | |||
| 807 | goto fail; | |||
| 808 | } | |||
| 809 | name = PyTuple_GET_ITEM(conv->names, 0)((((void) (0)), (PyTupleObject *)(conv->names))->ob_item [0]); | |||
| 810 | if (name == NULL((void*)0)) { | |||
| 811 | return -1; | |||
| 812 | } | |||
| 813 | tup = PyDict_GetItemWithError(conv->fields, name); | |||
| 814 | if (tup == NULL((void*)0)) { | |||
| 815 | if (!PyErr_Occurred()) { | |||
| 816 | /* fields was missing the name it claimed to contain */ | |||
| 817 | PyErr_BadInternalCall()_PyErr_BadInternalCall("/tmp/pyrefcon/numpy/numpy/core/src/multiarray/descriptor.c" , 817); | |||
| 818 | } | |||
| 819 | return -1; | |||
| 820 | } | |||
| 821 | dtype = (PyArray_Descr *)PyTuple_GET_ITEM(tup, 0)((((void) (0)), (PyTupleObject *)(tup))->ob_item[0]); | |||
| 822 | if (dtype == NULL((void*)0)) { | |||
| 823 | return -1; | |||
| 824 | } | |||
| 825 | if (dtype->kind != 'O') { | |||
| 826 | goto fail; | |||
| 827 | } | |||
| 828 | return 0; | |||
| 829 | ||||
| 830 | fail: | |||
| 831 | PyErr_SetString(PyExc_ValueError, | |||
| 832 | "dtypes of the form (old_dtype, new_dtype) containing the object " | |||
| 833 | "dtype are not supported"); | |||
| 834 | return -1; | |||
| 835 | } | |||
| 836 | ||||
| 837 | /* | |||
| 838 | * A tuple type would be either (generic typeobject, typesize) | |||
| 839 | * or (fixed-length data-type, shape) | |||
| 840 | * | |||
| 841 | * or (inheriting data-type, new-data-type) | |||
| 842 | * The new data-type must have the same itemsize as the inheriting data-type | |||
| 843 | * unless the latter is 0 | |||
| 844 | * | |||
| 845 | * Thus (int32, {'real':(int16,0),'imag',(int16,2)}) | |||
| 846 | * | |||
| 847 | * is one way to specify a descriptor that will give | |||
| 848 | * a['real'] and a['imag'] to an int32 array. | |||
| 849 | * | |||
| 850 | * leave type reference alone | |||
| 851 | * | |||
| 852 | * Returns `Py_NotImplemented` if the second tuple item is not | |||
| 853 | * appropriate. | |||
| 854 | */ | |||
| 855 | static PyArray_Descr * | |||
| 856 | _try_convert_from_inherit_tuple(PyArray_Descr *type, PyObject *newobj) | |||
| 857 | { | |||
| 858 | if (PyArray_IsScalar(newobj, Integer)(((((PyObject*)(newobj))->ob_type) == (&PyIntegerArrType_Type ) || PyType_IsSubtype((((PyObject*)(newobj))->ob_type), (& PyIntegerArrType_Type)))) || _is_tuple_of_integers(newobj)) { | |||
| 859 | /* It's a subarray or flexible type instead */ | |||
| 860 | Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct)))); | |||
| 861 | return (PyArray_Descr *)Py_NotImplemented(&_Py_NotImplementedStruct); | |||
| 862 | } | |||
| 863 | PyArray_Descr *conv = _convert_from_any(newobj, 0); | |||
| 864 | if (conv == NULL((void*)0)) { | |||
| 865 | /* Let someone else try to convert this */ | |||
| 866 | PyErr_Clear(); | |||
| 867 | Py_INCREF(Py_NotImplemented)_Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct)))); | |||
| 868 | return (PyArray_Descr *)Py_NotImplemented(&_Py_NotImplementedStruct); | |||
| 869 | } | |||
| 870 | PyArray_Descr *new = PyArray_DescrNew(type); | |||
| 871 | if (new == NULL((void*)0)) { | |||
| 872 | goto fail; | |||
| 873 | } | |||
| 874 | if (PyDataType_ISUNSIZED(new)((new)->elsize == 0 && !(((PyArray_Descr *)(new))-> names != ((void*)0)))) { | |||
| 875 | new->elsize = conv->elsize; | |||
| 876 | } | |||
| 877 | else if (new->elsize != conv->elsize) { | |||
| 878 | PyErr_SetString(PyExc_ValueError, | |||
| 879 | "mismatch in size of old and new data-descriptor"); | |||
| 880 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 881 | goto fail; | |||
| 882 | } | |||
| 883 | else if (_validate_union_object_dtype(new, conv) < 0) { | |||
| 884 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 885 | goto fail; | |||
| 886 | } | |||
| 887 | ||||
| 888 | if (PyDataType_HASFIELDS(conv)(((PyArray_Descr *)(conv))->names != ((void*)0))) { | |||
| 889 | Py_XDECREF(new->fields)_Py_XDECREF(((PyObject*)(new->fields))); | |||
| 890 | new->fields = conv->fields; | |||
| 891 | Py_XINCREF(new->fields)_Py_XINCREF(((PyObject*)(new->fields))); | |||
| 892 | ||||
| 893 | Py_XDECREF(new->names)_Py_XDECREF(((PyObject*)(new->names))); | |||
| 894 | new->names = conv->names; | |||
| 895 | Py_XINCREF(new->names)_Py_XINCREF(((PyObject*)(new->names))); | |||
| 896 | } | |||
| 897 | if (conv->metadata != NULL((void*)0)) { | |||
| 898 | Py_XDECREF(new->metadata)_Py_XDECREF(((PyObject*)(new->metadata))); | |||
| 899 | new->metadata = conv->metadata; | |||
| 900 | Py_XINCREF(new->metadata)_Py_XINCREF(((PyObject*)(new->metadata))); | |||
| 901 | } | |||
| 902 | /* | |||
| 903 | * Certain flags must be inherited from the fields. This is needed | |||
| 904 | * only for void dtypes (or subclasses of it such as a record dtype). | |||
| 905 | * For other dtypes, the field part will only be used for direct field | |||
| 906 | * access and thus flag inheritance should not be necessary. | |||
| 907 | * (We only allow object fields if the dtype is object as well.) | |||
| 908 | * This ensures copying over of the NPY_FROM_FIELDS "inherited" flags. | |||
| 909 | */ | |||
| 910 | if (new->type_num == NPY_VOID) { | |||
| 911 | new->flags = conv->flags; | |||
| 912 | } | |||
| 913 | Py_DECREF(conv)_Py_DECREF(((PyObject*)(conv))); | |||
| 914 | return new; | |||
| 915 | ||||
| 916 | fail: | |||
| 917 | Py_DECREF(conv)_Py_DECREF(((PyObject*)(conv))); | |||
| 918 | return NULL((void*)0); | |||
| 919 | } | |||
| 920 | ||||
| 921 | /* | |||
| 922 | * Validates that any field of the structured array 'dtype' which has | |||
| 923 | * the NPY_ITEM_HASOBJECT flag set does not overlap with another field. | |||
| 924 | * | |||
| 925 | * This algorithm is worst case O(n^2). It could be done with a sort | |||
| 926 | * and sweep algorithm, but the structured dtype representation is | |||
| 927 | * rather ugly right now, so writing something better can wait until | |||
| 928 | * that representation is made sane. | |||
| 929 | * | |||
| 930 | * Returns 0 on success, -1 if an exception is raised. | |||
| 931 | */ | |||
| 932 | static int | |||
| 933 | _validate_object_field_overlap(PyArray_Descr *dtype) | |||
| 934 | { | |||
| 935 | PyObject *names, *fields, *key, *tup, *title; | |||
| 936 | Py_ssize_t i, j, names_size; | |||
| 937 | PyArray_Descr *fld_dtype, *fld2_dtype; | |||
| 938 | int fld_offset, fld2_offset; | |||
| 939 | ||||
| 940 | /* Get some properties from the dtype */ | |||
| 941 | names = dtype->names; | |||
| 942 | names_size = PyTuple_GET_SIZE(names)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(names))))-> ob_size); | |||
| 943 | fields = dtype->fields; | |||
| 944 | ||||
| 945 | for (i = 0; i < names_size; ++i) { | |||
| 946 | key = PyTuple_GET_ITEM(names, i)((((void) (0)), (PyTupleObject *)(names))->ob_item[i]); | |||
| 947 | if (key == NULL((void*)0)) { | |||
| 948 | return -1; | |||
| 949 | } | |||
| 950 | tup = PyDict_GetItemWithError(fields, key); | |||
| 951 | if (tup == NULL((void*)0)) { | |||
| 952 | if (!PyErr_Occurred()) { | |||
| 953 | /* fields was missing the name it claimed to contain */ | |||
| 954 | PyErr_BadInternalCall()_PyErr_BadInternalCall("/tmp/pyrefcon/numpy/numpy/core/src/multiarray/descriptor.c" , 954); | |||
| 955 | } | |||
| 956 | return -1; | |||
| 957 | } | |||
| 958 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(tup, "Oi|O", &fld_dtype, &fld_offset, &title)) { | |||
| 959 | return -1; | |||
| 960 | } | |||
| 961 | ||||
| 962 | /* If this field has objects, check for overlaps */ | |||
| 963 | if (PyDataType_REFCHK(fld_dtype)(((fld_dtype)->flags & (0x01)) == (0x01))) { | |||
| 964 | for (j = 0; j < names_size; ++j) { | |||
| 965 | if (i != j) { | |||
| 966 | key = PyTuple_GET_ITEM(names, j)((((void) (0)), (PyTupleObject *)(names))->ob_item[j]); | |||
| 967 | if (key == NULL((void*)0)) { | |||
| 968 | return -1; | |||
| 969 | } | |||
| 970 | tup = PyDict_GetItemWithError(fields, key); | |||
| 971 | if (tup == NULL((void*)0)) { | |||
| 972 | if (!PyErr_Occurred()) { | |||
| 973 | /* fields was missing the name it claimed to contain */ | |||
| 974 | PyErr_BadInternalCall()_PyErr_BadInternalCall("/tmp/pyrefcon/numpy/numpy/core/src/multiarray/descriptor.c" , 974); | |||
| 975 | } | |||
| 976 | return -1; | |||
| 977 | } | |||
| 978 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(tup, "Oi|O", &fld2_dtype, | |||
| 979 | &fld2_offset, &title)) { | |||
| 980 | return -1; | |||
| 981 | } | |||
| 982 | /* Raise an exception if it overlaps */ | |||
| 983 | if (fld_offset < fld2_offset + fld2_dtype->elsize && | |||
| 984 | fld2_offset < fld_offset + fld_dtype->elsize) { | |||
| 985 | PyErr_SetString(PyExc_TypeError, | |||
| 986 | "Cannot create a NumPy dtype with overlapping " | |||
| 987 | "object fields"); | |||
| 988 | return -1; | |||
| 989 | } | |||
| 990 | } | |||
| 991 | } | |||
| 992 | } | |||
| 993 | } | |||
| 994 | ||||
| 995 | /* It passed all the overlap tests */ | |||
| 996 | return 0; | |||
| 997 | } | |||
| 998 | ||||
| 999 | /* | |||
| 1000 | * a dictionary specifying a data-type | |||
| 1001 | * must have at least two and up to four | |||
| 1002 | * keys These must all be sequences of the same length. | |||
| 1003 | * | |||
| 1004 | * can also have an additional key called "metadata" which can be any dictionary | |||
| 1005 | * | |||
| 1006 | * "names" --- field names | |||
| 1007 | * "formats" --- the data-type descriptors for the field. | |||
| 1008 | * | |||
| 1009 | * Optional: | |||
| 1010 | * | |||
| 1011 | * "offsets" --- integers indicating the offset into the | |||
| 1012 | * record of the start of the field. | |||
| 1013 | * if not given, then "consecutive offsets" | |||
| 1014 | * will be assumed and placed in the dictionary. | |||
| 1015 | * | |||
| 1016 | * "titles" --- Allows the use of an additional key | |||
| 1017 | * for the fields dictionary.(if these are strings | |||
| 1018 | * or unicode objects) or | |||
| 1019 | * this can also be meta-data to | |||
| 1020 | * be passed around with the field description. | |||
| 1021 | * | |||
| 1022 | * Attribute-lookup-based field names merely has to query the fields | |||
| 1023 | * dictionary of the data-descriptor. Any result present can be used | |||
| 1024 | * to return the correct field. | |||
| 1025 | * | |||
| 1026 | * So, the notion of what is a name and what is a title is really quite | |||
| 1027 | * arbitrary. | |||
| 1028 | * | |||
| 1029 | * What does distinguish a title, however, is that if it is not None, | |||
| 1030 | * it will be placed at the end of the tuple inserted into the | |||
| 1031 | * fields dictionary.and can therefore be used to carry meta-data around. | |||
| 1032 | * | |||
| 1033 | * If the dictionary does not have "names" and "formats" entries, | |||
| 1034 | * then it will be checked for conformity and used directly. | |||
| 1035 | */ | |||
| 1036 | static PyArray_Descr * | |||
| 1037 | _convert_from_field_dict(PyObject *obj, int align) | |||
| 1038 | { | |||
| 1039 | PyObject *_numpy_internal; | |||
| 1040 | PyArray_Descr *res; | |||
| 1041 | ||||
| 1042 | _numpy_internal = PyImport_ImportModule("numpy.core._internal"); | |||
| 1043 | if (_numpy_internal == NULL((void*)0)) { | |||
| 1044 | return NULL((void*)0); | |||
| 1045 | } | |||
| 1046 | res = (PyArray_Descr *)PyObject_CallMethod_PyObject_CallMethod_SizeT(_numpy_internal, | |||
| 1047 | "_usefields", "Oi", obj, align); | |||
| 1048 | Py_DECREF(_numpy_internal)_Py_DECREF(((PyObject*)(_numpy_internal))); | |||
| 1049 | return res; | |||
| 1050 | } | |||
| 1051 | ||||
| 1052 | /* | |||
| 1053 | * Creates a struct dtype object from a Python dictionary. | |||
| 1054 | */ | |||
| 1055 | static PyArray_Descr * | |||
| 1056 | _convert_from_dict(PyObject *obj, int align) | |||
| 1057 | { | |||
| 1058 | PyObject *fields = PyDict_New(); | |||
| 1059 | if (fields == NULL((void*)0)) { | |||
| 1060 | return (PyArray_Descr *)PyErr_NoMemory(); | |||
| 1061 | } | |||
| 1062 | /* | |||
| 1063 | * Use PyMapping_GetItemString to support dictproxy objects as well. | |||
| 1064 | */ | |||
| 1065 | PyObject *names = PyMapping_GetItemString(obj, "names"); | |||
| 1066 | if (names == NULL((void*)0)) { | |||
| 1067 | Py_DECREF(fields)_Py_DECREF(((PyObject*)(fields))); | |||
| 1068 | /* XXX should check this is a KeyError */ | |||
| 1069 | PyErr_Clear(); | |||
| 1070 | return _convert_from_field_dict(obj, align); | |||
| 1071 | } | |||
| 1072 | PyObject *descrs = PyMapping_GetItemString(obj, "formats"); | |||
| 1073 | if (descrs == NULL((void*)0)) { | |||
| 1074 | Py_DECREF(fields)_Py_DECREF(((PyObject*)(fields))); | |||
| 1075 | /* XXX should check this is a KeyError */ | |||
| 1076 | PyErr_Clear(); | |||
| 1077 | Py_DECREF(names)_Py_DECREF(((PyObject*)(names))); | |||
| 1078 | return _convert_from_field_dict(obj, align); | |||
| 1079 | } | |||
| 1080 | int n = PyObject_LengthPyObject_Size(names); | |||
| 1081 | PyObject *offsets = PyMapping_GetItemString(obj, "offsets"); | |||
| 1082 | if (!offsets) { | |||
| 1083 | PyErr_Clear(); | |||
| 1084 | } | |||
| 1085 | PyObject *titles = PyMapping_GetItemString(obj, "titles"); | |||
| 1086 | if (!titles) { | |||
| 1087 | PyErr_Clear(); | |||
| 1088 | } | |||
| 1089 | ||||
| 1090 | if ((n > PyObject_LengthPyObject_Size(descrs)) | |||
| 1091 | || (offsets && (n > PyObject_LengthPyObject_Size(offsets))) | |||
| 1092 | || (titles && (n > PyObject_LengthPyObject_Size(titles)))) { | |||
| 1093 | PyErr_SetString(PyExc_ValueError, | |||
| 1094 | "'names', 'formats', 'offsets', and 'titles' dict " | |||
| 1095 | "entries must have the same length"); | |||
| 1096 | goto fail; | |||
| 1097 | } | |||
| 1098 | ||||
| 1099 | /* | |||
| 1100 | * If a property 'aligned' is in the dict, it overrides the align flag | |||
| 1101 | * to be True if it not already true. | |||
| 1102 | */ | |||
| 1103 | PyObject *tmp = PyMapping_GetItemString(obj, "aligned"); | |||
| 1104 | if (tmp == NULL((void*)0)) { | |||
| 1105 | PyErr_Clear(); | |||
| 1106 | } else { | |||
| 1107 | if (tmp == Py_True((PyObject *) &_Py_TrueStruct)) { | |||
| 1108 | align = 1; | |||
| 1109 | } | |||
| 1110 | else if (tmp != Py_False((PyObject *) &_Py_FalseStruct)) { | |||
| 1111 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | |||
| 1112 | PyErr_SetString(PyExc_ValueError, | |||
| 1113 | "NumPy dtype descriptor includes 'aligned' entry, " | |||
| 1114 | "but its value is neither True nor False"); | |||
| 1115 | goto fail; | |||
| 1116 | } | |||
| 1117 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | |||
| 1118 | } | |||
| 1119 | ||||
| 1120 | /* Types with fields need the Python C API for field access */ | |||
| 1121 | char dtypeflags = NPY_NEEDS_PYAPI0x10; | |||
| 1122 | int totalsize = 0; | |||
| 1123 | int maxalign = 0; | |||
| 1124 | int has_out_of_order_fields = 0; | |||
| 1125 | for (int i = 0; i < n; i++) { | |||
| 1126 | /* Build item to insert (descr, offset, [title])*/ | |||
| 1127 | int len = 2; | |||
| 1128 | PyObject *title = NULL((void*)0); | |||
| 1129 | PyObject *ind = PyLong_FromLong(i); | |||
| 1130 | if (titles) { | |||
| 1131 | title=PyObject_GetItem(titles, ind); | |||
| 1132 | if (title && title != Py_None(&_Py_NoneStruct)) { | |||
| 1133 | len = 3; | |||
| 1134 | } | |||
| 1135 | else { | |||
| 1136 | Py_XDECREF(title)_Py_XDECREF(((PyObject*)(title))); | |||
| 1137 | } | |||
| 1138 | PyErr_Clear(); | |||
| 1139 | } | |||
| 1140 | PyObject *tup = PyTuple_New(len); | |||
| 1141 | PyObject *descr = PyObject_GetItem(descrs, ind); | |||
| 1142 | if (!descr) { | |||
| 1143 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1144 | Py_DECREF(ind)_Py_DECREF(((PyObject*)(ind))); | |||
| 1145 | goto fail; | |||
| 1146 | } | |||
| 1147 | PyArray_Descr *newdescr = _convert_from_any(descr, align); | |||
| 1148 | Py_DECREF(descr)_Py_DECREF(((PyObject*)(descr))); | |||
| 1149 | if (newdescr == NULL((void*)0)) { | |||
| 1150 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1151 | Py_DECREF(ind)_Py_DECREF(((PyObject*)(ind))); | |||
| 1152 | goto fail; | |||
| 1153 | } | |||
| 1154 | PyTuple_SET_ITEM(tup, 0, (PyObject *)newdescr)PyTuple_SetItem(tup, 0, (PyObject *)newdescr); | |||
| 1155 | int _align = 1; | |||
| 1156 | if (align) { | |||
| 1157 | _align = newdescr->alignment; | |||
| 1158 | maxalign = PyArray_MAX(maxalign,_align)(((maxalign)>(_align))?(maxalign):(_align)); | |||
| 1159 | } | |||
| 1160 | if (offsets) { | |||
| 1161 | PyObject *off = PyObject_GetItem(offsets, ind); | |||
| 1162 | if (!off) { | |||
| 1163 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1164 | Py_DECREF(ind)_Py_DECREF(((PyObject*)(ind))); | |||
| 1165 | goto fail; | |||
| 1166 | } | |||
| 1167 | long offset = PyArray_PyIntAsInt(off); | |||
| 1168 | if (error_converting(offset)(((offset) == -1) && PyErr_Occurred())) { | |||
| 1169 | Py_DECREF(off)_Py_DECREF(((PyObject*)(off))); | |||
| 1170 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1171 | Py_DECREF(ind)_Py_DECREF(((PyObject*)(ind))); | |||
| 1172 | goto fail; | |||
| 1173 | } | |||
| 1174 | Py_DECREF(off)_Py_DECREF(((PyObject*)(off))); | |||
| 1175 | if (offset < 0) { | |||
| 1176 | PyErr_Format(PyExc_ValueError, "offset %ld cannot be negative", | |||
| 1177 | offset); | |||
| 1178 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1179 | Py_DECREF(ind)_Py_DECREF(((PyObject*)(ind))); | |||
| 1180 | goto fail; | |||
| 1181 | } | |||
| 1182 | ||||
| 1183 | PyTuple_SET_ITEM(tup, 1, PyLong_FromLong(offset))PyTuple_SetItem(tup, 1, PyLong_FromLong(offset)); | |||
| 1184 | /* Flag whether the fields are specified out of order */ | |||
| 1185 | if (offset < totalsize) { | |||
| 1186 | has_out_of_order_fields = 1; | |||
| 1187 | } | |||
| 1188 | /* If align=True, enforce field alignment */ | |||
| 1189 | if (align && offset % newdescr->alignment != 0) { | |||
| 1190 | PyErr_Format(PyExc_ValueError, | |||
| 1191 | "offset %ld for NumPy dtype with fields is " | |||
| 1192 | "not divisible by the field alignment %d " | |||
| 1193 | "with align=True", | |||
| 1194 | offset, newdescr->alignment); | |||
| 1195 | Py_DECREF(ind)_Py_DECREF(((PyObject*)(ind))); | |||
| 1196 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1197 | goto fail; | |||
| 1198 | } | |||
| 1199 | else if (offset + newdescr->elsize > totalsize) { | |||
| 1200 | totalsize = offset + newdescr->elsize; | |||
| 1201 | } | |||
| 1202 | } | |||
| 1203 | else { | |||
| 1204 | if (align && _align > 1) { | |||
| 1205 | totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, _align); | |||
| 1206 | } | |||
| 1207 | PyTuple_SET_ITEM(tup, 1, PyLong_FromLong(totalsize))PyTuple_SetItem(tup, 1, PyLong_FromLong(totalsize)); | |||
| 1208 | totalsize += newdescr->elsize; | |||
| 1209 | } | |||
| 1210 | if (len == 3) { | |||
| 1211 | PyTuple_SET_ITEM(tup, 2, title)PyTuple_SetItem(tup, 2, title); | |||
| 1212 | } | |||
| 1213 | PyObject *name = PyObject_GetItem(names, ind); | |||
| 1214 | Py_DECREF(ind)_Py_DECREF(((PyObject*)(ind))); | |||
| 1215 | if (!name) { | |||
| 1216 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1217 | goto fail; | |||
| 1218 | } | |||
| 1219 | if (!PyUnicode_Check(name)((((((PyObject*)(name))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 1220 | PyErr_SetString(PyExc_ValueError, | |||
| 1221 | "field names must be strings"); | |||
| 1222 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1223 | goto fail; | |||
| 1224 | } | |||
| 1225 | ||||
| 1226 | /* Insert into dictionary */ | |||
| 1227 | if (PyDict_GetItemWithError(fields, name) != NULL((void*)0)) { | |||
| 1228 | PyErr_SetString(PyExc_ValueError, | |||
| 1229 | "name already used as a name or title"); | |||
| 1230 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1231 | goto fail; | |||
| 1232 | } | |||
| 1233 | else if (PyErr_Occurred()) { | |||
| 1234 | /* MemoryError during dict lookup */ | |||
| 1235 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1236 | goto fail; | |||
| 1237 | } | |||
| 1238 | int ret = PyDict_SetItem(fields, name, tup); | |||
| 1239 | Py_DECREF(name)_Py_DECREF(((PyObject*)(name))); | |||
| 1240 | if (ret < 0) { | |||
| 1241 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1242 | goto fail; | |||
| 1243 | } | |||
| 1244 | if (len == 3) { | |||
| 1245 | if (PyUnicode_Check(title)((((((PyObject*)(title))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 1246 | if (PyDict_GetItemWithError(fields, title) != NULL((void*)0)) { | |||
| 1247 | PyErr_SetString(PyExc_ValueError, | |||
| 1248 | "title already used as a name or title."); | |||
| 1249 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1250 | goto fail; | |||
| 1251 | } | |||
| 1252 | else if (PyErr_Occurred()) { | |||
| 1253 | /* MemoryError during dict lookup */ | |||
| 1254 | goto fail; | |||
| 1255 | } | |||
| 1256 | if (PyDict_SetItem(fields, title, tup) < 0) { | |||
| 1257 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1258 | goto fail; | |||
| 1259 | } | |||
| 1260 | } | |||
| 1261 | } | |||
| 1262 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 1263 | dtypeflags |= (newdescr->flags & NPY_FROM_FIELDS(0x08 | 0x02 | 0x01 | 0x10)); | |||
| 1264 | } | |||
| 1265 | ||||
| 1266 | PyArray_Descr *new = PyArray_DescrNewFromType(NPY_VOID); | |||
| 1267 | if (new == NULL((void*)0)) { | |||
| 1268 | goto fail; | |||
| 1269 | } | |||
| 1270 | if (maxalign > 1) { | |||
| 1271 | totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, maxalign); | |||
| 1272 | } | |||
| 1273 | if (align) { | |||
| 1274 | new->alignment = maxalign; | |||
| 1275 | } | |||
| 1276 | new->elsize = totalsize; | |||
| 1277 | if (!PyTuple_Check(names)((((((PyObject*)(names))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | |||
| 1278 | Py_SETREF(names, PySequence_Tuple(names))do { PyObject *_py_tmp = ((PyObject*)(names)); (names) = (PySequence_Tuple (names)); _Py_DECREF(((PyObject*)(_py_tmp))); } while (0); | |||
| 1279 | if (names == NULL((void*)0)) { | |||
| 1280 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 1281 | goto fail; | |||
| 1282 | } | |||
| 1283 | } | |||
| 1284 | new->names = names; | |||
| 1285 | new->fields = fields; | |||
| 1286 | new->flags = dtypeflags; | |||
| 1287 | /* new takes responsibility for DECREFing names, fields */ | |||
| 1288 | names = NULL((void*)0); | |||
| 1289 | fields = NULL((void*)0); | |||
| 1290 | ||||
| 1291 | /* | |||
| 1292 | * If the fields weren't in order, and there was an OBJECT type, | |||
| 1293 | * need to verify that no OBJECT types overlap with something else. | |||
| 1294 | */ | |||
| 1295 | if (has_out_of_order_fields && PyDataType_REFCHK(new)(((new)->flags & (0x01)) == (0x01))) { | |||
| 1296 | if (_validate_object_field_overlap(new) < 0) { | |||
| 1297 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 1298 | goto fail; | |||
| 1299 | } | |||
| 1300 | } | |||
| 1301 | ||||
| 1302 | /* Structured arrays get a sticky aligned bit */ | |||
| 1303 | if (align) { | |||
| 1304 | new->flags |= NPY_ALIGNED_STRUCT0x80; | |||
| 1305 | } | |||
| 1306 | ||||
| 1307 | /* Override the itemsize if provided */ | |||
| 1308 | tmp = PyMapping_GetItemString(obj, "itemsize"); | |||
| 1309 | if (tmp == NULL((void*)0)) { | |||
| 1310 | PyErr_Clear(); | |||
| 1311 | } else { | |||
| 1312 | int itemsize = (int)PyArray_PyIntAsInt(tmp); | |||
| 1313 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | |||
| 1314 | if (error_converting(itemsize)(((itemsize) == -1) && PyErr_Occurred())) { | |||
| 1315 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 1316 | goto fail; | |||
| 1317 | } | |||
| 1318 | /* Make sure the itemsize isn't made too small */ | |||
| 1319 | if (itemsize < new->elsize) { | |||
| 1320 | PyErr_Format(PyExc_ValueError, | |||
| 1321 | "NumPy dtype descriptor requires %d bytes, " | |||
| 1322 | "cannot override to smaller itemsize of %d", | |||
| 1323 | new->elsize, itemsize); | |||
| 1324 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 1325 | goto fail; | |||
| 1326 | } | |||
| 1327 | /* If align is set, make sure the alignment divides into the size */ | |||
| 1328 | if (align && itemsize % new->alignment != 0) { | |||
| 1329 | PyErr_Format(PyExc_ValueError, | |||
| 1330 | "NumPy dtype descriptor requires alignment of %d bytes, " | |||
| 1331 | "which is not divisible into the specified itemsize %d", | |||
| 1332 | new->alignment, itemsize); | |||
| 1333 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 1334 | goto fail; | |||
| 1335 | } | |||
| 1336 | /* Set the itemsize */ | |||
| 1337 | new->elsize = itemsize; | |||
| 1338 | } | |||
| 1339 | ||||
| 1340 | /* Add the metadata if provided */ | |||
| 1341 | PyObject *metadata = PyMapping_GetItemString(obj, "metadata"); | |||
| 1342 | ||||
| 1343 | if (metadata == NULL((void*)0)) { | |||
| 1344 | PyErr_Clear(); | |||
| 1345 | } | |||
| 1346 | else if (new->metadata == NULL((void*)0)) { | |||
| 1347 | new->metadata = metadata; | |||
| 1348 | } | |||
| 1349 | else { | |||
| 1350 | int ret = PyDict_Merge(new->metadata, metadata, 0); | |||
| 1351 | Py_DECREF(metadata)_Py_DECREF(((PyObject*)(metadata))); | |||
| 1352 | if (ret < 0) { | |||
| 1353 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 1354 | goto fail; | |||
| 1355 | } | |||
| 1356 | } | |||
| 1357 | ||||
| 1358 | Py_XDECREF(fields)_Py_XDECREF(((PyObject*)(fields))); | |||
| 1359 | Py_XDECREF(names)_Py_XDECREF(((PyObject*)(names))); | |||
| 1360 | Py_XDECREF(descrs)_Py_XDECREF(((PyObject*)(descrs))); | |||
| 1361 | Py_XDECREF(offsets)_Py_XDECREF(((PyObject*)(offsets))); | |||
| 1362 | Py_XDECREF(titles)_Py_XDECREF(((PyObject*)(titles))); | |||
| 1363 | return new; | |||
| 1364 | ||||
| 1365 | fail: | |||
| 1366 | Py_XDECREF(fields)_Py_XDECREF(((PyObject*)(fields))); | |||
| 1367 | Py_XDECREF(names)_Py_XDECREF(((PyObject*)(names))); | |||
| 1368 | Py_XDECREF(descrs)_Py_XDECREF(((PyObject*)(descrs))); | |||
| 1369 | Py_XDECREF(offsets)_Py_XDECREF(((PyObject*)(offsets))); | |||
| 1370 | Py_XDECREF(titles)_Py_XDECREF(((PyObject*)(titles))); | |||
| 1371 | return NULL((void*)0); | |||
| 1372 | } | |||
| 1373 | ||||
| 1374 | ||||
| 1375 | /*NUMPY_API*/ | |||
| 1376 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr * | |||
| 1377 | PyArray_DescrNewFromType(int type_num) | |||
| 1378 | { | |||
| 1379 | PyArray_Descr *old; | |||
| 1380 | PyArray_Descr *new; | |||
| 1381 | ||||
| 1382 | old = PyArray_DescrFromType(type_num); | |||
| 1383 | new = PyArray_DescrNew(old); | |||
| 1384 | Py_DECREF(old)_Py_DECREF(((PyObject*)(old))); | |||
| 1385 | return new; | |||
| 1386 | } | |||
| 1387 | ||||
| 1388 | /*NUMPY_API | |||
| 1389 | * Get typenum from an object -- None goes to NULL | |||
| 1390 | */ | |||
| 1391 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | |||
| 1392 | PyArray_DescrConverter2(PyObject *obj, PyArray_Descr **at) | |||
| 1393 | { | |||
| 1394 | if (obj == Py_None(&_Py_NoneStruct)) { | |||
| 1395 | *at = NULL((void*)0); | |||
| 1396 | return NPY_SUCCEED1; | |||
| 1397 | } | |||
| 1398 | else { | |||
| 1399 | return PyArray_DescrConverter(obj, at); | |||
| 1400 | } | |||
| 1401 | } | |||
| 1402 | ||||
| 1403 | /** | |||
| 1404 | * Get a dtype instance from a python type | |||
| 1405 | */ | |||
| 1406 | static PyArray_Descr * | |||
| 1407 | _convert_from_type(PyObject *obj) { | |||
| 1408 | PyTypeObject *typ = (PyTypeObject*)obj; | |||
| 1409 | ||||
| 1410 | if (PyType_IsSubtype(typ, &PyGenericArrType_Type)) { | |||
| 1411 | return PyArray_DescrFromTypeObject(obj); | |||
| 1412 | } | |||
| 1413 | else if (typ == &PyLong_Type) { | |||
| 1414 | return PyArray_DescrFromType(NPY_LONG); | |||
| 1415 | } | |||
| 1416 | else if (typ == &PyFloat_Type) { | |||
| 1417 | return PyArray_DescrFromType(NPY_DOUBLE); | |||
| 1418 | } | |||
| 1419 | else if (typ == &PyComplex_Type) { | |||
| 1420 | return PyArray_DescrFromType(NPY_CDOUBLE); | |||
| 1421 | } | |||
| 1422 | else if (typ == &PyBool_Type) { | |||
| 1423 | return PyArray_DescrFromType(NPY_BOOL); | |||
| 1424 | } | |||
| 1425 | else if (typ == &PyBytes_Type) { | |||
| 1426 | /* | |||
| 1427 | * TODO: This should be deprecated, and have special handling for | |||
| 1428 | * dtype=bytes/"S" in coercion: It should not rely on "S0". | |||
| 1429 | */ | |||
| 1430 | return PyArray_DescrFromType(NPY_STRING); | |||
| 1431 | } | |||
| 1432 | else if (typ == &PyUnicode_Type) { | |||
| 1433 | /* | |||
| 1434 | * TODO: This should be deprecated, and have special handling for | |||
| 1435 | * dtype=str/"U" in coercion: It should not rely on "U0". | |||
| 1436 | */ | |||
| 1437 | return PyArray_DescrFromType(NPY_UNICODE); | |||
| 1438 | } | |||
| 1439 | else if (typ == &PyMemoryView_Type) { | |||
| 1440 | return PyArray_DescrFromType(NPY_VOID); | |||
| 1441 | } | |||
| 1442 | else if (typ == &PyBaseObject_Type) { | |||
| 1443 | return PyArray_DescrFromType(NPY_OBJECT); | |||
| 1444 | } | |||
| 1445 | else { | |||
| 1446 | PyArray_Descr *ret = _try_convert_from_dtype_attr(obj); | |||
| 1447 | if ((PyObject *)ret != Py_NotImplemented(&_Py_NotImplementedStruct)) { | |||
| 1448 | return ret; | |||
| 1449 | } | |||
| 1450 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 1451 | ||||
| 1452 | /* | |||
| 1453 | * Note: this comes after _try_convert_from_dtype_attr because the ctypes | |||
| 1454 | * type might override the dtype if numpy does not otherwise | |||
| 1455 | * support it. | |||
| 1456 | */ | |||
| 1457 | ret = _try_convert_from_ctypes_type(typ); | |||
| 1458 | if ((PyObject *)ret != Py_NotImplemented(&_Py_NotImplementedStruct)) { | |||
| 1459 | return ret; | |||
| 1460 | } | |||
| 1461 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 1462 | ||||
| 1463 | /* | |||
| 1464 | * All other classes are treated as object. This can be convenient | |||
| 1465 | * to convey an intention of using it for a specific python type | |||
| 1466 | * and possibly allow converting to a new type-specific dtype in the future. It may make sense to | |||
| 1467 | * only allow this only within `dtype=...` keyword argument context | |||
| 1468 | * in the future. | |||
| 1469 | */ | |||
| 1470 | return PyArray_DescrFromType(NPY_OBJECT); | |||
| 1471 | } | |||
| 1472 | } | |||
| 1473 | ||||
| 1474 | ||||
| 1475 | static PyArray_Descr * | |||
| 1476 | _convert_from_str(PyObject *obj, int align); | |||
| 1477 | ||||
| 1478 | static PyArray_Descr * | |||
| 1479 | _convert_from_any(PyObject *obj, int align) | |||
| 1480 | { | |||
| 1481 | /* default */ | |||
| 1482 | if (obj == Py_None(&_Py_NoneStruct)) { | |||
| 1483 | return PyArray_DescrFromType(NPY_DEFAULT_TYPENPY_DOUBLE); | |||
| 1484 | } | |||
| 1485 | else if (PyArray_DescrCheck(obj)((((PyObject*)(obj))->ob_type) == (&(*(PyTypeObject *) (&PyArrayDescr_TypeFull))) || PyType_IsSubtype((((PyObject *)(obj))->ob_type), (&(*(PyTypeObject *)(&PyArrayDescr_TypeFull )))))) { | |||
| 1486 | PyArray_Descr *ret = (PyArray_Descr *)obj; | |||
| 1487 | Py_INCREF(ret)_Py_INCREF(((PyObject*)(ret))); | |||
| 1488 | return ret; | |||
| 1489 | } | |||
| 1490 | else if (PyType_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 31))) != 0)) { | |||
| 1491 | return _convert_from_type(obj); | |||
| 1492 | } | |||
| 1493 | /* or a typecode string */ | |||
| 1494 | else if (PyBytes_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 27))) != 0)) { | |||
| 1495 | /* Allow bytes format strings: convert to unicode */ | |||
| 1496 | PyObject *obj2 = PyUnicode_FromEncodedObject(obj, NULL((void*)0), NULL((void*)0)); | |||
| 1497 | if (obj2 == NULL((void*)0)) { | |||
| 1498 | /* Convert the exception into a TypeError */ | |||
| 1499 | if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { | |||
| 1500 | PyErr_SetString(PyExc_TypeError, | |||
| 1501 | "data type not understood"); | |||
| 1502 | } | |||
| 1503 | return NULL((void*)0); | |||
| 1504 | } | |||
| 1505 | PyArray_Descr *ret = _convert_from_str(obj2, align); | |||
| 1506 | Py_DECREF(obj2)_Py_DECREF(((PyObject*)(obj2))); | |||
| 1507 | return ret; | |||
| 1508 | } | |||
| 1509 | else if (PyUnicode_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 1510 | return _convert_from_str(obj, align); | |||
| 1511 | } | |||
| 1512 | else if (PyTuple_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | |||
| 1513 | /* or a tuple */ | |||
| 1514 | if (Py_EnterRecursiveCall(((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from" " a tuple object")) | |||
| 1515 | " while trying to convert the given data type from"((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from" " a tuple object")) | |||
| 1516 | " a tuple object" )((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from" " a tuple object")) != 0) { | |||
| 1517 | return NULL((void*)0); | |||
| 1518 | } | |||
| 1519 | PyArray_Descr *ret = _convert_from_tuple(obj, align); | |||
| 1520 | Py_LeaveRecursiveCall()do{ if((--(PyThreadState_Get()->recursion_depth) < (((_Py_CheckRecursionLimit ) > 200) ? ((_Py_CheckRecursionLimit) - 50) : (3 * ((_Py_CheckRecursionLimit ) >> 2))))) PyThreadState_Get()->overflowed = 0; } while (0); | |||
| 1521 | return ret; | |||
| 1522 | } | |||
| 1523 | else if (PyList_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 25))) != 0)) { | |||
| 1524 | /* or a list */ | |||
| 1525 | if (Py_EnterRecursiveCall(((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from" " a list object")) | |||
| 1526 | " while trying to convert the given data type from"((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from" " a list object")) | |||
| 1527 | " a list object" )((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from" " a list object")) != 0) { | |||
| 1528 | return NULL((void*)0); | |||
| 1529 | } | |||
| 1530 | PyArray_Descr *ret = _convert_from_array_descr(obj, align); | |||
| 1531 | Py_LeaveRecursiveCall()do{ if((--(PyThreadState_Get()->recursion_depth) < (((_Py_CheckRecursionLimit ) > 200) ? ((_Py_CheckRecursionLimit) - 50) : (3 * ((_Py_CheckRecursionLimit ) >> 2))))) PyThreadState_Get()->overflowed = 0; } while (0); | |||
| 1532 | return ret; | |||
| 1533 | } | |||
| 1534 | else if (PyDict_Check(obj)((((((PyObject*)(obj))->ob_type))->tp_flags & ((1UL << 29))) != 0) || PyDictProxy_Check(obj)) { | |||
| 1535 | /* or a dictionary */ | |||
| 1536 | if (Py_EnterRecursiveCall(((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from" " a dict object")) | |||
| 1537 | " while trying to convert the given data type from"((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from" " a dict object")) | |||
| 1538 | " a dict object" )((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit ) && _Py_CheckRecursiveCall(" while trying to convert the given data type from" " a dict object")) != 0) { | |||
| 1539 | return NULL((void*)0); | |||
| 1540 | } | |||
| 1541 | PyArray_Descr *ret = _convert_from_dict(obj, align); | |||
| 1542 | Py_LeaveRecursiveCall()do{ if((--(PyThreadState_Get()->recursion_depth) < (((_Py_CheckRecursionLimit ) > 200) ? ((_Py_CheckRecursionLimit) - 50) : (3 * ((_Py_CheckRecursionLimit ) >> 2))))) PyThreadState_Get()->overflowed = 0; } while (0); | |||
| 1543 | return ret; | |||
| 1544 | } | |||
| 1545 | else if (PyArray_Check(obj)((((PyObject*)(obj))->ob_type) == (&PyArray_Type) || PyType_IsSubtype ((((PyObject*)(obj))->ob_type), (&PyArray_Type)))) { | |||
| 1546 | PyErr_SetString(PyExc_TypeError, "Cannot construct a dtype from an array"); | |||
| 1547 | return NULL((void*)0); | |||
| 1548 | } | |||
| 1549 | else { | |||
| 1550 | PyArray_Descr *ret = _try_convert_from_dtype_attr(obj); | |||
| 1551 | if ((PyObject *)ret != Py_NotImplemented(&_Py_NotImplementedStruct)) { | |||
| 1552 | return ret; | |||
| 1553 | } | |||
| 1554 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 1555 | /* | |||
| 1556 | * Note: this comes after _try_convert_from_dtype_attr because the ctypes | |||
| 1557 | * type might override the dtype if numpy does not otherwise | |||
| 1558 | * support it. | |||
| 1559 | */ | |||
| 1560 | ret = _try_convert_from_ctypes_type(Py_TYPE(obj)(((PyObject*)(obj))->ob_type)); | |||
| 1561 | if ((PyObject *)ret != Py_NotImplemented(&_Py_NotImplementedStruct)) { | |||
| 1562 | return ret; | |||
| 1563 | } | |||
| 1564 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 1565 | PyErr_Format(PyExc_TypeError, "Cannot interpret '%R' as a data type", obj); | |||
| 1566 | return NULL((void*)0); | |||
| 1567 | } | |||
| 1568 | } | |||
| 1569 | ||||
| 1570 | ||||
| 1571 | /*NUMPY_API | |||
| 1572 | * Get typenum from an object -- None goes to NPY_DEFAULT_TYPE | |||
| 1573 | * This function takes a Python object representing a type and converts it | |||
| 1574 | * to a the correct PyArray_Descr * structure to describe the type. | |||
| 1575 | * | |||
| 1576 | * Many objects can be used to represent a data-type which in NumPy is | |||
| 1577 | * quite a flexible concept. | |||
| 1578 | * | |||
| 1579 | * This is the central code that converts Python objects to | |||
| 1580 | * Type-descriptor objects that are used throughout numpy. | |||
| 1581 | * | |||
| 1582 | * Returns a new reference in *at, but the returned should not be | |||
| 1583 | * modified as it may be one of the canonical immutable objects or | |||
| 1584 | * a reference to the input obj. | |||
| 1585 | */ | |||
| 1586 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | |||
| 1587 | PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at) | |||
| 1588 | { | |||
| 1589 | *at = _convert_from_any(obj, 0); | |||
| 1590 | return (*at) ? NPY_SUCCEED1 : NPY_FAIL0; | |||
| 1591 | } | |||
| 1592 | ||||
| 1593 | /** Convert a bytestring specification into a dtype */ | |||
| 1594 | static PyArray_Descr * | |||
| 1595 | _convert_from_str(PyObject *obj, int align) | |||
| 1596 | { | |||
| 1597 | /* Check for a string typecode. */ | |||
| 1598 | Py_ssize_t len = 0; | |||
| 1599 | char const *type = PyUnicode_AsUTF8AndSize(obj, &len); | |||
| 1600 | if (type == NULL((void*)0)) { | |||
| 1601 | return NULL((void*)0); | |||
| 1602 | } | |||
| 1603 | ||||
| 1604 | /* Empty string is invalid */ | |||
| 1605 | if (len == 0) { | |||
| 1606 | goto fail; | |||
| 1607 | } | |||
| 1608 | ||||
| 1609 | /* check for commas present or first (or second) element a digit */ | |||
| 1610 | if (_check_for_commastring(type, len)) { | |||
| 1611 | return _convert_from_commastring(obj, align); | |||
| 1612 | } | |||
| 1613 | ||||
| 1614 | /* Process the endian character. '|' is replaced by '='*/ | |||
| 1615 | char endian = '='; | |||
| 1616 | switch (type[0]) { | |||
| 1617 | case '>': | |||
| 1618 | case '<': | |||
| 1619 | case '=': | |||
| 1620 | endian = type[0]; | |||
| 1621 | ++type; | |||
| 1622 | --len; | |||
| 1623 | break; | |||
| 1624 | ||||
| 1625 | case '|': | |||
| 1626 | endian = '='; | |||
| 1627 | ++type; | |||
| 1628 | --len; | |||
| 1629 | break; | |||
| 1630 | } | |||
| 1631 | ||||
| 1632 | /* Just an endian character is invalid */ | |||
| 1633 | if (len == 0) { | |||
| 1634 | goto fail; | |||
| 1635 | } | |||
| 1636 | ||||
| 1637 | /* Check for datetime format */ | |||
| 1638 | if (is_datetime_typestr(type, len)) { | |||
| 1639 | PyArray_Descr *ret = parse_dtype_from_datetime_typestr(type, len); | |||
| 1640 | if (ret == NULL((void*)0)) { | |||
| 1641 | return NULL((void*)0); | |||
| 1642 | } | |||
| 1643 | /* ret has byte order '=' at this point */ | |||
| 1644 | if (!PyArray_ISNBO(endian)((endian) != '>')) { | |||
| 1645 | ret->byteorder = endian; | |||
| 1646 | } | |||
| 1647 | return ret; | |||
| 1648 | } | |||
| 1649 | ||||
| 1650 | int check_num = NPY_NOTYPE + 10; | |||
| 1651 | int elsize = 0; | |||
| 1652 | /* A typecode like 'd' */ | |||
| 1653 | if (len == 1) { | |||
| 1654 | /* Python byte string characters are unsigned */ | |||
| 1655 | check_num = (unsigned char) type[0]; | |||
| 1656 | } | |||
| 1657 | /* A kind + size like 'f8' */ | |||
| 1658 | else { | |||
| 1659 | char *typeend = NULL((void*)0); | |||
| 1660 | int kind; | |||
| 1661 | ||||
| 1662 | /* Parse the integer, make sure it's the rest of the string */ | |||
| 1663 | elsize = (int)strtol(type + 1, &typeend, 10); | |||
| 1664 | if (typeend - type == len) { | |||
| 1665 | ||||
| 1666 | kind = type[0]; | |||
| 1667 | switch (kind) { | |||
| 1668 | case NPY_STRINGLTR: | |||
| 1669 | case NPY_STRINGLTR2: | |||
| 1670 | check_num = NPY_STRING; | |||
| 1671 | break; | |||
| 1672 | ||||
| 1673 | /* | |||
| 1674 | * When specifying length of UNICODE | |||
| 1675 | * the number of characters is given to match | |||
| 1676 | * the STRING interface. Each character can be | |||
| 1677 | * more than one byte and itemsize must be | |||
| 1678 | * the number of bytes. | |||
| 1679 | */ | |||
| 1680 | case NPY_UNICODELTR: | |||
| 1681 | check_num = NPY_UNICODE; | |||
| 1682 | elsize <<= 2; | |||
| 1683 | break; | |||
| 1684 | ||||
| 1685 | case NPY_VOIDLTR: | |||
| 1686 | check_num = NPY_VOID; | |||
| 1687 | break; | |||
| 1688 | ||||
| 1689 | default: | |||
| 1690 | if (elsize == 0) { | |||
| 1691 | check_num = NPY_NOTYPE+10; | |||
| 1692 | } | |||
| 1693 | /* Support for generic processing c8, i4, f8, etc...*/ | |||
| 1694 | else { | |||
| 1695 | check_num = PyArray_TypestrConvert(elsize, kind); | |||
| 1696 | if (check_num == NPY_NOTYPE) { | |||
| 1697 | check_num += 10; | |||
| 1698 | } | |||
| 1699 | elsize = 0; | |||
| 1700 | } | |||
| 1701 | } | |||
| 1702 | } | |||
| 1703 | } | |||
| 1704 | ||||
| 1705 | if (PyErr_Occurred()) { | |||
| 1706 | goto fail; | |||
| 1707 | } | |||
| 1708 | ||||
| 1709 | PyArray_Descr *ret; | |||
| 1710 | if ((check_num == NPY_NOTYPE + 10) || | |||
| 1711 | (ret = PyArray_DescrFromType(check_num)) == NULL((void*)0)) { | |||
| 1712 | PyErr_Clear(); | |||
| 1713 | /* Now check to see if the object is registered in typeDict */ | |||
| 1714 | if (typeDict == NULL((void*)0)) { | |||
| 1715 | goto fail; | |||
| 1716 | } | |||
| 1717 | PyObject *item = PyDict_GetItemWithError(typeDict, obj); | |||
| 1718 | if (item == NULL((void*)0)) { | |||
| 1719 | if (PyErr_Occurred()) { | |||
| 1720 | return NULL((void*)0); | |||
| 1721 | } | |||
| 1722 | goto fail; | |||
| 1723 | } | |||
| 1724 | ||||
| 1725 | /* Check for a deprecated Numeric-style typecode */ | |||
| 1726 | /* `Uint` has deliberately weird uppercasing */ | |||
| 1727 | char *dep_tps[] = {"Bytes", "Datetime64", "Str", "Uint"}; | |||
| 1728 | int ndep_tps = sizeof(dep_tps) / sizeof(dep_tps[0]); | |||
| 1729 | for (int i = 0; i < ndep_tps; ++i) { | |||
| 1730 | char *dep_tp = dep_tps[i]; | |||
| 1731 | ||||
| 1732 | if (strncmp(type, dep_tp, strlen(dep_tp)) == 0) { | |||
| 1733 | /* Deprecated 2020-06-09, NumPy 1.20 */ | |||
| 1734 | if (DEPRECATE("Numeric-style type codes are "PyErr_WarnEx(PyExc_DeprecationWarning,"Numeric-style type codes are " "deprecated and will result in " "an error in the future.",1 ) | |||
| 1735 | "deprecated and will result in "PyErr_WarnEx(PyExc_DeprecationWarning,"Numeric-style type codes are " "deprecated and will result in " "an error in the future.",1 ) | |||
| 1736 | "an error in the future.")PyErr_WarnEx(PyExc_DeprecationWarning,"Numeric-style type codes are " "deprecated and will result in " "an error in the future.",1 ) < 0) { | |||
| 1737 | goto fail; | |||
| 1738 | } | |||
| 1739 | } | |||
| 1740 | } | |||
| 1741 | /* | |||
| 1742 | * Probably only ever dispatches to `_convert_from_type`, but who | |||
| 1743 | * knows what users are injecting into `np.typeDict`. | |||
| 1744 | */ | |||
| 1745 | return _convert_from_any(item, align); | |||
| 1746 | } | |||
| 1747 | ||||
| 1748 | if (PyDataType_ISUNSIZED(ret)((ret)->elsize == 0 && !(((PyArray_Descr *)(ret))-> names != ((void*)0))) && ret->elsize != elsize) { | |||
| 1749 | PyArray_DESCR_REPLACE(ret)do { PyArray_Descr *_new_; _new_ = PyArray_DescrNew(ret); _Py_XDECREF (((PyObject*)(ret))); ret = _new_; } while(0); | |||
| 1750 | if (ret == NULL((void*)0)) { | |||
| 1751 | return NULL((void*)0); | |||
| 1752 | } | |||
| 1753 | ret->elsize = elsize; | |||
| 1754 | } | |||
| 1755 | if (endian != '=' && PyArray_ISNBO(endian)((endian) != '>')) { | |||
| 1756 | endian = '='; | |||
| 1757 | } | |||
| 1758 | if (endian != '=' && ret->byteorder != '|' && ret->byteorder != endian) { | |||
| 1759 | PyArray_DESCR_REPLACE(ret)do { PyArray_Descr *_new_; _new_ = PyArray_DescrNew(ret); _Py_XDECREF (((PyObject*)(ret))); ret = _new_; } while(0); | |||
| 1760 | if (ret == NULL((void*)0)) { | |||
| 1761 | return NULL((void*)0); | |||
| 1762 | } | |||
| 1763 | ret->byteorder = endian; | |||
| 1764 | } | |||
| 1765 | return ret; | |||
| 1766 | ||||
| 1767 | fail: | |||
| 1768 | PyErr_Format(PyExc_TypeError, "data type %R not understood", obj); | |||
| 1769 | return NULL((void*)0); | |||
| 1770 | } | |||
| 1771 | ||||
| 1772 | /** Array Descr Objects for dynamic types **/ | |||
| 1773 | ||||
| 1774 | /* | |||
| 1775 | * There are some statically-defined PyArray_Descr objects corresponding | |||
| 1776 | * to the basic built-in types. | |||
| 1777 | * These can and should be DECREF'd and INCREF'd as appropriate, anyway. | |||
| 1778 | * If a mistake is made in reference counting, deallocation on these | |||
| 1779 | * builtins will be attempted leading to problems. | |||
| 1780 | * | |||
| 1781 | * This lets us deal with all PyArray_Descr objects using reference | |||
| 1782 | * counting (regardless of whether they are statically or dynamically | |||
| 1783 | * allocated). | |||
| 1784 | */ | |||
| 1785 | ||||
| 1786 | /*NUMPY_API | |||
| 1787 | * base cannot be NULL | |||
| 1788 | */ | |||
| 1789 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr * | |||
| 1790 | PyArray_DescrNew(PyArray_Descr *base) | |||
| 1791 | { | |||
| 1792 | PyArray_Descr *newdescr = PyObject_New(PyArray_Descr, Py_TYPE(base))( (PyArray_Descr *) _PyObject_New((((PyObject*)(base))->ob_type )) ); | |||
| 1793 | ||||
| 1794 | if (newdescr == NULL((void*)0)) { | |||
| 1795 | return NULL((void*)0); | |||
| 1796 | } | |||
| 1797 | /* Don't copy PyObject_HEAD part */ | |||
| 1798 | memcpy((char *)newdescr + sizeof(PyObject), | |||
| 1799 | (char *)base + sizeof(PyObject), | |||
| 1800 | sizeof(PyArray_Descr) - sizeof(PyObject)); | |||
| 1801 | ||||
| 1802 | /* | |||
| 1803 | * The c_metadata has a by-value ownership model, need to clone it | |||
| 1804 | * (basically a deep copy, but the auxdata clone function has some | |||
| 1805 | * flexibility still) so the new PyArray_Descr object owns | |||
| 1806 | * a copy of the data. Having both 'base' and 'newdescr' point to | |||
| 1807 | * the same auxdata pointer would cause a double-free of memory. | |||
| 1808 | */ | |||
| 1809 | if (base->c_metadata != NULL((void*)0)) { | |||
| 1810 | newdescr->c_metadata = NPY_AUXDATA_CLONE(base->c_metadata)((base->c_metadata)->clone(base->c_metadata)); | |||
| 1811 | if (newdescr->c_metadata == NULL((void*)0)) { | |||
| 1812 | PyErr_NoMemory(); | |||
| 1813 | /* TODO: This seems wrong, as the old fields get decref'd? */ | |||
| 1814 | Py_DECREF(newdescr)_Py_DECREF(((PyObject*)(newdescr))); | |||
| 1815 | return NULL((void*)0); | |||
| 1816 | } | |||
| 1817 | } | |||
| 1818 | ||||
| 1819 | if (newdescr->fields == Py_None(&_Py_NoneStruct)) { | |||
| 1820 | newdescr->fields = NULL((void*)0); | |||
| 1821 | } | |||
| 1822 | Py_XINCREF(newdescr->fields)_Py_XINCREF(((PyObject*)(newdescr->fields))); | |||
| 1823 | Py_XINCREF(newdescr->names)_Py_XINCREF(((PyObject*)(newdescr->names))); | |||
| 1824 | if (newdescr->subarray) { | |||
| 1825 | newdescr->subarray = PyArray_mallocPyMem_RawMalloc(sizeof(PyArray_ArrayDescr)); | |||
| 1826 | if (newdescr->subarray == NULL((void*)0)) { | |||
| 1827 | Py_DECREF(newdescr)_Py_DECREF(((PyObject*)(newdescr))); | |||
| 1828 | return (PyArray_Descr *)PyErr_NoMemory(); | |||
| 1829 | } | |||
| 1830 | memcpy(newdescr->subarray, base->subarray, sizeof(PyArray_ArrayDescr)); | |||
| 1831 | Py_INCREF(newdescr->subarray->shape)_Py_INCREF(((PyObject*)(newdescr->subarray->shape))); | |||
| 1832 | Py_INCREF(newdescr->subarray->base)_Py_INCREF(((PyObject*)(newdescr->subarray->base))); | |||
| 1833 | } | |||
| 1834 | Py_XINCREF(newdescr->typeobj)_Py_XINCREF(((PyObject*)(newdescr->typeobj))); | |||
| 1835 | Py_XINCREF(newdescr->metadata)_Py_XINCREF(((PyObject*)(newdescr->metadata))); | |||
| 1836 | newdescr->hash = -1; | |||
| 1837 | ||||
| 1838 | return newdescr; | |||
| 1839 | } | |||
| 1840 | ||||
| 1841 | /* | |||
| 1842 | * should never be called for builtin-types unless | |||
| 1843 | * there is a reference-count problem | |||
| 1844 | */ | |||
| 1845 | static void | |||
| 1846 | arraydescr_dealloc(PyArray_Descr *self) | |||
| 1847 | { | |||
| 1848 | if (self->fields == Py_None(&_Py_NoneStruct)) { | |||
| 1849 | fprintf(stderr, "*** Reference count error detected: "__fprintf_chk (stderr, 2 - 1, "*** Reference count error detected: " "an attempt was made to deallocate the dtype %d (%c) ***\n", self->type_num, self->type) | |||
| 1850 | "an attempt was made to deallocate the dtype %d (%c) ***\n",__fprintf_chk (stderr, 2 - 1, "*** Reference count error detected: " "an attempt was made to deallocate the dtype %d (%c) ***\n", self->type_num, self->type) | |||
| 1851 | self->type_num, self->type)__fprintf_chk (stderr, 2 - 1, "*** Reference count error detected: " "an attempt was made to deallocate the dtype %d (%c) ***\n", self->type_num, self->type); | |||
| 1852 | assert(0)((void) (0)); | |||
| 1853 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
| 1854 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
| 1855 | return; | |||
| 1856 | } | |||
| 1857 | Py_XDECREF(self->typeobj)_Py_XDECREF(((PyObject*)(self->typeobj))); | |||
| 1858 | Py_XDECREF(self->names)_Py_XDECREF(((PyObject*)(self->names))); | |||
| 1859 | Py_XDECREF(self->fields)_Py_XDECREF(((PyObject*)(self->fields))); | |||
| 1860 | if (self->subarray) { | |||
| 1861 | Py_XDECREF(self->subarray->shape)_Py_XDECREF(((PyObject*)(self->subarray->shape))); | |||
| 1862 | Py_DECREF(self->subarray->base)_Py_DECREF(((PyObject*)(self->subarray->base))); | |||
| 1863 | PyArray_freePyMem_RawFree(self->subarray); | |||
| 1864 | } | |||
| 1865 | Py_XDECREF(self->metadata)_Py_XDECREF(((PyObject*)(self->metadata))); | |||
| 1866 | NPY_AUXDATA_FREE(self->c_metadata)do { if ((self->c_metadata) != ((void*)0)) { (self->c_metadata )->free(self->c_metadata); } } while(0); | |||
| 1867 | self->c_metadata = NULL((void*)0); | |||
| 1868 | Py_TYPE(self)(((PyObject*)(self))->ob_type)->tp_free((PyObject *)self); | |||
| 1869 | } | |||
| 1870 | ||||
| 1871 | /* | |||
| 1872 | * we need to be careful about setting attributes because these | |||
| 1873 | * objects are pointed to by arrays that depend on them for interpreting | |||
| 1874 | * data. Currently no attributes of data-type objects can be set | |||
| 1875 | * directly except names. | |||
| 1876 | */ | |||
| 1877 | static PyMemberDef arraydescr_members[] = { | |||
| 1878 | {"type", | |||
| 1879 | T_OBJECT6, offsetof(PyArray_Descr, typeobj)__builtin_offsetof(PyArray_Descr, typeobj), READONLY1, NULL((void*)0)}, | |||
| 1880 | {"kind", | |||
| 1881 | T_CHAR7, offsetof(PyArray_Descr, kind)__builtin_offsetof(PyArray_Descr, kind), READONLY1, NULL((void*)0)}, | |||
| 1882 | {"char", | |||
| 1883 | T_CHAR7, offsetof(PyArray_Descr, type)__builtin_offsetof(PyArray_Descr, type), READONLY1, NULL((void*)0)}, | |||
| 1884 | {"num", | |||
| 1885 | T_INT1, offsetof(PyArray_Descr, type_num)__builtin_offsetof(PyArray_Descr, type_num), READONLY1, NULL((void*)0)}, | |||
| 1886 | {"byteorder", | |||
| 1887 | T_CHAR7, offsetof(PyArray_Descr, byteorder)__builtin_offsetof(PyArray_Descr, byteorder), READONLY1, NULL((void*)0)}, | |||
| 1888 | {"itemsize", | |||
| 1889 | T_INT1, offsetof(PyArray_Descr, elsize)__builtin_offsetof(PyArray_Descr, elsize), READONLY1, NULL((void*)0)}, | |||
| 1890 | {"alignment", | |||
| 1891 | T_INT1, offsetof(PyArray_Descr, alignment)__builtin_offsetof(PyArray_Descr, alignment), READONLY1, NULL((void*)0)}, | |||
| 1892 | {"flags", | |||
| 1893 | T_BYTE8, offsetof(PyArray_Descr, flags)__builtin_offsetof(PyArray_Descr, flags), READONLY1, NULL((void*)0)}, | |||
| 1894 | {NULL((void*)0), 0, 0, 0, NULL((void*)0)}, | |||
| 1895 | }; | |||
| 1896 | ||||
| 1897 | static PyObject * | |||
| 1898 | arraydescr_subdescr_get(PyArray_Descr *self) | |||
| 1899 | { | |||
| 1900 | if (!PyDataType_HASSUBARRAY(self)((self)->subarray != ((void*)0))) { | |||
| 1901 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 1902 | } | |||
| 1903 | return Py_BuildValue_Py_BuildValue_SizeT("OO", | |||
| 1904 | (PyObject *)self->subarray->base, self->subarray->shape); | |||
| 1905 | } | |||
| 1906 | ||||
| 1907 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | |||
| 1908 | arraydescr_protocol_typestr_get(PyArray_Descr *self) | |||
| 1909 | { | |||
| 1910 | char basic_ = self->kind; | |||
| 1911 | char endian = self->byteorder; | |||
| 1912 | int size = self->elsize; | |||
| 1913 | PyObject *ret; | |||
| 1914 | ||||
| 1915 | if (endian == '=') { | |||
| 1916 | endian = '<'; | |||
| 1917 | if (!PyArray_IsNativeByteOrder(endian)((endian) != '>')) { | |||
| 1918 | endian = '>'; | |||
| 1919 | } | |||
| 1920 | } | |||
| 1921 | if (self->type_num == NPY_UNICODE) { | |||
| 1922 | size >>= 2; | |||
| 1923 | } | |||
| 1924 | if (self->type_num == NPY_OBJECT) { | |||
| 1925 | ret = PyUnicode_FromFormat("%c%c", endian, basic_); | |||
| 1926 | } | |||
| 1927 | else { | |||
| 1928 | ret = PyUnicode_FromFormat("%c%c%d", endian, basic_, size); | |||
| 1929 | } | |||
| 1930 | if (ret == NULL((void*)0)) { | |||
| 1931 | return NULL((void*)0); | |||
| 1932 | } | |||
| 1933 | ||||
| 1934 | if (PyDataType_ISDATETIME(self)(((((PyArray_Descr*)(self))->type_num) >=NPY_DATETIME) && ((((PyArray_Descr*)(self))->type_num) <=NPY_TIMEDELTA) )) { | |||
| 1935 | PyArray_DatetimeMetaData *meta; | |||
| 1936 | meta = get_datetime_metadata_from_dtype(self); | |||
| 1937 | if (meta == NULL((void*)0)) { | |||
| 1938 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 1939 | return NULL((void*)0); | |||
| 1940 | } | |||
| 1941 | PyObject *umeta = metastr_to_unicode(meta, 0); | |||
| 1942 | if (umeta == NULL((void*)0)) { | |||
| 1943 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 1944 | return NULL((void*)0); | |||
| 1945 | } | |||
| 1946 | ||||
| 1947 | Py_SETREF(ret, PyUnicode_Concat(ret, umeta))do { PyObject *_py_tmp = ((PyObject*)(ret)); (ret) = (PyUnicode_Concat (ret, umeta)); _Py_DECREF(((PyObject*)(_py_tmp))); } while (0 ); | |||
| 1948 | Py_DECREF(umeta)_Py_DECREF(((PyObject*)(umeta))); | |||
| 1949 | } | |||
| 1950 | return ret; | |||
| 1951 | } | |||
| 1952 | ||||
| 1953 | static PyObject * | |||
| 1954 | arraydescr_name_get(PyArray_Descr *self) | |||
| 1955 | { | |||
| 1956 | /* let python handle this */ | |||
| 1957 | PyObject *_numpy_dtype; | |||
| 1958 | PyObject *res; | |||
| 1959 | _numpy_dtype = PyImport_ImportModule("numpy.core._dtype"); | |||
| 1960 | if (_numpy_dtype == NULL((void*)0)) { | |||
| 1961 | return NULL((void*)0); | |||
| 1962 | } | |||
| 1963 | res = PyObject_CallMethod_PyObject_CallMethod_SizeT(_numpy_dtype, "_name_get", "O", self); | |||
| 1964 | Py_DECREF(_numpy_dtype)_Py_DECREF(((PyObject*)(_numpy_dtype))); | |||
| 1965 | return res; | |||
| 1966 | } | |||
| 1967 | ||||
| 1968 | static PyObject * | |||
| 1969 | arraydescr_base_get(PyArray_Descr *self) | |||
| 1970 | { | |||
| 1971 | if (!PyDataType_HASSUBARRAY(self)((self)->subarray != ((void*)0))) { | |||
| 1972 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
| 1973 | return (PyObject *)self; | |||
| 1974 | } | |||
| 1975 | Py_INCREF(self->subarray->base)_Py_INCREF(((PyObject*)(self->subarray->base))); | |||
| 1976 | return (PyObject *)(self->subarray->base); | |||
| 1977 | } | |||
| 1978 | ||||
| 1979 | static PyObject * | |||
| 1980 | arraydescr_shape_get(PyArray_Descr *self) | |||
| 1981 | { | |||
| 1982 | if (!PyDataType_HASSUBARRAY(self)((self)->subarray != ((void*)0))) { | |||
| 1983 | return PyTuple_New(0); | |||
| 1984 | } | |||
| 1985 | assert(PyTuple_Check(self->subarray->shape))((void) (0)); | |||
| 1986 | Py_INCREF(self->subarray->shape)_Py_INCREF(((PyObject*)(self->subarray->shape))); | |||
| 1987 | return self->subarray->shape; | |||
| 1988 | } | |||
| 1989 | ||||
| 1990 | static PyObject * | |||
| 1991 | arraydescr_ndim_get(PyArray_Descr *self) | |||
| 1992 | { | |||
| 1993 | Py_ssize_t ndim; | |||
| 1994 | ||||
| 1995 | if (!PyDataType_HASSUBARRAY(self)((self)->subarray != ((void*)0))) { | |||
| 1996 | return PyLong_FromLong(0); | |||
| 1997 | } | |||
| 1998 | ||||
| 1999 | /* | |||
| 2000 | * PyTuple_Size has built in check | |||
| 2001 | * for tuple argument | |||
| 2002 | */ | |||
| 2003 | ndim = PyTuple_Size(self->subarray->shape); | |||
| 2004 | return PyLong_FromLong(ndim); | |||
| 2005 | } | |||
| 2006 | ||||
| 2007 | ||||
| 2008 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyObject * | |||
| 2009 | arraydescr_protocol_descr_get(PyArray_Descr *self) | |||
| 2010 | { | |||
| 2011 | PyObject *dobj, *res; | |||
| 2012 | PyObject *_numpy_internal; | |||
| 2013 | ||||
| 2014 | if (!PyDataType_HASFIELDS(self)(((PyArray_Descr *)(self))->names != ((void*)0))) { | |||
| 2015 | /* get default */ | |||
| 2016 | dobj = PyTuple_New(2); | |||
| 2017 | if (dobj == NULL((void*)0)) { | |||
| 2018 | return NULL((void*)0); | |||
| 2019 | } | |||
| 2020 | PyTuple_SET_ITEM(dobj, 0, PyUnicode_FromString(""))PyTuple_SetItem(dobj, 0, PyUnicode_FromString("")); | |||
| 2021 | PyTuple_SET_ITEM(dobj, 1, arraydescr_protocol_typestr_get(self))PyTuple_SetItem(dobj, 1, arraydescr_protocol_typestr_get(self )); | |||
| 2022 | res = PyList_New(1); | |||
| 2023 | if (res == NULL((void*)0)) { | |||
| 2024 | Py_DECREF(dobj)_Py_DECREF(((PyObject*)(dobj))); | |||
| 2025 | return NULL((void*)0); | |||
| 2026 | } | |||
| 2027 | PyList_SET_ITEM(res, 0, dobj)PyList_SetItem(res, 0, dobj); | |||
| 2028 | return res; | |||
| 2029 | } | |||
| 2030 | ||||
| 2031 | _numpy_internal = PyImport_ImportModule("numpy.core._internal"); | |||
| 2032 | if (_numpy_internal == NULL((void*)0)) { | |||
| 2033 | return NULL((void*)0); | |||
| 2034 | } | |||
| 2035 | res = PyObject_CallMethod_PyObject_CallMethod_SizeT(_numpy_internal, "_array_descr", "O", self); | |||
| 2036 | Py_DECREF(_numpy_internal)_Py_DECREF(((PyObject*)(_numpy_internal))); | |||
| 2037 | return res; | |||
| 2038 | } | |||
| 2039 | ||||
| 2040 | /* | |||
| 2041 | * returns 1 for a builtin type | |||
| 2042 | * and 2 for a user-defined data-type descriptor | |||
| 2043 | * return 0 if neither (i.e. it's a copy of one) | |||
| 2044 | */ | |||
| 2045 | static PyObject * | |||
| 2046 | arraydescr_isbuiltin_get(PyArray_Descr *self) | |||
| 2047 | { | |||
| 2048 | long val; | |||
| 2049 | val = 0; | |||
| 2050 | if (self->fields == Py_None(&_Py_NoneStruct)) { | |||
| 2051 | val = 1; | |||
| 2052 | } | |||
| 2053 | if (PyTypeNum_ISUSERDEF(self->type_num)(((self->type_num) >= NPY_USERDEF) && ((self-> type_num) < NPY_USERDEF+ NPY_NUMUSERTYPES))) { | |||
| 2054 | val = 2; | |||
| 2055 | } | |||
| 2056 | return PyLong_FromLong(val); | |||
| 2057 | } | |||
| 2058 | ||||
| 2059 | static int | |||
| 2060 | _arraydescr_isnative(PyArray_Descr *self) | |||
| 2061 | { | |||
| 2062 | if (!PyDataType_HASFIELDS(self)(((PyArray_Descr *)(self))->names != ((void*)0))) { | |||
| 2063 | return PyArray_ISNBO(self->byteorder)((self->byteorder) != '>'); | |||
| 2064 | } | |||
| 2065 | else { | |||
| 2066 | PyObject *key, *value, *title = NULL((void*)0); | |||
| 2067 | PyArray_Descr *new; | |||
| 2068 | int offset; | |||
| 2069 | Py_ssize_t pos = 0; | |||
| 2070 | while (PyDict_Next(self->fields, &pos, &key, &value)) { | |||
| 2071 | if (NPY_TITLE_KEY(key, value)(NPY_TITLE_KEY_check((key), (value)))) { | |||
| 2072 | continue; | |||
| 2073 | } | |||
| 2074 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(value, "Oi|O", &new, &offset, &title)) { | |||
| 2075 | return -1; | |||
| 2076 | } | |||
| 2077 | if (!_arraydescr_isnative(new)) { | |||
| 2078 | return 0; | |||
| 2079 | } | |||
| 2080 | } | |||
| 2081 | } | |||
| 2082 | return 1; | |||
| 2083 | } | |||
| 2084 | ||||
| 2085 | /* | |||
| 2086 | * return Py_True if this data-type descriptor | |||
| 2087 | * has native byteorder if no fields are defined | |||
| 2088 | * | |||
| 2089 | * or if all sub-fields have native-byteorder if | |||
| 2090 | * fields are defined | |||
| 2091 | */ | |||
| 2092 | static PyObject * | |||
| 2093 | arraydescr_isnative_get(PyArray_Descr *self) | |||
| 2094 | { | |||
| 2095 | PyObject *ret; | |||
| 2096 | int retval; | |||
| 2097 | retval = _arraydescr_isnative(self); | |||
| 2098 | if (retval == -1) { | |||
| 2099 | return NULL((void*)0); | |||
| 2100 | } | |||
| 2101 | ret = retval ? Py_True((PyObject *) &_Py_TrueStruct) : Py_False((PyObject *) &_Py_FalseStruct); | |||
| 2102 | Py_INCREF(ret)_Py_INCREF(((PyObject*)(ret))); | |||
| 2103 | return ret; | |||
| 2104 | } | |||
| 2105 | ||||
| 2106 | static PyObject * | |||
| 2107 | arraydescr_isalignedstruct_get(PyArray_Descr *self) | |||
| 2108 | { | |||
| 2109 | PyObject *ret; | |||
| 2110 | ret = (self->flags&NPY_ALIGNED_STRUCT0x80) ? Py_True((PyObject *) &_Py_TrueStruct) : Py_False((PyObject *) &_Py_FalseStruct); | |||
| 2111 | Py_INCREF(ret)_Py_INCREF(((PyObject*)(ret))); | |||
| 2112 | return ret; | |||
| 2113 | } | |||
| 2114 | ||||
| 2115 | static PyObject * | |||
| 2116 | arraydescr_fields_get(PyArray_Descr *self) | |||
| 2117 | { | |||
| 2118 | if (!PyDataType_HASFIELDS(self)(((PyArray_Descr *)(self))->names != ((void*)0))) { | |||
| 2119 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 2120 | } | |||
| 2121 | return PyDictProxy_New(self->fields); | |||
| 2122 | } | |||
| 2123 | ||||
| 2124 | static PyObject * | |||
| 2125 | arraydescr_metadata_get(PyArray_Descr *self) | |||
| 2126 | { | |||
| 2127 | if (self->metadata == NULL((void*)0)) { | |||
| 2128 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 2129 | } | |||
| 2130 | return PyDictProxy_New(self->metadata); | |||
| 2131 | } | |||
| 2132 | ||||
| 2133 | static PyObject * | |||
| 2134 | arraydescr_hasobject_get(PyArray_Descr *self) | |||
| 2135 | { | |||
| 2136 | if (PyDataType_FLAGCHK(self, NPY_ITEM_HASOBJECT)(((self)->flags & (0x01)) == (0x01))) { | |||
| 2137 | Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct )))), ((PyObject *) &_Py_TrueStruct); | |||
| 2138 | } | |||
| 2139 | else { | |||
| 2140 | Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct )))), ((PyObject *) &_Py_FalseStruct); | |||
| 2141 | } | |||
| 2142 | } | |||
| 2143 | ||||
| 2144 | static PyObject * | |||
| 2145 | arraydescr_names_get(PyArray_Descr *self) | |||
| 2146 | { | |||
| 2147 | if (!PyDataType_HASFIELDS(self)(((PyArray_Descr *)(self))->names != ((void*)0))) { | |||
| 2148 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 2149 | } | |||
| 2150 | Py_INCREF(self->names)_Py_INCREF(((PyObject*)(self->names))); | |||
| 2151 | return self->names; | |||
| 2152 | } | |||
| 2153 | ||||
| 2154 | static int | |||
| 2155 | arraydescr_names_set(PyArray_Descr *self, PyObject *val) | |||
| 2156 | { | |||
| 2157 | int N = 0; | |||
| 2158 | int i; | |||
| 2159 | PyObject *new_names; | |||
| 2160 | PyObject *new_fields; | |||
| 2161 | ||||
| 2162 | if (val == NULL((void*)0)) { | |||
| 2163 | PyErr_SetString(PyExc_AttributeError, | |||
| 2164 | "Cannot delete dtype names attribute"); | |||
| 2165 | return -1; | |||
| 2166 | } | |||
| 2167 | if (!PyDataType_HASFIELDS(self)(((PyArray_Descr *)(self))->names != ((void*)0))) { | |||
| 2168 | PyErr_SetString(PyExc_ValueError, | |||
| 2169 | "there are no fields defined"); | |||
| 2170 | return -1; | |||
| 2171 | } | |||
| 2172 | ||||
| 2173 | /* | |||
| 2174 | * FIXME | |||
| 2175 | * | |||
| 2176 | * This deprecation has been temporarily removed for the NumPy 1.7 | |||
| 2177 | * release. It should be re-added after the 1.7 branch is done, | |||
| 2178 | * and a convenience API to replace the typical use-cases for | |||
| 2179 | * mutable names should be implemented. | |||
| 2180 | * | |||
| 2181 | * if (DEPRECATE("Setting NumPy dtype names is deprecated, the dtype " | |||
| 2182 | * "will become immutable in a future version") < 0) { | |||
| 2183 | * return -1; | |||
| 2184 | * } | |||
| 2185 | */ | |||
| 2186 | ||||
| 2187 | N = PyTuple_GET_SIZE(self->names)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(self->names ))))->ob_size); | |||
| 2188 | if (!PySequence_Check(val) || PyObject_Size((PyObject *)val) != N) { | |||
| 2189 | PyErr_Format(PyExc_ValueError, | |||
| 2190 | "must replace all names at once with a sequence of length %d", | |||
| 2191 | N); | |||
| 2192 | return -1; | |||
| 2193 | } | |||
| 2194 | /* Make sure all entries are strings */ | |||
| 2195 | for (i = 0; i < N; i++) { | |||
| 2196 | PyObject *item; | |||
| 2197 | int valid = 1; | |||
| 2198 | item = PySequence_GetItem(val, i); | |||
| 2199 | valid = PyUnicode_Check(item)((((((PyObject*)(item))->ob_type))->tp_flags & ((1UL << 28))) != 0); | |||
| 2200 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
| 2201 | if (!valid) { | |||
| 2202 | PyErr_Format(PyExc_ValueError, | |||
| 2203 | "item #%d of names is of type %s and not string", | |||
| 2204 | i, Py_TYPE(item)(((PyObject*)(item))->ob_type)->tp_name); | |||
| 2205 | return -1; | |||
| 2206 | } | |||
| 2207 | } | |||
| 2208 | /* Invalidate cached hash value */ | |||
| 2209 | self->hash = -1; | |||
| 2210 | /* Update dictionary keys in fields */ | |||
| 2211 | new_names = PySequence_Tuple(val); | |||
| 2212 | if (new_names == NULL((void*)0)) { | |||
| 2213 | return -1; | |||
| 2214 | } | |||
| 2215 | new_fields = PyDict_New(); | |||
| 2216 | if (new_fields == NULL((void*)0)) { | |||
| 2217 | Py_DECREF(new_names)_Py_DECREF(((PyObject*)(new_names))); | |||
| 2218 | return -1; | |||
| 2219 | } | |||
| 2220 | for (i = 0; i < N; i++) { | |||
| 2221 | PyObject *key; | |||
| 2222 | PyObject *item; | |||
| 2223 | PyObject *new_key; | |||
| 2224 | int ret; | |||
| 2225 | key = PyTuple_GET_ITEM(self->names, i)((((void) (0)), (PyTupleObject *)(self->names))->ob_item [i]); | |||
| 2226 | /* Borrowed references to item and new_key */ | |||
| 2227 | item = PyDict_GetItemWithError(self->fields, key); | |||
| 2228 | if (item == NULL((void*)0)) { | |||
| 2229 | if (!PyErr_Occurred()) { | |||
| 2230 | /* fields was missing the name it claimed to contain */ | |||
| 2231 | PyErr_BadInternalCall()_PyErr_BadInternalCall("/tmp/pyrefcon/numpy/numpy/core/src/multiarray/descriptor.c" , 2231); | |||
| 2232 | } | |||
| 2233 | Py_DECREF(new_names)_Py_DECREF(((PyObject*)(new_names))); | |||
| 2234 | Py_DECREF(new_fields)_Py_DECREF(((PyObject*)(new_fields))); | |||
| 2235 | return -1; | |||
| 2236 | } | |||
| 2237 | new_key = PyTuple_GET_ITEM(new_names, i)((((void) (0)), (PyTupleObject *)(new_names))->ob_item[i]); | |||
| 2238 | /* Check for duplicates */ | |||
| 2239 | ret = PyDict_Contains(new_fields, new_key); | |||
| 2240 | if (ret < 0) { | |||
| 2241 | Py_DECREF(new_names)_Py_DECREF(((PyObject*)(new_names))); | |||
| 2242 | Py_DECREF(new_fields)_Py_DECREF(((PyObject*)(new_fields))); | |||
| 2243 | return -1; | |||
| 2244 | } | |||
| 2245 | else if (ret != 0) { | |||
| 2246 | PyErr_SetString(PyExc_ValueError, "Duplicate field names given."); | |||
| 2247 | Py_DECREF(new_names)_Py_DECREF(((PyObject*)(new_names))); | |||
| 2248 | Py_DECREF(new_fields)_Py_DECREF(((PyObject*)(new_fields))); | |||
| 2249 | return -1; | |||
| 2250 | } | |||
| 2251 | if (PyDict_SetItem(new_fields, new_key, item) < 0) { | |||
| 2252 | Py_DECREF(new_names)_Py_DECREF(((PyObject*)(new_names))); | |||
| 2253 | Py_DECREF(new_fields)_Py_DECREF(((PyObject*)(new_fields))); | |||
| 2254 | return -1; | |||
| 2255 | } | |||
| 2256 | } | |||
| 2257 | ||||
| 2258 | /* Replace names */ | |||
| 2259 | Py_DECREF(self->names)_Py_DECREF(((PyObject*)(self->names))); | |||
| 2260 | self->names = new_names; | |||
| 2261 | ||||
| 2262 | /* Replace fields */ | |||
| 2263 | Py_DECREF(self->fields)_Py_DECREF(((PyObject*)(self->fields))); | |||
| 2264 | self->fields = new_fields; | |||
| 2265 | ||||
| 2266 | return 0; | |||
| 2267 | } | |||
| 2268 | ||||
| 2269 | static PyGetSetDef arraydescr_getsets[] = { | |||
| 2270 | {"subdtype", | |||
| 2271 | (getter)arraydescr_subdescr_get, | |||
| 2272 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2273 | {"descr", | |||
| 2274 | (getter)arraydescr_protocol_descr_get, | |||
| 2275 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2276 | {"str", | |||
| 2277 | (getter)arraydescr_protocol_typestr_get, | |||
| 2278 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2279 | {"name", | |||
| 2280 | (getter)arraydescr_name_get, | |||
| 2281 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2282 | {"base", | |||
| 2283 | (getter)arraydescr_base_get, | |||
| 2284 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2285 | {"shape", | |||
| 2286 | (getter)arraydescr_shape_get, | |||
| 2287 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2288 | {"ndim", | |||
| 2289 | (getter)arraydescr_ndim_get, | |||
| 2290 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2291 | {"isbuiltin", | |||
| 2292 | (getter)arraydescr_isbuiltin_get, | |||
| 2293 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2294 | {"isnative", | |||
| 2295 | (getter)arraydescr_isnative_get, | |||
| 2296 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2297 | {"isalignedstruct", | |||
| 2298 | (getter)arraydescr_isalignedstruct_get, | |||
| 2299 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2300 | {"fields", | |||
| 2301 | (getter)arraydescr_fields_get, | |||
| 2302 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2303 | {"metadata", | |||
| 2304 | (getter)arraydescr_metadata_get, | |||
| 2305 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2306 | {"names", | |||
| 2307 | (getter)arraydescr_names_get, | |||
| 2308 | (setter)arraydescr_names_set, | |||
| 2309 | NULL((void*)0), NULL((void*)0)}, | |||
| 2310 | {"hasobject", | |||
| 2311 | (getter)arraydescr_hasobject_get, | |||
| 2312 | NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2313 | {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)}, | |||
| 2314 | }; | |||
| 2315 | ||||
| 2316 | static PyObject * | |||
| 2317 | arraydescr_new(PyTypeObject *subtype, | |||
| 2318 | PyObject *args, PyObject *kwds) | |||
| 2319 | { | |||
| 2320 | if (subtype != &PyArrayDescr_Type(*(PyTypeObject *)(&PyArrayDescr_TypeFull))) { | |||
| 2321 | /* The DTypeMeta class should prevent this from happening. */ | |||
| 2322 | PyErr_Format(PyExc_SystemError, | |||
| 2323 | "'%S' must not inherit np.dtype.__new__().", subtype); | |||
| 2324 | return NULL((void*)0); | |||
| 2325 | } | |||
| 2326 | ||||
| 2327 | PyObject *odescr, *metadata=NULL((void*)0); | |||
| 2328 | PyArray_Descr *descr, *conv; | |||
| 2329 | npy_bool align = NPY_FALSE0; | |||
| 2330 | npy_bool copy = NPY_FALSE0; | |||
| 2331 | npy_bool copied = NPY_FALSE0; | |||
| 2332 | ||||
| 2333 | static char *kwlist[] = {"dtype", "align", "copy", "metadata", NULL((void*)0)}; | |||
| 2334 | ||||
| 2335 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, kwds, "O|O&O&O!:dtype", kwlist, | |||
| 2336 | &odescr, | |||
| 2337 | PyArray_BoolConverter, &align, | |||
| 2338 | PyArray_BoolConverter, ©, | |||
| 2339 | &PyDict_Type, &metadata)) { | |||
| 2340 | return NULL((void*)0); | |||
| 2341 | } | |||
| 2342 | ||||
| 2343 | conv = _convert_from_any(odescr, align); | |||
| 2344 | if (conv == NULL((void*)0)) { | |||
| 2345 | return NULL((void*)0); | |||
| 2346 | } | |||
| 2347 | ||||
| 2348 | /* Get a new copy of it unless it's already a copy */ | |||
| 2349 | if (copy && conv->fields == Py_None(&_Py_NoneStruct)) { | |||
| 2350 | descr = PyArray_DescrNew(conv); | |||
| 2351 | Py_DECREF(conv)_Py_DECREF(((PyObject*)(conv))); | |||
| 2352 | conv = descr; | |||
| 2353 | copied = NPY_TRUE1; | |||
| 2354 | } | |||
| 2355 | ||||
| 2356 | if ((metadata != NULL((void*)0))) { | |||
| 2357 | /* | |||
| 2358 | * We need to be sure to make a new copy of the data-type and any | |||
| 2359 | * underlying dictionary | |||
| 2360 | */ | |||
| 2361 | if (!copied) { | |||
| 2362 | copied = NPY_TRUE1; | |||
| 2363 | descr = PyArray_DescrNew(conv); | |||
| 2364 | Py_DECREF(conv)_Py_DECREF(((PyObject*)(conv))); | |||
| 2365 | conv = descr; | |||
| 2366 | } | |||
| 2367 | if ((conv->metadata != NULL((void*)0))) { | |||
| 2368 | /* | |||
| 2369 | * Make a copy of the metadata before merging with the | |||
| 2370 | * input metadata so that this data-type descriptor has | |||
| 2371 | * it's own copy | |||
| 2372 | */ | |||
| 2373 | /* Save a reference */ | |||
| 2374 | odescr = conv->metadata; | |||
| 2375 | conv->metadata = PyDict_Copy(odescr); | |||
| 2376 | /* Decrement the old reference */ | |||
| 2377 | Py_DECREF(odescr)_Py_DECREF(((PyObject*)(odescr))); | |||
| 2378 | ||||
| 2379 | /* | |||
| 2380 | * Update conv->metadata with anything new in metadata | |||
| 2381 | * keyword, but do not over-write anything already there | |||
| 2382 | */ | |||
| 2383 | if (PyDict_Merge(conv->metadata, metadata, 0) != 0) { | |||
| 2384 | Py_DECREF(conv)_Py_DECREF(((PyObject*)(conv))); | |||
| 2385 | return NULL((void*)0); | |||
| 2386 | } | |||
| 2387 | } | |||
| 2388 | else { | |||
| 2389 | /* Make a copy of the input dictionary */ | |||
| 2390 | conv->metadata = PyDict_Copy(metadata); | |||
| 2391 | } | |||
| 2392 | } | |||
| 2393 | ||||
| 2394 | return (PyObject *)conv; | |||
| 2395 | } | |||
| 2396 | ||||
| 2397 | ||||
| 2398 | /* | |||
| 2399 | * Return a tuple of | |||
| 2400 | * (cleaned metadata dictionary, tuple with (str, num)) | |||
| 2401 | */ | |||
| 2402 | static PyObject * | |||
| 2403 | _get_pickleabletype_from_datetime_metadata(PyArray_Descr *dtype) | |||
| 2404 | { | |||
| 2405 | PyObject *ret, *dt_tuple; | |||
| 2406 | PyArray_DatetimeMetaData *meta; | |||
| 2407 | ||||
| 2408 | /* Create the 2-item tuple to return */ | |||
| 2409 | ret = PyTuple_New(2); | |||
| 2410 | if (ret == NULL((void*)0)) { | |||
| 2411 | return NULL((void*)0); | |||
| 2412 | } | |||
| 2413 | ||||
| 2414 | /* Store the metadata dictionary */ | |||
| 2415 | if (dtype->metadata != NULL((void*)0)) { | |||
| 2416 | Py_INCREF(dtype->metadata)_Py_INCREF(((PyObject*)(dtype->metadata))); | |||
| 2417 | PyTuple_SET_ITEM(ret, 0, dtype->metadata)PyTuple_SetItem(ret, 0, dtype->metadata); | |||
| 2418 | } else { | |||
| 2419 | PyTuple_SET_ITEM(ret, 0, PyDict_New())PyTuple_SetItem(ret, 0, PyDict_New()); | |||
| 2420 | } | |||
| 2421 | ||||
| 2422 | /* Convert the datetime metadata into a tuple */ | |||
| 2423 | meta = get_datetime_metadata_from_dtype(dtype); | |||
| 2424 | if (meta == NULL((void*)0)) { | |||
| 2425 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 2426 | return NULL((void*)0); | |||
| 2427 | } | |||
| 2428 | /* Use a 4-tuple that numpy 1.6 knows how to unpickle */ | |||
| 2429 | dt_tuple = PyTuple_New(4); | |||
| 2430 | if (dt_tuple == NULL((void*)0)) { | |||
| 2431 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 2432 | return NULL((void*)0); | |||
| 2433 | } | |||
| 2434 | PyTuple_SET_ITEM(dt_tuple, 0,PyTuple_SetItem(dt_tuple, 0, PyBytes_FromString(_datetime_strings [meta->base])) | |||
| 2435 | PyBytes_FromString(_datetime_strings[meta->base]))PyTuple_SetItem(dt_tuple, 0, PyBytes_FromString(_datetime_strings [meta->base])); | |||
| 2436 | PyTuple_SET_ITEM(dt_tuple, 1,PyTuple_SetItem(dt_tuple, 1, PyLong_FromLong(meta->num)) | |||
| 2437 | PyLong_FromLong(meta->num))PyTuple_SetItem(dt_tuple, 1, PyLong_FromLong(meta->num)); | |||
| 2438 | PyTuple_SET_ITEM(dt_tuple, 2,PyTuple_SetItem(dt_tuple, 2, PyLong_FromLong(1)) | |||
| 2439 | PyLong_FromLong(1))PyTuple_SetItem(dt_tuple, 2, PyLong_FromLong(1)); | |||
| 2440 | PyTuple_SET_ITEM(dt_tuple, 3,PyTuple_SetItem(dt_tuple, 3, PyLong_FromLong(1)) | |||
| 2441 | PyLong_FromLong(1))PyTuple_SetItem(dt_tuple, 3, PyLong_FromLong(1)); | |||
| 2442 | ||||
| 2443 | PyTuple_SET_ITEM(ret, 1, dt_tuple)PyTuple_SetItem(ret, 1, dt_tuple); | |||
| 2444 | ||||
| 2445 | return ret; | |||
| 2446 | } | |||
| 2447 | ||||
| 2448 | /* | |||
| 2449 | * return a tuple of (callable object, args, state). | |||
| 2450 | * | |||
| 2451 | * TODO: This method needs to change so that unpickling doesn't | |||
| 2452 | * use __setstate__. This is required for the dtype | |||
| 2453 | * to be an immutable object. | |||
| 2454 | */ | |||
| 2455 | static PyObject * | |||
| 2456 | arraydescr_reduce(PyArray_Descr *self, PyObject *NPY_UNUSED(args)(__NPY_UNUSED_TAGGEDargs) __attribute__ ((__unused__))) | |||
| 2457 | { | |||
| 2458 | /* | |||
| 2459 | * version number of this pickle type. Increment if we need to | |||
| 2460 | * change the format. Be sure to handle the old versions in | |||
| 2461 | * arraydescr_setstate. | |||
| 2462 | */ | |||
| 2463 | const int version = 4; | |||
| 2464 | PyObject *ret, *mod, *obj; | |||
| 2465 | PyObject *state; | |||
| 2466 | char endian; | |||
| 2467 | int elsize, alignment; | |||
| 2468 | ||||
| 2469 | ret = PyTuple_New(3); | |||
| 2470 | if (ret == NULL((void*)0)) { | |||
| 2471 | return NULL((void*)0); | |||
| 2472 | } | |||
| 2473 | mod = PyImport_ImportModule("numpy.core._multiarray_umath"); | |||
| 2474 | if (mod == NULL((void*)0)) { | |||
| 2475 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 2476 | return NULL((void*)0); | |||
| 2477 | } | |||
| 2478 | obj = PyObject_GetAttrString(mod, "dtype"); | |||
| 2479 | Py_DECREF(mod)_Py_DECREF(((PyObject*)(mod))); | |||
| 2480 | if (obj == NULL((void*)0)) { | |||
| 2481 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 2482 | return NULL((void*)0); | |||
| 2483 | } | |||
| 2484 | PyTuple_SET_ITEM(ret, 0, obj)PyTuple_SetItem(ret, 0, obj); | |||
| 2485 | if (PyTypeNum_ISUSERDEF(self->type_num)(((self->type_num) >= NPY_USERDEF) && ((self-> type_num) < NPY_USERDEF+ NPY_NUMUSERTYPES)) | |||
| 2486 | || ((self->type_num == NPY_VOID | |||
| 2487 | && self->typeobj != &PyVoidArrType_Type))) { | |||
| 2488 | obj = (PyObject *)self->typeobj; | |||
| 2489 | Py_INCREF(obj)_Py_INCREF(((PyObject*)(obj))); | |||
| 2490 | } | |||
| 2491 | else { | |||
| 2492 | elsize = self->elsize; | |||
| 2493 | if (self->type_num == NPY_UNICODE) { | |||
| 2494 | elsize >>= 2; | |||
| 2495 | } | |||
| 2496 | obj = PyUnicode_FromFormat("%c%d",self->kind, elsize); | |||
| 2497 | } | |||
| 2498 | PyTuple_SET_ITEM(ret, 1, Py_BuildValue("(NOO)", obj, Py_False, Py_True))PyTuple_SetItem(ret, 1, _Py_BuildValue_SizeT("(NOO)", obj, (( PyObject *) &_Py_FalseStruct), ((PyObject *) &_Py_TrueStruct ))); | |||
| 2499 | ||||
| 2500 | /* | |||
| 2501 | * Now return the state which is at least byteorder, | |||
| 2502 | * subarray, and fields | |||
| 2503 | */ | |||
| 2504 | endian = self->byteorder; | |||
| 2505 | if (endian == '=') { | |||
| 2506 | endian = '<'; | |||
| 2507 | if (!PyArray_IsNativeByteOrder(endian)((endian) != '>')) { | |||
| 2508 | endian = '>'; | |||
| 2509 | } | |||
| 2510 | } | |||
| 2511 | if (PyDataType_ISDATETIME(self)(((((PyArray_Descr*)(self))->type_num) >=NPY_DATETIME) && ((((PyArray_Descr*)(self))->type_num) <=NPY_TIMEDELTA) )) { | |||
| 2512 | PyObject *newobj; | |||
| 2513 | state = PyTuple_New(9); | |||
| 2514 | PyTuple_SET_ITEM(state, 0, PyLong_FromLong(version))PyTuple_SetItem(state, 0, PyLong_FromLong(version)); | |||
| 2515 | /* | |||
| 2516 | * newobj is a tuple of the Python metadata dictionary | |||
| 2517 | * and tuple of date_time info (str, num) | |||
| 2518 | */ | |||
| 2519 | newobj = _get_pickleabletype_from_datetime_metadata(self); | |||
| 2520 | if (newobj == NULL((void*)0)) { | |||
| 2521 | Py_DECREF(state)_Py_DECREF(((PyObject*)(state))); | |||
| 2522 | Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret))); | |||
| 2523 | return NULL((void*)0); | |||
| 2524 | } | |||
| 2525 | PyTuple_SET_ITEM(state, 8, newobj)PyTuple_SetItem(state, 8, newobj); | |||
| 2526 | } | |||
| 2527 | else if (self->metadata) { | |||
| 2528 | state = PyTuple_New(9); | |||
| 2529 | PyTuple_SET_ITEM(state, 0, PyLong_FromLong(version))PyTuple_SetItem(state, 0, PyLong_FromLong(version)); | |||
| 2530 | Py_INCREF(self->metadata)_Py_INCREF(((PyObject*)(self->metadata))); | |||
| 2531 | PyTuple_SET_ITEM(state, 8, self->metadata)PyTuple_SetItem(state, 8, self->metadata); | |||
| 2532 | } | |||
| 2533 | else { /* Use version 3 pickle format */ | |||
| 2534 | state = PyTuple_New(8); | |||
| 2535 | PyTuple_SET_ITEM(state, 0, PyLong_FromLong(3))PyTuple_SetItem(state, 0, PyLong_FromLong(3)); | |||
| 2536 | } | |||
| 2537 | ||||
| 2538 | PyTuple_SET_ITEM(state, 1, PyUnicode_FromFormat("%c", endian))PyTuple_SetItem(state, 1, PyUnicode_FromFormat("%c", endian)); | |||
| 2539 | PyTuple_SET_ITEM(state, 2, arraydescr_subdescr_get(self))PyTuple_SetItem(state, 2, arraydescr_subdescr_get(self)); | |||
| 2540 | if (PyDataType_HASFIELDS(self)(((PyArray_Descr *)(self))->names != ((void*)0))) { | |||
| 2541 | Py_INCREF(self->names)_Py_INCREF(((PyObject*)(self->names))); | |||
| 2542 | Py_INCREF(self->fields)_Py_INCREF(((PyObject*)(self->fields))); | |||
| 2543 | PyTuple_SET_ITEM(state, 3, self->names)PyTuple_SetItem(state, 3, self->names); | |||
| 2544 | PyTuple_SET_ITEM(state, 4, self->fields)PyTuple_SetItem(state, 4, self->fields); | |||
| 2545 | } | |||
| 2546 | else { | |||
| 2547 | PyTuple_SET_ITEM(state, 3, Py_None)PyTuple_SetItem(state, 3, (&_Py_NoneStruct)); | |||
| 2548 | PyTuple_SET_ITEM(state, 4, Py_None)PyTuple_SetItem(state, 4, (&_Py_NoneStruct)); | |||
| 2549 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
| 2550 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
| 2551 | } | |||
| 2552 | ||||
| 2553 | /* for extended types it also includes elsize and alignment */ | |||
| 2554 | if (PyTypeNum_ISEXTENDED(self->type_num)((((self->type_num) >=NPY_STRING) && ((self-> type_num) <=NPY_VOID)) || (((self->type_num) >= NPY_USERDEF ) && ((self->type_num) < NPY_USERDEF+ NPY_NUMUSERTYPES )))) { | |||
| 2555 | elsize = self->elsize; | |||
| 2556 | alignment = self->alignment; | |||
| 2557 | } | |||
| 2558 | else { | |||
| 2559 | elsize = -1; | |||
| 2560 | alignment = -1; | |||
| 2561 | } | |||
| 2562 | PyTuple_SET_ITEM(state, 5, PyLong_FromLong(elsize))PyTuple_SetItem(state, 5, PyLong_FromLong(elsize)); | |||
| 2563 | PyTuple_SET_ITEM(state, 6, PyLong_FromLong(alignment))PyTuple_SetItem(state, 6, PyLong_FromLong(alignment)); | |||
| 2564 | PyTuple_SET_ITEM(state, 7, PyLong_FromLong(self->flags))PyTuple_SetItem(state, 7, PyLong_FromLong(self->flags)); | |||
| 2565 | ||||
| 2566 | PyTuple_SET_ITEM(ret, 2, state)PyTuple_SetItem(ret, 2, state); | |||
| 2567 | return ret; | |||
| 2568 | } | |||
| 2569 | ||||
| 2570 | /* | |||
| 2571 | * returns NPY_OBJECT_DTYPE_FLAGS if this data-type has an object portion used | |||
| 2572 | * when setting the state because hasobject is not stored. | |||
| 2573 | */ | |||
| 2574 | static char | |||
| 2575 | _descr_find_object(PyArray_Descr *self) | |||
| 2576 | { | |||
| 2577 | if (self->flags | |||
| 2578 | || self->type_num == NPY_OBJECT | |||
| 2579 | || self->kind == 'O') { | |||
| 2580 | return NPY_OBJECT_DTYPE_FLAGS(0x02 | 0x20 | 0x04 | 0x01 | 0x08 | 0x10); | |||
| 2581 | } | |||
| 2582 | if (PyDataType_HASFIELDS(self)(((PyArray_Descr *)(self))->names != ((void*)0))) { | |||
| 2583 | PyObject *key, *value, *title = NULL((void*)0); | |||
| 2584 | PyArray_Descr *new; | |||
| 2585 | int offset; | |||
| 2586 | Py_ssize_t pos = 0; | |||
| 2587 | ||||
| 2588 | while (PyDict_Next(self->fields, &pos, &key, &value)) { | |||
| 2589 | if (NPY_TITLE_KEY(key, value)(NPY_TITLE_KEY_check((key), (value)))) { | |||
| 2590 | continue; | |||
| 2591 | } | |||
| 2592 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(value, "Oi|O", &new, &offset, &title)) { | |||
| 2593 | PyErr_Clear(); | |||
| 2594 | return 0; | |||
| 2595 | } | |||
| 2596 | if (_descr_find_object(new)) { | |||
| 2597 | new->flags = NPY_OBJECT_DTYPE_FLAGS(0x02 | 0x20 | 0x04 | 0x01 | 0x08 | 0x10); | |||
| 2598 | return NPY_OBJECT_DTYPE_FLAGS(0x02 | 0x20 | 0x04 | 0x01 | 0x08 | 0x10); | |||
| 2599 | } | |||
| 2600 | } | |||
| 2601 | } | |||
| 2602 | return 0; | |||
| 2603 | } | |||
| 2604 | ||||
| 2605 | /* | |||
| 2606 | * state is at least byteorder, subarray, and fields but could include elsize | |||
| 2607 | * and alignment for EXTENDED arrays | |||
| 2608 | */ | |||
| 2609 | static PyObject * | |||
| 2610 | arraydescr_setstate(PyArray_Descr *self, PyObject *args) | |||
| 2611 | { | |||
| 2612 | int elsize = -1, alignment = -1; | |||
| 2613 | int version = 4; | |||
| 2614 | char endian; | |||
| 2615 | PyObject *endian_obj; | |||
| 2616 | PyObject *subarray, *fields, *names = NULL((void*)0), *metadata=NULL((void*)0); | |||
| 2617 | int incref_names = 1; | |||
| 2618 | int int_dtypeflags = 0; | |||
| 2619 | char dtypeflags; | |||
| 2620 | ||||
| 2621 | if (self->fields == Py_None(&_Py_NoneStruct)) { | |||
| 2622 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 2623 | } | |||
| 2624 | if (PyTuple_GET_SIZE(args)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(args))))-> ob_size) != 1 | |||
| 2625 | || !(PyTuple_Check(PyTuple_GET_ITEM(args, 0))((((((PyObject*)(((((void) (0)), (PyTupleObject *)(args))-> ob_item[0])))->ob_type))->tp_flags & ((1UL << 26))) != 0))) { | |||
| 2626 | PyErr_BadInternalCall()_PyErr_BadInternalCall("/tmp/pyrefcon/numpy/numpy/core/src/multiarray/descriptor.c" , 2626); | |||
| 2627 | return NULL((void*)0); | |||
| 2628 | } | |||
| 2629 | switch (PyTuple_GET_SIZE(PyTuple_GET_ITEM(args,0))(((PyVarObject*)((((void) (0)), (PyTupleObject *)(((((void) ( 0)), (PyTupleObject *)(args))->ob_item[0])))))->ob_size )) { | |||
| 2630 | case 9: | |||
| 2631 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "(iOOOOiiiO):__setstate__", | |||
| 2632 | &version, &endian_obj, | |||
| 2633 | &subarray, &names, &fields, &elsize, | |||
| 2634 | &alignment, &int_dtypeflags, &metadata)) { | |||
| 2635 | PyErr_Clear(); | |||
| 2636 | return NULL((void*)0); | |||
| 2637 | } | |||
| 2638 | break; | |||
| 2639 | case 8: | |||
| 2640 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "(iOOOOiii):__setstate__", | |||
| 2641 | &version, &endian_obj, | |||
| 2642 | &subarray, &names, &fields, &elsize, | |||
| 2643 | &alignment, &int_dtypeflags)) { | |||
| 2644 | return NULL((void*)0); | |||
| 2645 | } | |||
| 2646 | break; | |||
| 2647 | case 7: | |||
| 2648 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "(iOOOOii):__setstate__", | |||
| 2649 | &version, &endian_obj, | |||
| 2650 | &subarray, &names, &fields, &elsize, | |||
| 2651 | &alignment)) { | |||
| 2652 | return NULL((void*)0); | |||
| 2653 | } | |||
| 2654 | break; | |||
| 2655 | case 6: | |||
| 2656 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "(iOOOii):__setstate__", | |||
| 2657 | &version, | |||
| 2658 | &endian_obj, &subarray, &fields, | |||
| 2659 | &elsize, &alignment)) { | |||
| 2660 | return NULL((void*)0); | |||
| 2661 | } | |||
| 2662 | break; | |||
| 2663 | case 5: | |||
| 2664 | version = 0; | |||
| 2665 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "(OOOii):__setstate__", | |||
| 2666 | &endian_obj, &subarray, &fields, &elsize, | |||
| 2667 | &alignment)) { | |||
| 2668 | return NULL((void*)0); | |||
| 2669 | } | |||
| 2670 | break; | |||
| 2671 | default: | |||
| 2672 | /* raise an error */ | |||
| 2673 | if (PyTuple_GET_SIZE(PyTuple_GET_ITEM(args,0))(((PyVarObject*)((((void) (0)), (PyTupleObject *)(((((void) ( 0)), (PyTupleObject *)(args))->ob_item[0])))))->ob_size ) > 5) { | |||
| 2674 | version = PyLong_AsLong(PyTuple_GET_ITEM(args, 0)((((void) (0)), (PyTupleObject *)(args))->ob_item[0])); | |||
| 2675 | } | |||
| 2676 | else { | |||
| 2677 | version = -1; | |||
| 2678 | } | |||
| 2679 | } | |||
| 2680 | ||||
| 2681 | /* | |||
| 2682 | * If we ever need another pickle format, increment the version | |||
| 2683 | * number. But we should still be able to handle the old versions. | |||
| 2684 | */ | |||
| 2685 | if (version < 0 || version > 4) { | |||
| 2686 | PyErr_Format(PyExc_ValueError, | |||
| 2687 | "can't handle version %d of numpy.dtype pickle", | |||
| 2688 | version); | |||
| 2689 | return NULL((void*)0); | |||
| 2690 | } | |||
| 2691 | /* Invalidate cached hash value */ | |||
| 2692 | self->hash = -1; | |||
| 2693 | ||||
| 2694 | if (version == 1 || version == 0) { | |||
| 2695 | if (fields != Py_None(&_Py_NoneStruct)) { | |||
| 2696 | PyObject *key, *list; | |||
| 2697 | key = PyLong_FromLong(-1); | |||
| 2698 | list = PyDict_GetItemWithError(fields, key); | |||
| 2699 | if (!list) { | |||
| 2700 | if (!PyErr_Occurred()) { | |||
| 2701 | /* fields was missing the name it claimed to contain */ | |||
| 2702 | PyErr_BadInternalCall()_PyErr_BadInternalCall("/tmp/pyrefcon/numpy/numpy/core/src/multiarray/descriptor.c" , 2702); | |||
| 2703 | } | |||
| 2704 | return NULL((void*)0); | |||
| 2705 | } | |||
| 2706 | Py_INCREF(list)_Py_INCREF(((PyObject*)(list))); | |||
| 2707 | names = list; | |||
| 2708 | PyDict_DelItem(fields, key); | |||
| 2709 | incref_names = 0; | |||
| 2710 | } | |||
| 2711 | else { | |||
| 2712 | names = Py_None(&_Py_NoneStruct); | |||
| 2713 | } | |||
| 2714 | } | |||
| 2715 | ||||
| 2716 | /* Parse endian */ | |||
| 2717 | if (PyUnicode_Check(endian_obj)((((((PyObject*)(endian_obj))->ob_type))->tp_flags & ((1UL << 28))) != 0) || PyBytes_Check(endian_obj)((((((PyObject*)(endian_obj))->ob_type))->tp_flags & ((1UL << 27))) != 0)) { | |||
| 2718 | PyObject *tmp = NULL((void*)0); | |||
| 2719 | char *str; | |||
| 2720 | Py_ssize_t len; | |||
| 2721 | ||||
| 2722 | if (PyUnicode_Check(endian_obj)((((((PyObject*)(endian_obj))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 2723 | tmp = PyUnicode_AsASCIIString(endian_obj); | |||
| 2724 | if (tmp == NULL((void*)0)) { | |||
| 2725 | return NULL((void*)0); | |||
| 2726 | } | |||
| 2727 | endian_obj = tmp; | |||
| 2728 | } | |||
| 2729 | ||||
| 2730 | if (PyBytes_AsStringAndSize(endian_obj, &str, &len) < 0) { | |||
| 2731 | Py_XDECREF(tmp)_Py_XDECREF(((PyObject*)(tmp))); | |||
| 2732 | return NULL((void*)0); | |||
| 2733 | } | |||
| 2734 | if (len != 1) { | |||
| 2735 | PyErr_SetString(PyExc_ValueError, | |||
| 2736 | "endian is not 1-char string in Numpy dtype unpickling"); | |||
| 2737 | Py_XDECREF(tmp)_Py_XDECREF(((PyObject*)(tmp))); | |||
| 2738 | return NULL((void*)0); | |||
| 2739 | } | |||
| 2740 | endian = str[0]; | |||
| 2741 | Py_XDECREF(tmp)_Py_XDECREF(((PyObject*)(tmp))); | |||
| 2742 | } | |||
| 2743 | else { | |||
| 2744 | PyErr_SetString(PyExc_ValueError, | |||
| 2745 | "endian is not a string in Numpy dtype unpickling"); | |||
| 2746 | return NULL((void*)0); | |||
| 2747 | } | |||
| 2748 | ||||
| 2749 | if ((fields == Py_None(&_Py_NoneStruct) && names != Py_None(&_Py_NoneStruct)) || | |||
| 2750 | (names == Py_None(&_Py_NoneStruct) && fields != Py_None(&_Py_NoneStruct))) { | |||
| 2751 | PyErr_Format(PyExc_ValueError, | |||
| 2752 | "inconsistent fields and names in Numpy dtype unpickling"); | |||
| 2753 | return NULL((void*)0); | |||
| 2754 | } | |||
| 2755 | ||||
| 2756 | if (names != Py_None(&_Py_NoneStruct) && !PyTuple_Check(names)((((((PyObject*)(names))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | |||
| 2757 | PyErr_Format(PyExc_ValueError, | |||
| 2758 | "non-tuple names in Numpy dtype unpickling"); | |||
| 2759 | return NULL((void*)0); | |||
| 2760 | } | |||
| 2761 | ||||
| 2762 | if (fields != Py_None(&_Py_NoneStruct) && !PyDict_Check(fields)((((((PyObject*)(fields))->ob_type))->tp_flags & (( 1UL << 29))) != 0)) { | |||
| 2763 | PyErr_Format(PyExc_ValueError, | |||
| 2764 | "non-dict fields in Numpy dtype unpickling"); | |||
| 2765 | return NULL((void*)0); | |||
| 2766 | } | |||
| 2767 | ||||
| 2768 | if (endian != '|' && PyArray_IsNativeByteOrder(endian)((endian) != '>')) { | |||
| 2769 | endian = '='; | |||
| 2770 | } | |||
| 2771 | self->byteorder = endian; | |||
| 2772 | if (self->subarray) { | |||
| 2773 | Py_XDECREF(self->subarray->base)_Py_XDECREF(((PyObject*)(self->subarray->base))); | |||
| 2774 | Py_XDECREF(self->subarray->shape)_Py_XDECREF(((PyObject*)(self->subarray->shape))); | |||
| 2775 | PyArray_freePyMem_RawFree(self->subarray); | |||
| 2776 | } | |||
| 2777 | self->subarray = NULL((void*)0); | |||
| 2778 | ||||
| 2779 | if (subarray != Py_None(&_Py_NoneStruct)) { | |||
| 2780 | PyObject *subarray_shape; | |||
| 2781 | ||||
| 2782 | /* | |||
| 2783 | * Ensure that subarray[0] is an ArrayDescr and | |||
| 2784 | * that subarray_shape obtained from subarray[1] is a tuple of integers. | |||
| 2785 | */ | |||
| 2786 | if (!(PyTuple_Check(subarray)((((((PyObject*)(subarray))->ob_type))->tp_flags & ( (1UL << 26))) != 0) && | |||
| 2787 | PyTuple_Size(subarray) == 2 && | |||
| 2788 | PyArray_DescrCheck(PyTuple_GET_ITEM(subarray, 0))((((PyObject*)(((((void) (0)), (PyTupleObject *)(subarray))-> ob_item[0])))->ob_type) == (&(*(PyTypeObject *)(&PyArrayDescr_TypeFull ))) || PyType_IsSubtype((((PyObject*)(((((void) (0)), (PyTupleObject *)(subarray))->ob_item[0])))->ob_type), (&(*(PyTypeObject *)(&PyArrayDescr_TypeFull))))))) { | |||
| 2789 | PyErr_Format(PyExc_ValueError, | |||
| 2790 | "incorrect subarray in __setstate__"); | |||
| 2791 | return NULL((void*)0); | |||
| 2792 | } | |||
| 2793 | subarray_shape = PyTuple_GET_ITEM(subarray, 1)((((void) (0)), (PyTupleObject *)(subarray))->ob_item[1]); | |||
| 2794 | if (PyNumber_Check(subarray_shape)) { | |||
| 2795 | PyObject *tmp; | |||
| 2796 | tmp = PyNumber_Long(subarray_shape); | |||
| 2797 | if (tmp == NULL((void*)0)) { | |||
| 2798 | return NULL((void*)0); | |||
| 2799 | } | |||
| 2800 | subarray_shape = Py_BuildValue_Py_BuildValue_SizeT("(O)", tmp); | |||
| 2801 | Py_DECREF(tmp)_Py_DECREF(((PyObject*)(tmp))); | |||
| 2802 | if (subarray_shape == NULL((void*)0)) { | |||
| 2803 | return NULL((void*)0); | |||
| 2804 | } | |||
| 2805 | } | |||
| 2806 | else if (_is_tuple_of_integers(subarray_shape)) { | |||
| 2807 | Py_INCREF(subarray_shape)_Py_INCREF(((PyObject*)(subarray_shape))); | |||
| 2808 | } | |||
| 2809 | else { | |||
| 2810 | PyErr_Format(PyExc_ValueError, | |||
| 2811 | "incorrect subarray shape in __setstate__"); | |||
| 2812 | return NULL((void*)0); | |||
| 2813 | } | |||
| 2814 | ||||
| 2815 | self->subarray = PyArray_mallocPyMem_RawMalloc(sizeof(PyArray_ArrayDescr)); | |||
| 2816 | if (!PyDataType_HASSUBARRAY(self)((self)->subarray != ((void*)0))) { | |||
| 2817 | return PyErr_NoMemory(); | |||
| 2818 | } | |||
| 2819 | self->subarray->base = (PyArray_Descr *)PyTuple_GET_ITEM(subarray, 0)((((void) (0)), (PyTupleObject *)(subarray))->ob_item[0]); | |||
| 2820 | Py_INCREF(self->subarray->base)_Py_INCREF(((PyObject*)(self->subarray->base))); | |||
| 2821 | self->subarray->shape = subarray_shape; | |||
| 2822 | } | |||
| 2823 | ||||
| 2824 | if (fields != Py_None(&_Py_NoneStruct)) { | |||
| 2825 | /* | |||
| 2826 | * Ensure names are of appropriate string type | |||
| 2827 | */ | |||
| 2828 | Py_ssize_t i; | |||
| 2829 | int names_ok = 1; | |||
| 2830 | PyObject *name; | |||
| 2831 | ||||
| 2832 | for (i = 0; i < PyTuple_GET_SIZE(names)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(names))))-> ob_size); ++i) { | |||
| 2833 | name = PyTuple_GET_ITEM(names, i)((((void) (0)), (PyTupleObject *)(names))->ob_item[i]); | |||
| 2834 | if (!PyUnicode_Check(name)((((((PyObject*)(name))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 2835 | names_ok = 0; | |||
| 2836 | break; | |||
| 2837 | } | |||
| 2838 | } | |||
| 2839 | ||||
| 2840 | if (names_ok) { | |||
| 2841 | Py_XDECREF(self->fields)_Py_XDECREF(((PyObject*)(self->fields))); | |||
| 2842 | self->fields = fields; | |||
| 2843 | Py_INCREF(fields)_Py_INCREF(((PyObject*)(fields))); | |||
| 2844 | Py_XDECREF(self->names)_Py_XDECREF(((PyObject*)(self->names))); | |||
| 2845 | self->names = names; | |||
| 2846 | if (incref_names) { | |||
| 2847 | Py_INCREF(names)_Py_INCREF(((PyObject*)(names))); | |||
| 2848 | } | |||
| 2849 | } | |||
| 2850 | else { | |||
| 2851 | /* | |||
| 2852 | * To support pickle.load(f, encoding='bytes') for loading Py2 | |||
| 2853 | * generated pickles on Py3, we need to be more lenient and convert | |||
| 2854 | * field names from byte strings to unicode. | |||
| 2855 | */ | |||
| 2856 | PyObject *tmp, *new_name, *field; | |||
| 2857 | ||||
| 2858 | tmp = PyDict_New(); | |||
| 2859 | if (tmp == NULL((void*)0)) { | |||
| 2860 | return NULL((void*)0); | |||
| 2861 | } | |||
| 2862 | Py_XDECREF(self->fields)_Py_XDECREF(((PyObject*)(self->fields))); | |||
| 2863 | self->fields = tmp; | |||
| 2864 | ||||
| 2865 | tmp = PyTuple_New(PyTuple_GET_SIZE(names)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(names))))-> ob_size)); | |||
| 2866 | if (tmp == NULL((void*)0)) { | |||
| 2867 | return NULL((void*)0); | |||
| 2868 | } | |||
| 2869 | Py_XDECREF(self->names)_Py_XDECREF(((PyObject*)(self->names))); | |||
| 2870 | self->names = tmp; | |||
| 2871 | ||||
| 2872 | for (i = 0; i < PyTuple_GET_SIZE(names)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(names))))-> ob_size); ++i) { | |||
| 2873 | name = PyTuple_GET_ITEM(names, i)((((void) (0)), (PyTupleObject *)(names))->ob_item[i]); | |||
| 2874 | field = PyDict_GetItemWithError(fields, name); | |||
| 2875 | if (!field) { | |||
| 2876 | if (!PyErr_Occurred()) { | |||
| 2877 | /* fields was missing the name it claimed to contain */ | |||
| 2878 | PyErr_BadInternalCall()_PyErr_BadInternalCall("/tmp/pyrefcon/numpy/numpy/core/src/multiarray/descriptor.c" , 2878); | |||
| 2879 | } | |||
| 2880 | return NULL((void*)0); | |||
| 2881 | } | |||
| 2882 | ||||
| 2883 | if (PyUnicode_Check(name)((((((PyObject*)(name))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 2884 | new_name = name; | |||
| 2885 | Py_INCREF(new_name)_Py_INCREF(((PyObject*)(new_name))); | |||
| 2886 | } | |||
| 2887 | else { | |||
| 2888 | new_name = PyUnicode_FromEncodedObject(name, "ASCII", "strict"); | |||
| 2889 | if (new_name == NULL((void*)0)) { | |||
| 2890 | return NULL((void*)0); | |||
| 2891 | } | |||
| 2892 | } | |||
| 2893 | ||||
| 2894 | PyTuple_SET_ITEM(self->names, i, new_name)PyTuple_SetItem(self->names, i, new_name); | |||
| 2895 | if (PyDict_SetItem(self->fields, new_name, field) != 0) { | |||
| 2896 | return NULL((void*)0); | |||
| 2897 | } | |||
| 2898 | } | |||
| 2899 | } | |||
| 2900 | } | |||
| 2901 | ||||
| 2902 | if (PyTypeNum_ISEXTENDED(self->type_num)((((self->type_num) >=NPY_STRING) && ((self-> type_num) <=NPY_VOID)) || (((self->type_num) >= NPY_USERDEF ) && ((self->type_num) < NPY_USERDEF+ NPY_NUMUSERTYPES )))) { | |||
| 2903 | self->elsize = elsize; | |||
| 2904 | self->alignment = alignment; | |||
| 2905 | } | |||
| 2906 | ||||
| 2907 | /* | |||
| 2908 | * We use an integer converted to char for backward compatibility with | |||
| 2909 | * pickled arrays. Pickled arrays created with previous versions encoded | |||
| 2910 | * flags as an int even though it actually was a char in the PyArray_Descr | |||
| 2911 | * structure | |||
| 2912 | */ | |||
| 2913 | dtypeflags = int_dtypeflags; | |||
| 2914 | if (dtypeflags != int_dtypeflags) { | |||
| 2915 | PyErr_Format(PyExc_ValueError, | |||
| 2916 | "incorrect value for flags variable (overflow)"); | |||
| 2917 | return NULL((void*)0); | |||
| 2918 | } | |||
| 2919 | else { | |||
| 2920 | self->flags = dtypeflags; | |||
| 2921 | } | |||
| 2922 | ||||
| 2923 | if (version < 3) { | |||
| 2924 | self->flags = _descr_find_object(self); | |||
| 2925 | } | |||
| 2926 | ||||
| 2927 | /* | |||
| 2928 | * We have a borrowed reference to metadata so no need | |||
| 2929 | * to alter reference count when throwing away Py_None. | |||
| 2930 | */ | |||
| 2931 | if (metadata == Py_None(&_Py_NoneStruct)) { | |||
| 2932 | metadata = NULL((void*)0); | |||
| 2933 | } | |||
| 2934 | ||||
| 2935 | if (PyDataType_ISDATETIME(self)(((((PyArray_Descr*)(self))->type_num) >=NPY_DATETIME) && ((((PyArray_Descr*)(self))->type_num) <=NPY_TIMEDELTA) ) && (metadata != NULL((void*)0))) { | |||
| 2936 | PyObject *old_metadata; | |||
| 2937 | PyArray_DatetimeMetaData temp_dt_data; | |||
| 2938 | ||||
| 2939 | if ((! PyTuple_Check(metadata)((((((PyObject*)(metadata))->ob_type))->tp_flags & ( (1UL << 26))) != 0)) || (PyTuple_Size(metadata) != 2)) { | |||
| 2940 | PyErr_Format(PyExc_ValueError, | |||
| 2941 | "Invalid datetime dtype (metadata, c_metadata): %R", | |||
| 2942 | metadata); | |||
| 2943 | return NULL((void*)0); | |||
| 2944 | } | |||
| 2945 | ||||
| 2946 | if (convert_datetime_metadata_tuple_to_datetime_metadata( | |||
| 2947 | PyTuple_GET_ITEM(metadata, 1)((((void) (0)), (PyTupleObject *)(metadata))->ob_item[1]), | |||
| 2948 | &temp_dt_data, | |||
| 2949 | NPY_TRUE1) < 0) { | |||
| 2950 | return NULL((void*)0); | |||
| 2951 | } | |||
| 2952 | ||||
| 2953 | old_metadata = self->metadata; | |||
| 2954 | self->metadata = PyTuple_GET_ITEM(metadata, 0)((((void) (0)), (PyTupleObject *)(metadata))->ob_item[0]); | |||
| 2955 | memcpy((char *) &((PyArray_DatetimeDTypeMetaData *)self->c_metadata)->meta, | |||
| 2956 | (char *) &temp_dt_data, | |||
| 2957 | sizeof(PyArray_DatetimeMetaData)); | |||
| 2958 | Py_XINCREF(self->metadata)_Py_XINCREF(((PyObject*)(self->metadata))); | |||
| 2959 | Py_XDECREF(old_metadata)_Py_XDECREF(((PyObject*)(old_metadata))); | |||
| 2960 | } | |||
| 2961 | else { | |||
| 2962 | PyObject *old_metadata = self->metadata; | |||
| 2963 | self->metadata = metadata; | |||
| 2964 | Py_XINCREF(self->metadata)_Py_XINCREF(((PyObject*)(self->metadata))); | |||
| 2965 | Py_XDECREF(old_metadata)_Py_XDECREF(((PyObject*)(old_metadata))); | |||
| 2966 | } | |||
| 2967 | ||||
| 2968 | Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (& _Py_NoneStruct); | |||
| 2969 | } | |||
| 2970 | ||||
| 2971 | /*NUMPY_API | |||
| 2972 | * | |||
| 2973 | * Get type-descriptor from an object forcing alignment if possible | |||
| 2974 | * None goes to DEFAULT type. | |||
| 2975 | * | |||
| 2976 | * any object with the .fields attribute and/or .itemsize attribute (if the | |||
| 2977 | *.fields attribute does not give the total size -- i.e. a partial record | |||
| 2978 | * naming). If itemsize is given it must be >= size computed from fields | |||
| 2979 | * | |||
| 2980 | * The .fields attribute must return a convertible dictionary if present. | |||
| 2981 | * Result inherits from NPY_VOID. | |||
| 2982 | */ | |||
| 2983 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | |||
| 2984 | PyArray_DescrAlignConverter(PyObject *obj, PyArray_Descr **at) | |||
| 2985 | { | |||
| 2986 | *at = _convert_from_any(obj, 1); | |||
| 2987 | return (*at) ? NPY_SUCCEED1 : NPY_FAIL0; | |||
| 2988 | } | |||
| 2989 | ||||
| 2990 | /*NUMPY_API | |||
| 2991 | * | |||
| 2992 | * Get type-descriptor from an object forcing alignment if possible | |||
| 2993 | * None goes to NULL. | |||
| 2994 | */ | |||
| 2995 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | |||
| 2996 | PyArray_DescrAlignConverter2(PyObject *obj, PyArray_Descr **at) | |||
| 2997 | { | |||
| 2998 | if (obj == Py_None(&_Py_NoneStruct)) { | |||
| 2999 | *at = NULL((void*)0); | |||
| 3000 | return NPY_SUCCEED1; | |||
| 3001 | } | |||
| 3002 | else { | |||
| 3003 | return PyArray_DescrAlignConverter(obj, at); | |||
| 3004 | } | |||
| 3005 | } | |||
| 3006 | ||||
| 3007 | ||||
| 3008 | ||||
| 3009 | /*NUMPY_API | |||
| 3010 | * | |||
| 3011 | * returns a copy of the PyArray_Descr structure with the byteorder | |||
| 3012 | * altered: | |||
| 3013 | * no arguments: The byteorder is swapped (in all subfields as well) | |||
| 3014 | * single argument: The byteorder is forced to the given state | |||
| 3015 | * (in all subfields as well) | |||
| 3016 | * | |||
| 3017 | * Valid states: ('big', '>') or ('little' or '<') | |||
| 3018 | * ('native', or '=') | |||
| 3019 | * | |||
| 3020 | * If a descr structure with | is encountered it's own | |||
| 3021 | * byte-order is not changed but any fields are: | |||
| 3022 | * | |||
| 3023 | * | |||
| 3024 | * Deep bytorder change of a data-type descriptor | |||
| 3025 | * *** Leaves reference count of self unchanged --- does not DECREF self *** | |||
| 3026 | */ | |||
| 3027 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr * | |||
| 3028 | PyArray_DescrNewByteorder(PyArray_Descr *self, char newendian) | |||
| 3029 | { | |||
| 3030 | PyArray_Descr *new; | |||
| 3031 | char endian; | |||
| 3032 | ||||
| 3033 | new = PyArray_DescrNew(self); | |||
| 3034 | endian = new->byteorder; | |||
| 3035 | if (endian != NPY_IGNORE'|') { | |||
| 3036 | if (newendian == NPY_SWAP's') { | |||
| 3037 | /* swap byteorder */ | |||
| 3038 | if (PyArray_ISNBO(endian)((endian) != '>')) { | |||
| 3039 | endian = NPY_OPPBYTE'>'; | |||
| 3040 | } | |||
| 3041 | else { | |||
| 3042 | endian = NPY_NATBYTE'<'; | |||
| 3043 | } | |||
| 3044 | new->byteorder = endian; | |||
| 3045 | } | |||
| 3046 | else if (newendian != NPY_IGNORE'|') { | |||
| 3047 | new->byteorder = newendian; | |||
| 3048 | } | |||
| 3049 | } | |||
| 3050 | if (PyDataType_HASFIELDS(new)(((PyArray_Descr *)(new))->names != ((void*)0))) { | |||
| 3051 | PyObject *newfields; | |||
| 3052 | PyObject *key, *value; | |||
| 3053 | PyObject *newvalue; | |||
| 3054 | PyObject *old; | |||
| 3055 | PyArray_Descr *newdescr; | |||
| 3056 | Py_ssize_t pos = 0; | |||
| 3057 | int len, i; | |||
| 3058 | ||||
| 3059 | newfields = PyDict_New(); | |||
| 3060 | /* make new dictionary with replaced PyArray_Descr Objects */ | |||
| 3061 | while (PyDict_Next(self->fields, &pos, &key, &value)) { | |||
| 3062 | if (NPY_TITLE_KEY(key, value)(NPY_TITLE_KEY_check((key), (value)))) { | |||
| 3063 | continue; | |||
| 3064 | } | |||
| 3065 | if (!PyUnicode_Check(key)((((((PyObject*)(key))->ob_type))->tp_flags & ((1UL << 28))) != 0) || !PyTuple_Check(value)((((((PyObject*)(value))->ob_type))->tp_flags & ((1UL << 26))) != 0) || | |||
| 3066 | ((len=PyTuple_GET_SIZE(value)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(value))))-> ob_size)) < 2)) { | |||
| 3067 | continue; | |||
| 3068 | } | |||
| 3069 | old = PyTuple_GET_ITEM(value, 0)((((void) (0)), (PyTupleObject *)(value))->ob_item[0]); | |||
| 3070 | if (!PyArray_DescrCheck(old)((((PyObject*)(old))->ob_type) == (&(*(PyTypeObject *) (&PyArrayDescr_TypeFull))) || PyType_IsSubtype((((PyObject *)(old))->ob_type), (&(*(PyTypeObject *)(&PyArrayDescr_TypeFull )))))) { | |||
| 3071 | continue; | |||
| 3072 | } | |||
| 3073 | newdescr = PyArray_DescrNewByteorder( | |||
| 3074 | (PyArray_Descr *)old, newendian); | |||
| 3075 | if (newdescr == NULL((void*)0)) { | |||
| 3076 | Py_DECREF(newfields)_Py_DECREF(((PyObject*)(newfields))); Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 3077 | return NULL((void*)0); | |||
| 3078 | } | |||
| 3079 | newvalue = PyTuple_New(len); | |||
| 3080 | PyTuple_SET_ITEM(newvalue, 0, (PyObject *)newdescr)PyTuple_SetItem(newvalue, 0, (PyObject *)newdescr); | |||
| 3081 | for (i = 1; i < len; i++) { | |||
| 3082 | old = PyTuple_GET_ITEM(value, i)((((void) (0)), (PyTupleObject *)(value))->ob_item[i]); | |||
| 3083 | Py_INCREF(old)_Py_INCREF(((PyObject*)(old))); | |||
| 3084 | PyTuple_SET_ITEM(newvalue, i, old)PyTuple_SetItem(newvalue, i, old); | |||
| 3085 | } | |||
| 3086 | int ret = PyDict_SetItem(newfields, key, newvalue); | |||
| 3087 | Py_DECREF(newvalue)_Py_DECREF(((PyObject*)(newvalue))); | |||
| 3088 | if (ret < 0) { | |||
| 3089 | Py_DECREF(newfields)_Py_DECREF(((PyObject*)(newfields))); | |||
| 3090 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 3091 | return NULL((void*)0); | |||
| 3092 | } | |||
| 3093 | } | |||
| 3094 | Py_DECREF(new->fields)_Py_DECREF(((PyObject*)(new->fields))); | |||
| 3095 | new->fields = newfields; | |||
| 3096 | } | |||
| 3097 | if (PyDataType_HASSUBARRAY(new)((new)->subarray != ((void*)0))) { | |||
| 3098 | Py_DECREF(new->subarray->base)_Py_DECREF(((PyObject*)(new->subarray->base))); | |||
| 3099 | new->subarray->base = PyArray_DescrNewByteorder( | |||
| 3100 | self->subarray->base, newendian); | |||
| 3101 | } | |||
| 3102 | return new; | |||
| 3103 | } | |||
| 3104 | ||||
| 3105 | ||||
| 3106 | static PyObject * | |||
| 3107 | arraydescr_newbyteorder(PyArray_Descr *self, PyObject *args) | |||
| 3108 | { | |||
| 3109 | char endian=NPY_SWAP's'; | |||
| 3110 | ||||
| 3111 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "|O&:newbyteorder", PyArray_ByteorderConverter, | |||
| 3112 | &endian)) { | |||
| 3113 | return NULL((void*)0); | |||
| 3114 | } | |||
| 3115 | return (PyObject *)PyArray_DescrNewByteorder(self, endian); | |||
| 3116 | } | |||
| 3117 | ||||
| 3118 | static PyMethodDef arraydescr_methods[] = { | |||
| 3119 | /* for pickling */ | |||
| 3120 | {"__reduce__", | |||
| 3121 | (PyCFunction)arraydescr_reduce, | |||
| 3122 | METH_VARARGS0x0001, NULL((void*)0)}, | |||
| 3123 | {"__setstate__", | |||
| 3124 | (PyCFunction)arraydescr_setstate, | |||
| 3125 | METH_VARARGS0x0001, NULL((void*)0)}, | |||
| 3126 | {"newbyteorder", | |||
| 3127 | (PyCFunction)arraydescr_newbyteorder, | |||
| 3128 | METH_VARARGS0x0001, NULL((void*)0)}, | |||
| 3129 | {NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)} /* sentinel */ | |||
| 3130 | }; | |||
| 3131 | ||||
| 3132 | /* | |||
| 3133 | * Checks whether the structured data type in 'dtype' | |||
| 3134 | * has a simple layout, where all the fields are in order, | |||
| 3135 | * and follow each other with no alignment padding. | |||
| 3136 | * | |||
| 3137 | * When this returns true, the dtype can be reconstructed | |||
| 3138 | * from a list of the field names and dtypes with no additional | |||
| 3139 | * dtype parameters. | |||
| 3140 | * | |||
| 3141 | * Returns 1 if it has a simple layout, 0 otherwise. | |||
| 3142 | */ | |||
| 3143 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) int | |||
| 3144 | is_dtype_struct_simple_unaligned_layout(PyArray_Descr *dtype) | |||
| 3145 | { | |||
| 3146 | PyObject *names, *fields, *key, *tup, *title; | |||
| 3147 | Py_ssize_t i, names_size; | |||
| 3148 | PyArray_Descr *fld_dtype; | |||
| 3149 | int fld_offset; | |||
| 3150 | npy_intp total_offset; | |||
| 3151 | ||||
| 3152 | /* Get some properties from the dtype */ | |||
| 3153 | names = dtype->names; | |||
| 3154 | names_size = PyTuple_GET_SIZE(names)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(names))))-> ob_size); | |||
| 3155 | fields = dtype->fields; | |||
| 3156 | ||||
| 3157 | /* Start at offset zero */ | |||
| 3158 | total_offset = 0; | |||
| 3159 | ||||
| 3160 | for (i = 0; i < names_size; ++i) { | |||
| 3161 | key = PyTuple_GET_ITEM(names, i)((((void) (0)), (PyTupleObject *)(names))->ob_item[i]); | |||
| 3162 | if (key == NULL((void*)0)) { | |||
| 3163 | return 0; | |||
| 3164 | } | |||
| 3165 | tup = PyDict_GetItem(fields, key); | |||
| 3166 | if (tup == NULL((void*)0)) { | |||
| 3167 | return 0; | |||
| 3168 | } | |||
| 3169 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(tup, "Oi|O", &fld_dtype, &fld_offset, &title)) { | |||
| 3170 | PyErr_Clear(); | |||
| 3171 | return 0; | |||
| 3172 | } | |||
| 3173 | /* If this field doesn't follow the pattern, not a simple layout */ | |||
| 3174 | if (total_offset != fld_offset) { | |||
| 3175 | return 0; | |||
| 3176 | } | |||
| 3177 | /* Get the next offset */ | |||
| 3178 | total_offset += fld_dtype->elsize; | |||
| 3179 | } | |||
| 3180 | ||||
| 3181 | /* | |||
| 3182 | * If the itemsize doesn't match the final offset, it's | |||
| 3183 | * not a simple layout. | |||
| 3184 | */ | |||
| 3185 | if (total_offset != dtype->elsize) { | |||
| 3186 | return 0; | |||
| 3187 | } | |||
| 3188 | ||||
| 3189 | /* It's a simple layout, since all the above tests passed */ | |||
| 3190 | return 1; | |||
| 3191 | } | |||
| 3192 | ||||
| 3193 | /* | |||
| 3194 | * The general dtype repr function. | |||
| 3195 | */ | |||
| 3196 | static PyObject * | |||
| 3197 | arraydescr_repr(PyArray_Descr *dtype) | |||
| 3198 | { | |||
| 3199 | PyObject *_numpy_dtype; | |||
| 3200 | PyObject *res; | |||
| 3201 | _numpy_dtype = PyImport_ImportModule("numpy.core._dtype"); | |||
| 3202 | if (_numpy_dtype == NULL((void*)0)) { | |||
| 3203 | return NULL((void*)0); | |||
| 3204 | } | |||
| 3205 | res = PyObject_CallMethod_PyObject_CallMethod_SizeT(_numpy_dtype, "__repr__", "O", dtype); | |||
| 3206 | Py_DECREF(_numpy_dtype)_Py_DECREF(((PyObject*)(_numpy_dtype))); | |||
| 3207 | return res; | |||
| 3208 | } | |||
| 3209 | /* | |||
| 3210 | * The general dtype str function. | |||
| 3211 | */ | |||
| 3212 | static PyObject * | |||
| 3213 | arraydescr_str(PyArray_Descr *dtype) | |||
| 3214 | { | |||
| 3215 | PyObject *_numpy_dtype; | |||
| 3216 | PyObject *res; | |||
| 3217 | _numpy_dtype = PyImport_ImportModule("numpy.core._dtype"); | |||
| 3218 | if (_numpy_dtype == NULL((void*)0)) { | |||
| 3219 | return NULL((void*)0); | |||
| 3220 | } | |||
| 3221 | res = PyObject_CallMethod_PyObject_CallMethod_SizeT(_numpy_dtype, "__str__", "O", dtype); | |||
| 3222 | Py_DECREF(_numpy_dtype)_Py_DECREF(((PyObject*)(_numpy_dtype))); | |||
| 3223 | return res; | |||
| 3224 | } | |||
| 3225 | ||||
| 3226 | static PyObject * | |||
| 3227 | arraydescr_richcompare(PyArray_Descr *self, PyObject *other, int cmp_op) | |||
| 3228 | { | |||
| 3229 | PyArray_Descr *new = _convert_from_any(other, 0); | |||
| 3230 | if (new == NULL((void*)0)) { | |||
| 3231 | return NULL((void*)0); | |||
| 3232 | } | |||
| 3233 | ||||
| 3234 | npy_bool ret; | |||
| 3235 | switch (cmp_op) { | |||
| 3236 | case Py_LT0: | |||
| 3237 | ret = !PyArray_EquivTypes(self, new) && PyArray_CanCastTo(self, new); | |||
| 3238 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 3239 | return PyBool_FromLong(ret); | |||
| 3240 | case Py_LE1: | |||
| 3241 | ret = PyArray_CanCastTo(self, new); | |||
| 3242 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 3243 | return PyBool_FromLong(ret); | |||
| 3244 | case Py_EQ2: | |||
| 3245 | ret = PyArray_EquivTypes(self, new); | |||
| 3246 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 3247 | return PyBool_FromLong(ret); | |||
| 3248 | case Py_NE3: | |||
| 3249 | ret = !PyArray_EquivTypes(self, new); | |||
| 3250 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 3251 | return PyBool_FromLong(ret); | |||
| 3252 | case Py_GT4: | |||
| 3253 | ret = !PyArray_EquivTypes(self, new) && PyArray_CanCastTo(new, self); | |||
| 3254 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 3255 | return PyBool_FromLong(ret); | |||
| 3256 | case Py_GE5: | |||
| 3257 | ret = PyArray_CanCastTo(new, self); | |||
| 3258 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 3259 | return PyBool_FromLong(ret); | |||
| 3260 | default: | |||
| 3261 | Py_DECREF(new)_Py_DECREF(((PyObject*)(new))); | |||
| 3262 | Py_RETURN_NOTIMPLEMENTEDreturn _Py_INCREF(((PyObject*)((&_Py_NotImplementedStruct )))), (&_Py_NotImplementedStruct); | |||
| 3263 | } | |||
| 3264 | } | |||
| 3265 | ||||
| 3266 | static int | |||
| 3267 | descr_nonzero(PyObject *NPY_UNUSED(self)(__NPY_UNUSED_TAGGEDself) __attribute__ ((__unused__))) | |||
| 3268 | { | |||
| 3269 | /* `bool(np.dtype(...)) == True` for all dtypes. Needed to override default | |||
| 3270 | * nonzero implementation, which checks if `len(object) > 0`. */ | |||
| 3271 | return 1; | |||
| 3272 | } | |||
| 3273 | ||||
| 3274 | static PyNumberMethods descr_as_number = { | |||
| 3275 | .nb_bool = (inquiry)descr_nonzero, | |||
| 3276 | }; | |||
| 3277 | ||||
| 3278 | /************************************************************************* | |||
| 3279 | **************** Implement Mapping Protocol *************************** | |||
| 3280 | *************************************************************************/ | |||
| 3281 | ||||
| 3282 | static Py_ssize_t | |||
| 3283 | descr_length(PyObject *self0) | |||
| 3284 | { | |||
| 3285 | PyArray_Descr *self = (PyArray_Descr *)self0; | |||
| 3286 | ||||
| 3287 | if (PyDataType_HASFIELDS(self)(((PyArray_Descr *)(self))->names != ((void*)0))) { | |||
| 3288 | return PyTuple_GET_SIZE(self->names)(((PyVarObject*)((((void) (0)), (PyTupleObject *)(self->names ))))->ob_size); | |||
| 3289 | } | |||
| 3290 | else { | |||
| 3291 | return 0; | |||
| 3292 | } | |||
| 3293 | } | |||
| 3294 | ||||
| 3295 | static PyObject * | |||
| 3296 | descr_repeat(PyObject *self, Py_ssize_t length) | |||
| 3297 | { | |||
| 3298 | PyObject *tup; | |||
| 3299 | PyArray_Descr *new; | |||
| 3300 | if (length < 0) { | |||
| 3301 | return PyErr_Format(PyExc_ValueError, | |||
| 3302 | "Array length must be >= 0, not %"NPY_INTP_FMT"ld", (npy_intp)length); | |||
| 3303 | } | |||
| 3304 | tup = Py_BuildValue_Py_BuildValue_SizeT("O" NPY_SSIZE_T_PYFMT"n", self, length); | |||
| 3305 | if (tup == NULL((void*)0)) { | |||
| 3306 | return NULL((void*)0); | |||
| 3307 | } | |||
| 3308 | new = _convert_from_any(tup, 0); | |||
| 3309 | Py_DECREF(tup)_Py_DECREF(((PyObject*)(tup))); | |||
| 3310 | return (PyObject *)new; | |||
| 3311 | } | |||
| 3312 | ||||
| 3313 | static int | |||
| 3314 | _check_has_fields(PyArray_Descr *self) | |||
| 3315 | { | |||
| 3316 | if (!PyDataType_HASFIELDS(self)(((PyArray_Descr *)(self))->names != ((void*)0))) { | |||
| 3317 | PyErr_Format(PyExc_KeyError, "There are no fields in dtype %S.", self); | |||
| 3318 | return -1; | |||
| 3319 | } | |||
| 3320 | else { | |||
| 3321 | return 0; | |||
| 3322 | } | |||
| 3323 | } | |||
| 3324 | ||||
| 3325 | static PyObject * | |||
| 3326 | _subscript_by_name(PyArray_Descr *self, PyObject *op) | |||
| 3327 | { | |||
| 3328 | PyObject *obj = PyDict_GetItemWithError(self->fields, op); | |||
| 3329 | if (obj == NULL((void*)0)) { | |||
| 3330 | if (!PyErr_Occurred()) { | |||
| 3331 | PyErr_Format(PyExc_KeyError, | |||
| 3332 | "Field named %R not found.", op); | |||
| 3333 | } | |||
| 3334 | return NULL((void*)0); | |||
| 3335 | } | |||
| 3336 | PyObject *descr = PyTuple_GET_ITEM(obj, 0)((((void) (0)), (PyTupleObject *)(obj))->ob_item[0]); | |||
| 3337 | Py_INCREF(descr)_Py_INCREF(((PyObject*)(descr))); | |||
| 3338 | return descr; | |||
| 3339 | } | |||
| 3340 | ||||
| 3341 | static PyObject * | |||
| 3342 | _subscript_by_index(PyArray_Descr *self, Py_ssize_t i) | |||
| 3343 | { | |||
| 3344 | PyObject *name = PySequence_GetItem(self->names, i); | |||
| 3345 | PyObject *ret; | |||
| 3346 | if (name == NULL((void*)0)) { | |||
| 3347 | PyErr_Format(PyExc_IndexError, | |||
| 3348 | "Field index %zd out of range.", i); | |||
| 3349 | return NULL((void*)0); | |||
| 3350 | } | |||
| 3351 | ret = _subscript_by_name(self, name); | |||
| 3352 | Py_DECREF(name)_Py_DECREF(((PyObject*)(name))); | |||
| 3353 | return ret; | |||
| 3354 | } | |||
| 3355 | ||||
| 3356 | static npy_bool | |||
| 3357 | _is_list_of_strings(PyObject *obj) | |||
| 3358 | { | |||
| 3359 | int seqlen, i; | |||
| 3360 | if (!PyList_CheckExact(obj)((((PyObject*)(obj))->ob_type) == &PyList_Type)) { | |||
| 3361 | return NPY_FALSE0; | |||
| 3362 | } | |||
| 3363 | seqlen = PyList_GET_SIZE(obj)(((void) (0)), (((PyVarObject*)(obj))->ob_size)); | |||
| 3364 | for (i = 0; i < seqlen; i++) { | |||
| 3365 | PyObject *item = PyList_GET_ITEM(obj, i)(((PyListObject *)(obj))->ob_item[i]); | |||
| 3366 | if (!PyUnicode_Check(item)((((((PyObject*)(item))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 3367 | return NPY_FALSE0; | |||
| 3368 | } | |||
| 3369 | } | |||
| 3370 | ||||
| 3371 | return NPY_TRUE1; | |||
| 3372 | } | |||
| 3373 | ||||
| 3374 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_Descr * | |||
| 3375 | arraydescr_field_subset_view(PyArray_Descr *self, PyObject *ind) | |||
| 3376 | { | |||
| 3377 | int seqlen, i; | |||
| 3378 | PyObject *fields = NULL((void*)0); | |||
| 3379 | PyObject *names = NULL((void*)0); | |||
| 3380 | PyArray_Descr *view_dtype; | |||
| 3381 | ||||
| 3382 | seqlen = PySequence_Size(ind); | |||
| 3383 | if (seqlen == -1) { | |||
| 3384 | return NULL((void*)0); | |||
| 3385 | } | |||
| 3386 | ||||
| 3387 | fields = PyDict_New(); | |||
| 3388 | if (fields == NULL((void*)0)) { | |||
| 3389 | goto fail; | |||
| 3390 | } | |||
| 3391 | names = PyTuple_New(seqlen); | |||
| 3392 | if (names == NULL((void*)0)) { | |||
| 3393 | goto fail; | |||
| 3394 | } | |||
| 3395 | ||||
| 3396 | for (i = 0; i < seqlen; i++) { | |||
| 3397 | PyObject *name; | |||
| 3398 | PyObject *tup; | |||
| 3399 | ||||
| 3400 | name = PySequence_GetItem(ind, i); | |||
| 3401 | if (name == NULL((void*)0)) { | |||
| 3402 | goto fail; | |||
| 3403 | } | |||
| 3404 | ||||
| 3405 | /* Let the names tuple steal a reference now, so we don't need to | |||
| 3406 | * decref name if an error occurs further on. | |||
| 3407 | */ | |||
| 3408 | PyTuple_SET_ITEM(names, i, name)PyTuple_SetItem(names, i, name); | |||
| 3409 | ||||
| 3410 | tup = PyDict_GetItemWithError(self->fields, name); | |||
| 3411 | if (tup == NULL((void*)0)) { | |||
| 3412 | if (!PyErr_Occurred()) { | |||
| 3413 | PyErr_SetObject(PyExc_KeyError, name); | |||
| 3414 | } | |||
| 3415 | goto fail; | |||
| 3416 | } | |||
| 3417 | ||||
| 3418 | /* disallow use of titles as index */ | |||
| 3419 | if (PyTuple_Size(tup) == 3) { | |||
| 3420 | PyObject *title = PyTuple_GET_ITEM(tup, 2)((((void) (0)), (PyTupleObject *)(tup))->ob_item[2]); | |||
| 3421 | int titlecmp = PyObject_RichCompareBool(title, name, Py_EQ2); | |||
| 3422 | if (titlecmp < 0) { | |||
| 3423 | goto fail; | |||
| 3424 | } | |||
| 3425 | if (titlecmp == 1) { | |||
| 3426 | /* if title == name, we were given a title, not a field name */ | |||
| 3427 | PyErr_SetString(PyExc_KeyError, | |||
| 3428 | "cannot use field titles in multi-field index"); | |||
| 3429 | goto fail; | |||
| 3430 | } | |||
| 3431 | if (PyDict_SetItem(fields, title, tup) < 0) { | |||
| 3432 | goto fail; | |||
| 3433 | } | |||
| 3434 | } | |||
| 3435 | /* disallow duplicate field indices */ | |||
| 3436 | if (PyDict_Contains(fields, name)) { | |||
| 3437 | PyObject *msg = NULL((void*)0); | |||
| 3438 | PyObject *fmt = PyUnicode_FromString( | |||
| 3439 | "duplicate field of name {!r}"); | |||
| 3440 | if (fmt != NULL((void*)0)) { | |||
| 3441 | msg = PyObject_CallMethod_PyObject_CallMethod_SizeT(fmt, "format", "O", name); | |||
| 3442 | Py_DECREF(fmt)_Py_DECREF(((PyObject*)(fmt))); | |||
| 3443 | } | |||
| 3444 | PyErr_SetObject(PyExc_ValueError, msg); | |||
| 3445 | Py_XDECREF(msg)_Py_XDECREF(((PyObject*)(msg))); | |||
| 3446 | goto fail; | |||
| 3447 | } | |||
| 3448 | if (PyDict_SetItem(fields, name, tup) < 0) { | |||
| 3449 | goto fail; | |||
| 3450 | } | |||
| 3451 | } | |||
| 3452 | ||||
| 3453 | view_dtype = PyArray_DescrNewFromType(NPY_VOID); | |||
| 3454 | if (view_dtype == NULL((void*)0)) { | |||
| 3455 | goto fail; | |||
| 3456 | } | |||
| 3457 | view_dtype->elsize = self->elsize; | |||
| 3458 | view_dtype->names = names; | |||
| 3459 | view_dtype->fields = fields; | |||
| 3460 | view_dtype->flags = self->flags; | |||
| 3461 | return view_dtype; | |||
| 3462 | ||||
| 3463 | fail: | |||
| 3464 | Py_XDECREF(fields)_Py_XDECREF(((PyObject*)(fields))); | |||
| 3465 | Py_XDECREF(names)_Py_XDECREF(((PyObject*)(names))); | |||
| 3466 | return NULL((void*)0); | |||
| 3467 | } | |||
| 3468 | ||||
| 3469 | static PyObject * | |||
| 3470 | descr_subscript(PyArray_Descr *self, PyObject *op) | |||
| 3471 | { | |||
| 3472 | if (_check_has_fields(self) < 0) { | |||
| 3473 | return NULL((void*)0); | |||
| 3474 | } | |||
| 3475 | ||||
| 3476 | if (PyUnicode_Check(op)((((((PyObject*)(op))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 3477 | return _subscript_by_name(self, op); | |||
| 3478 | } | |||
| 3479 | else if (_is_list_of_strings(op)) { | |||
| 3480 | return (PyObject *)arraydescr_field_subset_view(self, op); | |||
| 3481 | } | |||
| 3482 | else { | |||
| 3483 | Py_ssize_t i = PyArray_PyIntAsIntp(op); | |||
| 3484 | if (error_converting(i)(((i) == -1) && PyErr_Occurred())) { | |||
| 3485 | /* if converting to an int gives a type error, adjust the message */ | |||
| 3486 | PyObject *err = PyErr_Occurred(); | |||
| 3487 | if (PyErr_GivenExceptionMatches(err, PyExc_TypeError)) { | |||
| 3488 | PyErr_SetString(PyExc_TypeError, | |||
| 3489 | "Field key must be an integer field offset, " | |||
| 3490 | "single field name, or list of field names."); | |||
| 3491 | } | |||
| 3492 | return NULL((void*)0); | |||
| 3493 | } | |||
| 3494 | return _subscript_by_index(self, i); | |||
| 3495 | } | |||
| 3496 | } | |||
| 3497 | ||||
| 3498 | static PySequenceMethods descr_as_sequence = { | |||
| 3499 | (lenfunc) descr_length, /* sq_length */ | |||
| 3500 | (binaryfunc) NULL((void*)0), /* sq_concat */ | |||
| 3501 | (ssizeargfunc) descr_repeat, /* sq_repeat */ | |||
| 3502 | (ssizeargfunc) NULL((void*)0), /* sq_item */ | |||
| 3503 | (ssizessizeargfunc) NULL((void*)0), /* sq_slice */ | |||
| 3504 | (ssizeobjargproc) NULL((void*)0), /* sq_ass_item */ | |||
| 3505 | (ssizessizeobjargproc) NULL((void*)0), /* sq_ass_slice */ | |||
| 3506 | (objobjproc) NULL((void*)0), /* sq_contains */ | |||
| 3507 | (binaryfunc) NULL((void*)0), /* sq_inplace_concat */ | |||
| 3508 | (ssizeargfunc) NULL((void*)0), /* sq_inplace_repeat */ | |||
| 3509 | }; | |||
| 3510 | ||||
| 3511 | static PyMappingMethods descr_as_mapping = { | |||
| 3512 | descr_length, /* mp_length*/ | |||
| 3513 | (binaryfunc)descr_subscript, /* mp_subscript*/ | |||
| 3514 | (objobjargproc)NULL((void*)0), /* mp_ass_subscript*/ | |||
| 3515 | }; | |||
| 3516 | ||||
| 3517 | /****************** End of Mapping Protocol ******************************/ | |||
| 3518 | ||||
| 3519 | ||||
| 3520 | /* | |||
| 3521 | * NOTE: Since this is a MetaClass, the name has Full appended here, the | |||
| 3522 | * correct name of the type is PyArrayDescr_Type. | |||
| 3523 | */ | |||
| 3524 | NPY_NO_EXPORT__attribute__((visibility("hidden"))) PyArray_DTypeMeta PyArrayDescr_TypeFull = { | |||
| 3525 | {{ | |||
| 3526 | /* NULL represents `type`, this is set to DTypeMeta at import time */ | |||
| 3527 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | |||
| 3528 | .tp_name = "numpy.dtype", | |||
| 3529 | .tp_basicsize = sizeof(PyArray_Descr), | |||
| 3530 | .tp_dealloc = (destructor)arraydescr_dealloc, | |||
| 3531 | .tp_repr = (reprfunc)arraydescr_repr, | |||
| 3532 | .tp_as_number = &descr_as_number, | |||
| 3533 | .tp_as_sequence = &descr_as_sequence, | |||
| 3534 | .tp_as_mapping = &descr_as_mapping, | |||
| 3535 | .tp_str = (reprfunc)arraydescr_str, | |||
| 3536 | .tp_flags = Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0) | Py_TPFLAGS_BASETYPE(1UL << 10), | |||
| 3537 | .tp_richcompare = (richcmpfunc)arraydescr_richcompare, | |||
| 3538 | .tp_methods = arraydescr_methods, | |||
| 3539 | .tp_members = arraydescr_members, | |||
| 3540 | .tp_getset = arraydescr_getsets, | |||
| 3541 | .tp_new = arraydescr_new, | |||
| 3542 | },}, | |||
| 3543 | .type_num = -1, | |||
| 3544 | .kind = '\0', | |||
| 3545 | .abstract = 1, | |||
| 3546 | .parametric = 0, | |||
| 3547 | .singleton = 0, | |||
| 3548 | .scalar_type = NULL((void*)0), | |||
| 3549 | }; |
| 1 | #ifndef PyUnicode_FromFormat |
| 2 | struct _object; |
| 3 | typedef struct _object PyObject; |
| 4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
| 5 | PyObject* PyUnicode_FromFormat(const char *format, ...) { |
| 6 | return clang_analyzer_PyObject_New_Reference(); |
| 7 | } |
| 8 | #else |
| 9 | #warning "API PyUnicode_FromFormat is defined as a macro." |
| 10 | #endif |
| 1 | #ifndef PyTuple_SetItem |
| 2 | struct _object; |
| 3 | typedef struct _object PyObject; |
| 4 | void clang_analyzer_PyObject_Steal_Reference(const void *); |
| 5 | int clang_analyzer_noimpl_conjure_int(); |
| 6 | int PyTuple_SetItem(PyObject *p, Py_ssize_t pos, PyObject *o) { |
| 7 | clang_analyzer_PyObject_Steal_Reference(o); |
| 8 | return clang_analyzer_noimpl_conjure_int(); |
| 9 | } |
| 10 | #else |
| 11 | #warning "API PyTuple_SetItem is defined as a macro." |
| 12 | #endif |