numpy 2.0.0
src/multiarray/descriptor.c File Reference
#include <Python.h>
#include "structmember.h"
#include "numpy/arrayobject.h"
#include "numpy/arrayscalars.h"
#include "npy_config.h"
#include "numpy/npy_3kcompat.h"
#include "_datetime.h"
#include "common.h"
#include "descriptor.h"

Defines

#define PY_SSIZE_T_CLEAN
#define NPY_NO_DEPRECATED_API
#define _MULTIARRAYMODULE
#define NPY_NO_PREFIX
#define NPY_NEXT_ALIGNED_OFFSET(offset, alignment)   (((offset) + (alignment) - 1) & (-(alignment)))
#define _chk_byteorder(arg)
#define _ARGSTR_   "(icOOOiiiO)"
#define _ARGSTR_   "(icOOOiii)"
#define _ARGSTR_   "(icOOOii)"
#define _ARGSTR_   "(icOOii)"
#define _ARGSTR_   "(cOOii)"

Functions

static PyArray_Descr_use_inherit (PyArray_Descr *type, PyObject *newobj, int *errflag)
NPY_NO_EXPORT PyArray_Descr_arraydescr_fromobj (PyObject *obj)
NPY_NO_EXPORT PyObject * array_set_typeDict (PyObject *NPY_UNUSED(ignored), PyObject *args)
static int _check_for_commastring (char *type, Py_ssize_t len)
static int is_datetime_typestr (char *type, Py_ssize_t len)
static PyArray_Descr_convert_from_tuple (PyObject *obj)
static PyArray_Descr_convert_from_array_descr (PyObject *obj, int align)
static PyArray_Descr_convert_from_list (PyObject *obj, int align)
static PyArray_Descr_convert_from_commastring (PyObject *obj, int align)
static int _is_tuple_of_integers (PyObject *obj)
static int validate_object_field_overlap (PyArray_Descr *dtype)
static PyArray_Descr_use_fields_dict (PyObject *obj, int align)
static PyArray_Descr_convert_from_dict (PyObject *obj, int align)
NPY_NO_EXPORT PyArray_DescrPyArray_DescrNewFromType (int type_num)
NPY_NO_EXPORT int PyArray_DescrConverter2 (PyObject *obj, PyArray_Descr **at)
NPY_NO_EXPORT int PyArray_DescrConverter (PyObject *obj, PyArray_Descr **at)
NPY_NO_EXPORT PyArray_DescrPyArray_DescrNew (PyArray_Descr *base)
static void arraydescr_dealloc (PyArray_Descr *self)
static PyObject * arraydescr_subdescr_get (PyArray_Descr *self)
NPY_NO_EXPORT PyObject * arraydescr_protocol_typestr_get (PyArray_Descr *self)
static PyObject * arraydescr_typename_get (PyArray_Descr *self)
static PyObject * arraydescr_base_get (PyArray_Descr *self)
static PyObject * arraydescr_shape_get (PyArray_Descr *self)
NPY_NO_EXPORT PyObject * arraydescr_protocol_descr_get (PyArray_Descr *self)
static PyObject * arraydescr_isbuiltin_get (PyArray_Descr *self)
static int _arraydescr_isnative (PyArray_Descr *self)
static PyObject * arraydescr_isnative_get (PyArray_Descr *self)
static PyObject * arraydescr_isalignedstruct_get (PyArray_Descr *self)
static PyObject * arraydescr_fields_get (PyArray_Descr *self)
static PyObject * arraydescr_metadata_get (PyArray_Descr *self)
static PyObject * arraydescr_hasobject_get (PyArray_Descr *self)
static PyObject * arraydescr_names_get (PyArray_Descr *self)
static int arraydescr_names_set (PyArray_Descr *self, PyObject *val)
static int _invalid_metadata_check (PyObject *metadata)
static PyObject * arraydescr_new (PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *kwds)
static PyObject * _get_pickleabletype_from_datetime_metadata (PyArray_Descr *dtype)
static PyObject * arraydescr_reduce (PyArray_Descr *self, PyObject *NPY_UNUSED(args))
static int _descr_find_object (PyArray_Descr *self)
static PyObject * arraydescr_setstate (PyArray_Descr *self, PyObject *args)
NPY_NO_EXPORT int PyArray_DescrAlignConverter (PyObject *obj, PyArray_Descr **at)
NPY_NO_EXPORT int PyArray_DescrAlignConverter2 (PyObject *obj, PyArray_Descr **at)
NPY_NO_EXPORT PyArray_DescrPyArray_DescrNewByteorder (PyArray_Descr *self, char newendian)
static PyObject * arraydescr_newbyteorder (PyArray_Descr *self, PyObject *args)
static int is_dtype_struct_simple_unaligned_layout (PyArray_Descr *dtype)
static PyObject * arraydescr_struct_list_str (PyArray_Descr *dtype)
static PyObject * arraydescr_struct_dict_str (PyArray_Descr *dtype)
static PyObject * arraydescr_struct_str (PyArray_Descr *dtype)
static PyObject * arraydescr_subarray_str (PyArray_Descr *dtype)
static PyObject * arraydescr_str (PyArray_Descr *dtype)
static PyObject * arraydescr_struct_repr (PyArray_Descr *dtype)
NPY_NO_EXPORT PyObject * arraydescr_short_construction_repr (PyArray_Descr *dtype)
static PyObject * arraydescr_repr (PyArray_Descr *dtype)
static PyObject * arraydescr_richcompare (PyArray_Descr *self, PyObject *other, int cmp_op)
static Py_ssize_t descr_length (PyObject *self0)
static PyObject * descr_repeat (PyObject *self, Py_ssize_t length)
static PyObject * descr_subscript (PyArray_Descr *self, PyObject *op)

Variables

static PyObject * typeDict = NULL
static PyMemberDef arraydescr_members []
static PyGetSetDef arraydescr_getsets []
static PyMethodDef arraydescr_methods []
static PySequenceMethods descr_as_sequence
static PyMappingMethods descr_as_mapping
NPY_NO_EXPORT PyTypeObject PyArrayDescr_Type

Define Documentation

#define _ARGSTR_   "(icOOOiiiO)"
#define _ARGSTR_   "(cOOii)"
#define _ARGSTR_   "(icOOOiii)"
#define _ARGSTR_   "(icOOOii)"
#define _ARGSTR_   "(icOOii)"
#define _chk_byteorder (   arg)
Value:
(arg == '>' || arg == '<' ||        \
                             arg == '|' || arg == '=')
#define _MULTIARRAYMODULE
#define NPY_NEXT_ALIGNED_OFFSET (   offset,
  alignment 
)    (((offset) + (alignment) - 1) & (-(alignment)))
offset: A starting offset. alignment: A power-of-two alignment.
This macro returns the smallest value >= 'offset' that is divisible by 'alignment'. Because 'alignment' is a power of two and integers are twos-complement, it is possible to use some simple bit-fiddling to do this.
#define NPY_NO_DEPRECATED_API
#define NPY_NO_PREFIX
#define PY_SSIZE_T_CLEAN

Function Documentation

NPY_NO_EXPORT PyArray_Descr* _arraydescr_fromobj ( PyObject *  obj)

Understand basic ctypes
derived type
Understand ctypes structures --
bit-fields are not supported automatically aligns

static int _check_for_commastring ( char *  type,
Py_ssize_t  len 
) [static]

Check for ints at start of string
Check for empty tuple
Check for presence of commas

static PyArray_Descr* _convert_from_array_descr ( PyObject *  obj,
int  align 
) [static]
obj is a list. Each item is a tuple with
(field-name, data-type (either a list or a string), and an optional shape parameter).
field-name can be a string or a 2-tuple data-type can now be a list, string, or 2-tuple (string, metadata dictionary))

Insert name into nameslist
Process rest
Title can be "meta-data". Only insert it into the fields dictionary if it is a string and if it is not the same as the name.
Structured arrays get a sticky aligned bit

static PyArray_Descr* _convert_from_commastring ( PyObject *  obj,
int  align 
) [static]
comma-separated string this is the format developed by the numarray records module and implemented by the format parser in that module this is an alternative implementation found in the _internal.py file patterned after that one -- the approach is to try to convert to a list (with tuples if any repeat information is present) and then call the _convert_from_list)

References _is_tuple_of_integers(), _PyArray_Descr::elsize, _PyArray_Descr::fields, _PyArray_Descr::flags, _PyArray_Descr::names, PyArray_DescrConverter(), PyArray_DescrNew(), PyArray_IsScalar, and PyDataType_HASFIELDS.

static PyArray_Descr* _convert_from_dict ( PyObject *  obj,
int  align 
) [static]

Build item to insert (descr, offset, [title])
Flag whether the fields are specified out of order
If align=True, enforce field alignment
Insert into dictionary
If the fields weren't in order, and there was an OBJECT type, need to verify that no OBJECT types overlap with something else.
Structured arrays get a sticky aligned bit
Override the itemsize if provided
Make sure the itemsize isn't made too small
If align is set, make sure the alignment divides into the size
Set the itemsize
Add the metadata if provided

static PyArray_Descr* _convert_from_list ( PyObject *  obj,
int  align 
) [static]
a list specifying a data-type can just be a list of formats. The names for the fields will default to f0, f1, f2, and so forth.

Ignore any empty string at end which _internal._commastring can produce
End ignore code.
Structured arrays get a sticky aligned bit

static PyArray_Descr* _convert_from_tuple ( PyObject *  obj) [static]

try to interpret next item as a type
We get here if res was NULL but errflag wasn't set --- i.e. the conversion to a data-descr failed in _use_inherit
interpret next item as a typesize
Assume it's a metadata dictionary
interpret next item as shape (if it's a tuple) and reset the type to PyArray_VOID with a new fields attribute.
If (type, 1) was given, it is equivalent to type... or (type, ()) was given it is equivalent to type...
Force subarray->shape to always be a tuple

References _PyArray_Descr::elsize, error_converting, PyArray_DESCR_REPLACE, PyArray_PyIntAsInt(), PyArray_UNICODE, and _PyArray_Descr::type_num.

static int _descr_find_object ( PyArray_Descr self) [static]
returns 1 if this data-type has an object portion used when setting the state because hasobject is not stored.
static PyObject* _get_pickleabletype_from_datetime_metadata ( PyArray_Descr dtype) [static]
Return a tuple of (cleaned metadata dictionary, tuple with (str, num))

Create the 2-item tuple to return
Make a cleaned copy of the metadata dictionary
Convert the datetime metadata into a tuple

static int _invalid_metadata_check ( PyObject *  metadata) [static]

borrowed reference

References PyArray_IsNativeByteOrder.

static int _is_tuple_of_integers ( PyObject *  obj) [static]
static PyArray_Descr* _use_fields_dict ( PyObject *  obj,
int  align 
) [static]
a dictionary specifying a data-type must have at least two and up to four keys These must all be sequences of the same length.
can also have an additional key called "metadata" which can be any dictionary
"names" --- field names "formats" --- the data-type descriptors for the field.
Optional:
"offsets" --- integers indicating the offset into the record of the start of the field. if not given, then "consecutive offsets" will be assumed and placed in the dictionary.
"titles" --- Allows the use of an additional key for the fields dictionary.(if these are strings or unicode objects) or this can also be meta-data to be passed around with the field description.
Attribute-lookup-based field names merely has to query the fields dictionary of the data-descriptor. Any result present can be used to return the correct field.
So, the notion of what is a name and what is a title is really quite arbitrary.
What does distinguish a title, however, is that if it is not None, it will be placed at the end of the tuple inserted into the fields dictionary.and can therefore be used to carry meta-data around.
If the dictionary does not have "names" and "formats" entries, then it will be checked for conformity and used directly.
static PyArray_Descr * _use_inherit ( PyArray_Descr type,
PyObject *  newobj,
int *  errflag 
) [static]
A tuple type would be either (generic typeobject, typesize) or (fixed-length data-type, shape)
or (inheriting data-type, new-data-type) The new data-type must have the same itemsize as the inheriting data-type unless the latter is 0
Thus (int32, {'real':(int16,0),'imag',(int16,2)})
is one way to specify a descriptor that will give a['real'] and a['imag'] to an int32 array.
leave type reference alone

References PyDataType_REFCHK.

NPY_NO_EXPORT PyObject* array_set_typeDict ( PyObject *  NPY_UNUSEDignored,
PyObject *  args 
)

Decrement old reference (if any)
Create an internal reference to it

static PyObject* arraydescr_base_get ( PyArray_Descr self) [static]

References PyDataType_HASFIELDS.

Referenced by _arraydescr_isnative().

static void arraydescr_dealloc ( PyArray_Descr self) [static]
should never be called for builtin-types unless there is a reference-count problem
static PyObject* arraydescr_fields_get ( PyArray_Descr self) [static]

Referenced by _arraydescr_isnative().

static PyObject* arraydescr_hasobject_get ( PyArray_Descr self) [static]
static PyObject* arraydescr_isalignedstruct_get ( PyArray_Descr self) [static]

Referenced by _arraydescr_isnative().

static PyObject* arraydescr_isbuiltin_get ( PyArray_Descr self) [static]
returns 1 for a builtin type and 2 for a user-defined data-type descriptor return 0 if neither (i.e. it's a copy of one)

Referenced by _arraydescr_isnative().

static PyObject* arraydescr_isnative_get ( PyArray_Descr self) [static]
return Py_True if this data-type descriptor has native byteorder if no fields are defined
or if all sub-fields have native-byteorder if fields are defined

References arraydescr_names_get(), and arraydescr_names_set().

Referenced by _arraydescr_isnative().

static PyObject* arraydescr_metadata_get ( PyArray_Descr self) [static]

Referenced by _arraydescr_isnative().

static PyObject* arraydescr_names_get ( PyArray_Descr self) [static]

Referenced by arraydescr_isnative_get().

static int arraydescr_names_set ( PyArray_Descr self,
PyObject *  val 
) [static]

Make sure all entries are strings
Update dictionary keys in fields
Borrowed references to item and new_key
Check for duplicates
Replace names
Replace fields

Referenced by arraydescr_isnative_get().

static PyObject* arraydescr_new ( PyTypeObject *  NPY_UNUSEDsubtype,
PyObject *  args,
PyObject *  kwds 
) [static]

Get a new copy of it unless it's already a copy
We need to be sure to make a new copy of the data-type and any underlying dictionary
Make a copy of the metadata before merging with the input metadata so that this data-type descriptor has it's own copy
Save a reference
Decrement the old reference
Update conv->metadata with anything new in metadata keyword, but do not over-write anything already there
Make a copy of the input dictionary

static PyObject* arraydescr_newbyteorder ( PyArray_Descr self,
PyObject *  args 
) [static]
NPY_NO_EXPORT PyObject* arraydescr_protocol_descr_get ( PyArray_Descr self)
NPY_NO_EXPORT PyObject* arraydescr_protocol_typestr_get ( PyArray_Descr self)
static PyObject* arraydescr_reduce ( PyArray_Descr self,
PyObject *  NPY_UNUSEDargs 
) [static]
return a tuple of (callable object, args, state).

TODO: This method needs to change so that unpickling doesn't
use __setstate__. This is required for the dtype to be an immutable object.

version number of this pickle type. Increment if we need to change the format. Be sure to handle the old versions in arraydescr_setstate.
Now return the state which is at least byteorder, subarray, and fields
Handle CObject in NPY_METADATA_DTSTR key separately
newobj is a tuple of cleaned metadata dictionary and tuple of date_time info (str, num)

<

Use version 3 pickle format
for extended types it also includes elsize and alignment

static PyObject* arraydescr_repr ( PyArray_Descr dtype) [static]
The general dtype repr function.
static PyObject* arraydescr_richcompare ( PyArray_Descr self,
PyObject *  other,
int  cmp_op 
) [static]
static PyObject* arraydescr_setstate ( PyArray_Descr self,
PyObject *  args 
) [static]
state is at least byteorder, subarray, and fields but could include elsize and alignment for EXTENDED arrays

raise an error
If we ever need another pickle format, increment the version number. But we should still be able to handle the old versions.
Ensure that subarray[0] is an ArrayDescr and that subarray_shape obtained from subarray[1] is a tuple of integers.
We have a borrowed reference to metadata so no need to alter reference count

static PyObject* arraydescr_shape_get ( PyArray_Descr self) [static]

TODO
self->subarray->shape should always be a tuple, so this check should be unnecessary

References DEPRECATE, and PyDataType_HASFIELDS.

Referenced by _arraydescr_isnative().

NPY_NO_EXPORT PyObject* arraydescr_short_construction_repr ( PyArray_Descr dtype)
This creates a shorter repr using 'kind' and 'itemsize', instead of the longer type name. This is the object passed as the first parameter to the dtype constructor, and if no additional constructor parameters are given, will reproduce the exact memory layout.
This does not preserve the 'align=True' parameter or sticky NPY_ALIGNED_STRUCT flag for struct arrays like the regular repr does, because the 'align' flag is not part of first dtype constructor parameter.

Normalize byteorder to '<' or '>'
Handle booleans, numbers, and custom dtypes
All the rest which don't fit in the same pattern
The object reference may be different sizes on different platforms, so it should never include the itemsize here.

References descr_length(), and descr_subscript().

static PyObject* arraydescr_str ( PyArray_Descr dtype) [static]
static PyObject* arraydescr_struct_dict_str ( PyArray_Descr dtype) [static]
Returns a string representation of a structured array, in a dict format.

Build up a string to make the dictionary
First, the names
Second, the formats
Check for whether to do titles as well
Third, the offsets
Fourth, the titles
Finally, the itemsize

References arraydescr_str(), arraydescr_struct_repr(), PyDataType_HASFIELDS, PyDataType_HASSUBARRAY, PyUString_Concat, PyUString_ConcatAndDel, and PyUString_FromString.

Referenced by arraydescr_newbyteorder().

static PyObject* arraydescr_struct_list_str ( PyArray_Descr dtype) [static]
Returns a string representation of a structured array, in a list format.

Build up a string to make the list
Go through all the names
Check for whether to do titles as well
Special case subarray handling here

References PyUString_FromString.

Referenced by arraydescr_newbyteorder().

static PyObject* arraydescr_struct_repr ( PyArray_Descr dtype) [static]
The dtype repr function specifically for structured arrays.

If it's an aligned structure, add the align=True parameter

Referenced by arraydescr_struct_dict_str().

static PyObject* arraydescr_struct_str ( PyArray_Descr dtype) [static]
Produces a string representation for a structured dtype

References INTP_FMT.

static PyObject* arraydescr_subarray_str ( PyArray_Descr dtype) [static]
Produces a string representation for a subarray dtype

References arraydescr_str(), PyBytes_AsString, and PyDataType_HASFIELDS.

static PyObject* arraydescr_subdescr_get ( PyArray_Descr self) [static]

Referenced by _arraydescr_isnative().

static PyObject* arraydescr_typename_get ( PyArray_Descr self) [static]

fixme: not reentrant

References _arraydescr_isnative().

Referenced by _arraydescr_isnative().

static Py_ssize_t descr_length ( PyObject *  self0) [static]

*********** Implement Mapping Protocol ***********************

System Message: WARNING/2 (<string>, line 1)
Title overline too short.

   Implement Mapping Protocol ***************************
 

Referenced by arraydescr_short_construction_repr().

static PyObject* descr_repeat ( PyObject *  self,
Py_ssize_t  length 
) [static]
static PyObject* descr_subscript ( PyArray_Descr self,
PyObject *  op 
) [static]
static int is_datetime_typestr ( char *  type,
Py_ssize_t  len 
) [static]
static int is_dtype_struct_simple_unaligned_layout ( PyArray_Descr dtype) [static]
Checks whether the structured data type in 'dtype' has a simple layout, where all the fields are in order, and follow each other with no alignment padding.
When this returns true, the dtype can be reconstructed from a list of the field names and dtypes with no additional dtype parameters.
Returns 1 if it has a simple layout, 0 otherwise.

Get some properties from the dtype
Start at offset zero
If this field doesn't follow the pattern, not a simple layout
Get the next offset
If the itemsize doesn't match the final offset, it's not a simple layout.
It's a simple layout, since all the above tests passed

Referenced by arraydescr_newbyteorder().

NPY_NO_EXPORT int PyArray_DescrAlignConverter ( PyObject *  obj,
PyArray_Descr **  at 
)
Get type-descriptor from an object forcing alignment if possible

None goes to DEFAULT type.

any object with the .fields attribute and/or .itemsize attribute (if the

.fields attribute does not give the total size -- i.e. a partial record

naming). If itemsize is given it must be >= size computed from fields

The .fields attribute must return a convertible dictionary if present. Result inherits from PyArray_VOID.

NPY_NO_EXPORT int PyArray_DescrAlignConverter2 ( PyObject *  obj,
PyArray_Descr **  at 
)
Get type-descriptor from an object forcing alignment if possible
None goes to NULL.
NPY_NO_EXPORT int PyArray_DescrConverter ( PyObject *  obj,
PyArray_Descr **  at 
)
Get typenum from an object -- None goes to NPY_DEFAULT_TYPE

This function takes a Python object representing a type and converts it to a the correct PyArray_Descr * structure to describe the type.

Many objects can be used to represent a data-type which in NumPy is quite a flexible concept.

This is the central code that converts Python objects to Type-descriptor objects that are used throughout numpy.

Returns a new reference in *at, but the returned should not be modified as it may be one of the canonical immutable objects or a reference to the input obj.

System Message: WARNING/2 (<string>, line 11); backlink Inline emphasis start-string without end-string.

default
or a typecode string
Allow unicode format strings: convert to bytes
Check for a string typecode.
Empty string is invalid
check for commas present or first (or second) element a digit
Process the endian character
Just an endian character is invalid
Check for datetime format
A typecode like 'd'
A kind + size like 'f8'
Parse the integer, make sure it's the rest of the string
When specifying length of UNICODE the number of characters is given to match the STRING interface. Each character can be more than one byte and itemsize must be the number of bytes.
Support for generic processing c8, i4, f8, etc...
or a tuple
or a list
or a dictionary
Now check to see if the object is registered in typeDict

Referenced by _convert_from_commastring(), array_nbytes_get(), and PyArray_DescrConverter2().

NPY_NO_EXPORT int PyArray_DescrConverter2 ( PyObject *  obj,
PyArray_Descr **  at 
)
Get typenum from an object -- None goes to NULL

References PY_FAIL, and PyArray_DescrConverter().

Referenced by array__get_ndarray_c_version(), and array_cumsum().

NPY_NO_EXPORT PyArray_Descr* PyArray_DescrNew ( PyArray_Descr base)
Array Descr Objects for dynamic types *
There are some statically-defined PyArray_Descr objects corresponding to the basic built-in types. These can and should be DECREF'd and INCREF'd as appropriate, anyway. If a mistake is made in reference counting, deallocation on these builtins will be attempted leading to problems.
This let's us deal with all PyArray_Descr objects using reference counting (regardless of whether they are statically or dynamically allocated).
base cannot be NULL

Don't copy PyObject_HEAD part

Referenced by _convert_from_commastring(), and array_base_get().

NPY_NO_EXPORT PyArray_Descr* PyArray_DescrNewByteorder ( PyArray_Descr self,
char  newendian 
)
returns a copy of the PyArray_Descr structure with the byteorder

altered: no arguments: The byteorder is swapped (in all subfields as well) single argument: The byteorder is forced to the given state (in all subfields as well)

Valid states: ('big', '>') or ('little' or '<') ('native', or '=')

If a descr structure with | is encountered it's own byte-order is not changed but any fields are:

Deep bytorder change of a data-type descriptor * Leaves reference count of self unchanged --- does not DECREF self *

swap byteorder
make new dictionary with replaced PyArray_Descr Objects

Referenced by npyiter_apply_forced_iteration_order().

NPY_NO_EXPORT PyArray_Descr* PyArray_DescrNewFromType ( int  type_num)
static int validate_object_field_overlap ( PyArray_Descr dtype) [static]
Validates that any field of the structured array 'dtype' which has the NPY_ITEM_HASOBJECT flag set does not overlap with another field.
This algorithm is worst case O(n^2). It could be done with a sort and sweep algorithm, but the structured dtype representation is rather ugly right now, so writing something better can wait until that representation is made sane.
Returns 0 on success, -1 if an exception is raised.

Get some properties from the dtype
If this field has objects, check for overlaps
Raise an exception if it overlaps
It passed all the overlap tests


Variable Documentation

PyGetSetDef arraydescr_getsets[] [static]
PyMemberDef arraydescr_members[] [static]
Initial value:
 {
    {"type",
        T_OBJECT, offsetof(PyArray_Descr, typeobj), READONLY, NULL},
    {"kind",
        T_CHAR, offsetof(PyArray_Descr, kind), READONLY, NULL},
    {"char",
        T_CHAR, offsetof(PyArray_Descr, type), READONLY, NULL},
    {"num",
        T_INT, offsetof(PyArray_Descr, type_num), READONLY, NULL},
    {"byteorder",
        T_CHAR, offsetof(PyArray_Descr, byteorder), READONLY, NULL},
    {"itemsize",
        T_INT, offsetof(PyArray_Descr, elsize), READONLY, NULL},
    {"alignment",
        T_INT, offsetof(PyArray_Descr, alignment), READONLY, NULL},
    {"flags",
        T_INT, offsetof(PyArray_Descr, flags), READONLY, NULL},
    {NULL, 0, 0, 0, NULL},
}
we need to be careful about setting attributes because these objects are pointed to by arrays that depend on them for interpreting data. Currently no attributes of data-type objects can be set directly except names.
PyMethodDef arraydescr_methods[] [static]
Initial value:
 {
    
    {"__reduce__",
        (PyCFunction)arraydescr_reduce,
        METH_VARARGS, NULL},
    {"__setstate__",
        (PyCFunction)arraydescr_setstate,
        METH_VARARGS, NULL},
    {"newbyteorder",
        (PyCFunction)arraydescr_newbyteorder,
        METH_VARARGS, NULL},
    {NULL, NULL, 0, NULL}           
}
PyMappingMethods descr_as_mapping [static]
Initial value:
 {
    descr_length,                                
    (binaryfunc)descr_subscript,                 
    (objobjargproc)NULL,                         
}
PySequenceMethods descr_as_sequence [static]
Initial value:
 {
    descr_length,
    (binaryfunc)NULL,
    descr_repeat,
    NULL, NULL,
    NULL,                                        
    NULL,                                        
    0,                                           
    0,                                           
    0,                                           
}
NPY_NO_EXPORT PyTypeObject PyArrayDescr_Type
************ End of Mapping Protocol *************************

Referenced by OBJECT_fill().

PyObject* typeDict = NULL [static]
Must be explicitly loaded