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